2020春招 笔试总结

202 阅读6分钟

个人情况

双非大三菜鸡,自己最近也参加了好多实习笔试,很多都没过,所以开个帖子来记录自己做过的笔试,复盘一下。

持续更新

4/8 微众银行笔试

  1. 大致是n个朋友m个礼物,要求均分礼物,
  • 可以花a元送红包打发走一位朋友;
  • 花b元再买一件礼物,两种操作可以混着用,要求输出打发所有朋友的最小花费。
import java.util.Scanner;

/**
 * @author Pan梓涵
 * @date 2020/4/22 17:22
 */
public class DivideGift {

    /**
     * 微众 第 1 题,最小花费问题
     */
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt(); // n个小朋友
        int m = sc.nextInt(); // m份礼物
        int a = sc.nextInt(); // 每个红包的花费
        int b = sc.nextInt(); // 每个礼物的价值
        sc.close();
        System.out.println(minCost(n, m, a, b));
    }

    private static int minCost(int n, int m, int a, int b) {
        if (n > m) {
            // 如果小朋友的个数n > 礼物数m
            // 此时可以花(n-m)份礼物钱或红包钱给小朋友,取决于礼物钱小还是红包钱小
            return (n - m) * Math.min(a, b);
        } else if (n % m == 0) {
            // 刚好分完
            return 0;
        } else {
            // 其他情况,当人数小于礼物数,且不能完全均分
            // n: 总小朋友数 m:总礼物数 x:离开多少人 y:买多少礼物
            // 方程1: k * (n - x) = m + y
            // 方程2: minCost = x * a + y * b
            int minCost = Integer.MAX_VALUE;
            // n-1,只留下一个小朋友,把所有的礼物送给他
            for(int redPacketNum = 0; redPacketNum < n; redPacketNum++) {
                if(m % (n - redPacketNum) == 0) {
                    minCost = Math.min(minCost, redPacketNum * a);
                } else {
                    int nowPerson = n - redPacketNum;
                    int buyGiftNum = nowPerson - (m % nowPerson);
                    minCost = Math.min(minCost, redPacketNum * a + buyGiftNum * b);
                }
            }
            return minCost;
        }
    }
}
  1. 游戏问题

import java.util.Scanner;

/**
 * @author Pan梓涵
 * @date 2020/4/22 17:48
 */
public class WhoWin {
    /**
     * 微众 第 2 题,先手博弈问题
     */
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int t = Integer.parseInt(sc.nextLine());
        for (int i = 0; i < t; i++) {
            String str = sc.nextLine();
            System.out.println(whoWin(str));
        }
        sc.close();
    }

    private static String whoWin(String str) {
        String p1 = "Cassidy", p2 = "Eleanore"; // p1先手
        // 判断奇数次字符的个数
        // 若该个数为 奇数次,则无论如何都是 Cassidy 赢;
        // 若该个数为 偶数次,则无论如何都是 Eleanore 赢
        return ((oddCharNum(str) & 1) != 0) ? p1 : p2;
    }

    // 判断一个字符串的出现奇数次字符的个数
    private static int oddCharNum(String str) {
        int[] arr = new int[26];
        for (int i = 0; i < str.length(); i++) {
            arr[str.charAt(i) - 'a'] += 1;
        }
        int oddNum = 0; // 奇数次字符的个数
        for (int num : arr) {
            if ((num & 1) != 0) {
                oddNum++; // 该字符出现了奇次
            }
        }
        return oddNum;
    }
}

  1. 抽卡游戏
import java.util.Arrays;
import java.util.Scanner;

/**
 * @author Pan梓涵
 * @date 2020/4/22 17:52
 */
public class YouXi {

    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int n = in.nextInt();
        int[][] src = new int[n][2];
        for(int i = 0; i < n; i++) {
            src[i][0] = in.nextInt();
            src[i][1] = in.nextInt();
        }
        System.out.println(youXi(src));
    }

    // 贪心方法,先按抽卡次数降序,抽次次数相同,钱数降序
    private static int youXi(int[][] src) {
        // 下标:0是钱数 1是抽卡次数
        Arrays.sort(src, (o1, o2) -> o1[1] == o2[1] ? o2[0] - o1[0] : o2[1] - o1[1]);
        int maxMoney = 0;
        int count = 1;
        for (int[] ints : src) {
            maxMoney += ints[0];
            count += ints[1] - 1;
            if(count == 0) break;
        }
        return maxMoney;
    }
}

4/11 网易互娱笔试

  1. 给两个字符串形式储存的九进制数(可能包括小数部分), 求两数之和, 用字符串形式输出

思路:

  • 先找出每个数中,小数点的位置
  • 对两个字符串进行预处理,对齐数位,不够的补零(代码比较丑陋,但能AC)
  • 执行相加
public class Add {
    /**
     * 接收两个表示9进制数的字符串,返回表示它们相加后的9进制数的字符串
     *
     * @param num1 string字符串 第一个加数
     * @param num2 string字符串 第二个加数
     * @return string字符串
     */
    public String add(String num1, String num2) {
        // write code here
        // "1.28","1.71" 和"3.10"
        // "25","15" 和"41"
        if (num1 == null || num2 == null) return null;
        String[] strings = preStrs(num1, num2);
        StringBuilder sb = new StringBuilder();
        num1 = strings[0];
        num2 = strings[1];
        int i1 = num1.length() - 1, i2 = num2.length() - 1;
        int carry = 0;
        while (i1 >= 0 || i2 >= 0) {
            boolean flag = false; // 标志是否遇到"."
            if (i1 >= 0) {
                char cur = num1.charAt(i1);
                if (cur == '.') flag = true;
                else carry += cur - '0';
                i1--;
            }
            if (i2 >= 0) {
                char cur = num2.charAt(i2);
                if (cur == '.') flag = true;
                else carry += cur - '0';
                i2--;
            }
            if (flag) {
                sb.append(".");
            } else {
                sb.append(carry % 9);
                carry = carry / 9;
            }
        }
        if (carry != 0) {
            sb.append(carry);
        }
        return sb.reverse().toString();
    }
    // 先找出其中.的下标
    private int findPoint(String str) {
        for (int i = 0; i < str.length(); i++) {
            if (str.charAt(i) == '.') {
                return i;
            }
        }
        return -1;
    }
    // 预处理,对齐数位
    private String[] preStrs(String num1, String num2) {
        int num1PointIdx = findPoint(num1);
        int num2PointIdx = findPoint(num2);
        if (num1PointIdx == -1 && num2PointIdx == -1) {
            return new String[]{num1, num2};
        } else if (num1PointIdx == -1 && num2PointIdx != -1) {
            int append0Nums = num2.length() - num2PointIdx - 1;
            StringBuilder sb = new StringBuilder(num1);
            sb.append(".");
            for (int i = 0; i < append0Nums; i++) sb.append('0');
            return new String[]{sb.toString(), num2};
        } else if (num1PointIdx != -1 && num2PointIdx == -1) {
            int append0Nums = num1.length() - num1PointIdx - 1;
            StringBuilder sb = new StringBuilder(num2);
            sb.append(".");
            for (int i = 0; i < append0Nums; i++) sb.append('0');
            return new String[]{num1, sb.toString()};
        } else {
            int num1Nums = num1.length() - num1PointIdx - 1;
            int num2Nums = num2.length() - num2PointIdx - 1;
            if (num1Nums == num2Nums) return new String[]{num1, num2};
            else if (num1Nums > num2Nums) {
                StringBuilder sb = new StringBuilder(num2);
                for (int i = 0; i < num1Nums - num2Nums; i++) sb.append('0');
                return new String[]{num1, sb.toString()};
            } else {
                StringBuilder sb = new StringBuilder(num1);
                for (int i = 0; i < num2Nums - num1Nums; i++) sb.append('0');
                return new String[]{sb.toString(), num2};
            }
        }
    }
}
  1. 给一个数组W表示n个人的等级,给一个数组T表示n个任务的难度。一个人的等级>=一个任务的难度时, 这个人才能解决这个任务,一个人只能解决一个任务。求解决所有任务的分配人手的方案的总数
import java.util.Arrays;
import java.util.Scanner;
/**
 * 分配任务
 * @author Pan梓涵
 * @date 2020/4/22 11:32
 */
public class AllocatingTask {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int[] w = new int[n];
        int[] t = new int[n];
        for (int i = 0; i < n; i++)
            w[i] = sc.nextInt();
        for (int i = 0; i < n; i++)
            t[i] = sc.nextInt();
        int m = sc.nextInt();
        allocatingTask(n, w, t, m);
    }
    private static void allocatingTask(int n, int[] w, int[] t, int m) {
        if(n == 0) System.out.println(0);
        Arrays.sort(w);
        Arrays.sort(t);
        long res = 1;
        for(int i = 0; i < n; i++) {
            long count = moreThanCount(t, w[i]) - i;
            if(count <= 0) System.out.println(0);
            res = res * count % m;
        }
        System.out.println(res % m);
    }
    private static long moreThanCount(int[] T, int wi) {
        long count = 0;
        for (int t : T) {
            if(wi >= t) {
                count++;
            }
        }
        return count;
    }
}
  1. 第组队
  • 题目都看不太懂,不想做

  1. 整理快递盒

/**
 * @author Pan梓涵
 * @date 2020/4/22 16:39
 */
public class MaxBoxes {
    private static final int DIMENSIONALITY = 3;
    /**
     * [[5,6,3], [5,4,6], [6,6,6]] 1
     *
     * @param boxes int整型二维数组
     * @return int整型
     */
    public int maxBoxes(int[][] boxes) {
        int n = boxes.length;
        // 表示箱子之间的关系,relations[i][j] = 0, 1, -1
        // 0: 表示无法放入, 1: 表示箱子i能放入到箱子j中, -1: 表示箱子j能放入到箱子i中
        int[][] relations = new int[n][n];
        // 表示每个箱子所处的高度 0:表示无法放入其他箱子, 1:表示能放入1个其他箱子
        int[] heights = new int[n];
        // 计算箱子的嵌套关系
        for(int i = 0; i < n; i++) {
            for(int j = 0; j < n; j++) {
                relations[i][j] = nest(boxes, i, j);
            }
        }
        // 递归修改嵌套深度
        for(int i = 0; i < n; i++) {
            for(int j = 0; j < n; j++) {
                if(relations[i][j] == 1) { // 如果i嵌入j
                    addHeight(n, heights, relations, i, j); // 增加j的高度
                }
            }
        }
        int max = 0;
        for (int height : heights) {
            max = Math.max(max, height + 1);
        }
        return max;
    }
    private void addHeight(int n, int[] heights, int[][] relations, int i, int j) {
        if(heights[i] == heights[j]) {
            heights[j]++; // 如果i和j高度相同,同时i又能放入j中,高度+1
        }
        for(int k = 0; k < n; k++) {
            if(relations[j][k] == 1) {
                // 如果j能放入到k中,那么递归调用,增加k的高度
                addHeight(n, heights, relations, j, k);
            }
        }
    }
    // 如果i嵌入j,返回1,如果j嵌入i,返回-1,如无嵌套关系,返回0
    private int nest(int[][] boxes, int i, int j) {
        if(boxes[i][0] < boxes[j][0]) {
            for(int k = 1; k < DIMENSIONALITY; k++) {
                if(boxes[i][k] >= boxes[j][k]) {
                    return 0;
                }
            }
            return 1;
        } else {
            for(int k = 1; k < DIMENSIONALITY; k++) {
                if(boxes[j][k] >= boxes[i][k]) {
                    return 0;
                }
            }
            return -1;
        }
    }
    public static void main(String[] args) {
        MaxBoxes maxBoxes = new MaxBoxes();
        int[][] boxes = {{5, 6, 3}, {5, 4, 6}, {6, 6, 6}};
        int[][] boxes2 = {{5, 4, 3}, {5, 4, 5}, {6, 6, 6}};
        System.out.println(maxBoxes.maxBoxes(boxes));
        System.out.println(maxBoxes.maxBoxes(boxes2));
    }
}