快手笔试题

1. 蓄水池问题

  默认输入 较小的为父水池,较大的为子水池

import java.util.*;

/**
 * @author zzm
 * @data 2020/4/20 23:23
 * 在你面前有n个蓄水池,他们组成了树形结构(由n-1条边连接)。蓄水池节点编号从1开始到n。
 * 对每个蓄水池节点来说,他的儿子蓄水池节点都摆放在他的下面,并且和它用水管相连,根据重力,水会向下流动。现在我们要在蓄水池上做一些操作:
 * 1. 把节点v填满水。然后v的所有儿子节点水也会被填满
 * 2. 清空节点v的水。然后v所有的父亲节点水都会被清空
 * 3. 询问每个蓄水池节点是否有水。
 * 初始状态时候,每个节点都是空的。
 * 现在我们会依次进行一系列操作,我们想提前知道每次操作后的结果,你能帮忙解决吗?
 * 输入描述:
 * 第一行包含一个正整数n(1<=n<=1000),表示蓄水池节点的数量。
 * 后面n-1行,每行有两个数字a[i], b[i]。(1<=a[i], b[i]<= n, a[i]!=b[i])表示蓄水池的连接关系。
 * 接下来的一行包含一个整数q(1<=q<=1000),表示我们要进行的操作的数量。
 * 最后的q行中,每行包含两个数字c[i] (1<=c[i]<=3)和v[i](1<=v[i]<=n)。其中c[i]表示操作类型(1,2或者3)。v[i]表示操作对应的蓄水池节点。
 * 输入数据保证合理,是一个连通的树。
 * 输出描述:
 * 对于每个操作3(c[i] == 3),输出一个数字1或者0。1表示v[i]蓄水池节点有水,0表示没水。
 */
public class KSwaterPool {

    static tree[] trees;

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int n = scanner.nextInt();
        trees = new tree[n+1];
        for (int i = 1; i <= n; i++) trees[i] = new tree();
        for (int i = 0; i < n - 1; i++) {
            int f = scanner.nextInt(), c = scanner.nextInt();
            if(f>c){
                int temp = f;
                f=c;
                c=temp;
            }
            trees[f].chile.add(c);
            trees[c].father.add(f);
        }
        int len = scanner.nextInt();
        for (int i = 0; i < len; i++) {
            int op = scanner.nextInt(), aim = scanner.nextInt();
            //灌满
            if (op == 1) full(aim);
            else if (op == 2) poll(aim);
            else System.out.println(trees[aim].hasWater ? 1 : 0);
        }
    }

    private static void full(int t) {
        tree tree = trees[t];
        if (!tree.hasWater) {
            tree.hasWater = true;
            for (int a : tree.chile) full(a);
        }
    }

    private static void poll(int t) {
        tree tree = trees[t];
        if (tree.hasWater) {
            tree.hasWater = false;
            for (int a : tree.father) poll(a);
        }
    }


}

class tree {
    List<Integer> father;
    List<Integer> chile;
    boolean hasWater;

    tree() {
        this.father = new ArrayList<>();
        this.chile = new ArrayList<>();
        hasWater = false;
    }
}

2. 全班最大考试成绩

  暴力法找每道题目最多的答案

import java.util.*;

/**
 * @author zzm
 * @data 2020/4/20 22:37
 * 现在你的班级刚刚参加了一个只有单选题的考试。班级一共n个学生,考试有m个问题。每个题目都有5个可选答案(A,B,C,D,E)。
 * 并且每个题目只有一个正确答案。每个题目的分数并不一样,第i个题目的分数用a[i]表示。如果题目没答对该题会获得0分。
 * 考试结束后,每个学生都记得自己的答案,但是他们还不知道正确答案是什么。如果非常乐观的考虑,他们班级最多可能得到多少分呢?
 * 输入描述:
 * 第一行包含2个正整数,n和m。(1 <= n, m <= 1000,n是班级中学生数量,m是题目的数量)
 * 下面n行数据每行包含一个string si,表示第i个学生的答案。si的第j个字符表示该学生第j个题目的答案。
 * 输出描述:
 * 一个正整数,全班学生最大的可能获得的分数总和。
 * 输入例子1:
 * 2 4
 * ABCD
 * ABCE
 * 1 2 3 4
 * 输出例子1:
 * 16
 */
public class KSexam {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        String[] mn = scanner.nextLine().split(" ");
        int n = Integer.parseInt(mn[0]);
        int m = Integer.parseInt(mn[1]);

        if (n <= 0 || m <= 0) {
            System.out.println(0);
            return;
        }
        char[][] answers = new char[n][m];
        int[] core = new int[m];

        for (int i = 0; i < n; i++) answers[i] = scanner.nextLine().toCharArray();
        String[] split = scanner.nextLine().split(" ");
        for (int i = 0; i < m; i++) core[i] = Integer.parseInt(split[i]);
        scanner.close();

        int res = 0;
        for (int i = 0; i < m; i++) {
            int[] temp = new int[5];
            int maxIndex = 0;
            for (int j = 0; j < n; j++) temp[answers[j][i] - 'A']++;
            for (int j = 0; j < 5; j++) if (temp[j] > temp[maxIndex]) maxIndex = j;
            res += core[i] * temp[maxIndex];
        }
        System.out.println(res);
    }
}

 3. 将数组分成两部分  使得  两部分和的差的绝对值最小

import java.util.*;

/**
 * @author zzm
 * @data 2020/5/22 8:29
 * 给定一个数组,每个元素范围是0~K(K < 整数最大值2^32),将该数组分成两部分,使得 |S1- S2|最小,其中S1和S2分别是数组两部分的元素之和。
 */
public class Main {
    static int min = Integer.MAX_VALUE;

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int n = scanner.nextInt();
        int[] nums = new int[n];
        int sum = 0;
        for (int i = 0; i < n; i++) {
            nums[i] = scanner.nextInt();
            sum += nums[i];
        }
        scanner.close();
        helper(nums,sum,0,0);
        System.out.println(min);
    }

    private static void helper(int[] nums, int sum, int tempSum, int index) {
        if (index == nums.length) {
            min = Math.min(min, Math.abs(sum - 2 * tempSum));
            return;
        }
        helper(nums, sum, tempSum + nums[index], index + 1);
        helper(nums, sum, tempSum, index + 1);
    }
}

 4. 最长等差数列

思路:

HashMap<Integer, Integer>[] maps = new HashMap[n]; maps 记录当前位置数为结尾的 所有等差数列的最大长度
注意:  Arrays.fill(maps, new HashMap<>())  会给数组填充同一个  map!!
import java.util.*;

/**
 * @author zzm
 * @data 2020/5/22 9:03
 * 给定一个未排序数组,找出其中最长的等差数列(无需保证数字顺序)。
 */
public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int n = scanner.nextInt();
        if (n <= 2) {
            System.out.println(n);
            return;
        }
        int[] nums = new int[n];

        for (int i = 0; i < n; i++) nums[i] = scanner.nextInt();
        scanner.close();

        Arrays.sort(nums);

        int max = 2;
        HashMap<Integer, Integer>[] maps = new HashMap[n];

        for (int j = 0; j < n; j++) {
            maps[j] = new HashMap<>();
            for (int i = 0; i < j; i++) {
                int dif = nums[j] - nums[i];
                Integer len = maps[i].getOrDefault(dif, 1);
                max = Math.max(max,len+1);
                maps[j].put(dif,len+1);
            }
        }
        System.out.println(max);
    }
}

 5. 判断IPV4 和IPV6

编写一个函数来验证输入的字符串是否是有效的 IPv4 或 IPv6 地址

IPv4 地址由十进制数和点来表示,每个地址包含4个十进制数,其范围为 0 - 255, 用(".")分割。比如,172.16.254.1;
同时,IPv4 地址内的数不会以 0 开头。比如,地址 172.16.254.01 是不合法的。

IPv6 地址由8组16进制的数字来表示,每组表示 16 比特。这些组数字通过 (":")分割。比如,  2001:0db8:85a3:0000:0000:8a2e:0370:7334 是一个有效的地址。而且,我们可以加入一些以 0 开头的数字,字母可以使用大写,也可以是小写。所以, 2001:db8:85a3:0:0:8A2E:0370:7334 也是一个有效的 IPv6 address地址 (即,忽略 0 开头,忽略大小写)。

然而,我们不能因为某个组的值为 0,而使用一个空的组,以至于出现 (::) 的情况。 比如, 2001:0db8:85a3::8A2E:0370:7334 是无效的 IPv6 地址。
同时,在 IPv6 地址中,多余的 0 也是不被允许的。比如, 02001:0db8:85a3:0000:0000:8a2e:0370:7334 是无效的。

说明: 你可以认为给定的字符串里没有空格或者其他特殊字符。

import java.util.*;

/**
 * @author zzm
 * @data 2020/5/22 11:29
 */
public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        String s = scanner.nextLine();
        scanner.close();

        for (int k = 0; k < 1; k++) {
            if (s.contains(".")) {
                String[] split = s.split("\\.");
//                System.out.println(split.length);
                if (split.length != 4) break;
                int i = 0;
                for (; i < 4; i++) {
                    String str = split[i];
                    if (str.equals("0") || (!str.startsWith("0"))) {
                        int n = Integer.parseInt(str);
                        if (0 <= n && 255 >= n) continue;
                        break;
                    }else break;
                }
                if (i == 4) {
                    System.out.println("IPv4");
                    return;
                }
            } else if (s.contains(":")) {
                String[] split = s.split(":");
                if (split.length != 8) break;
                int i = 0;
                for (; i < 8; i++) {
                    String str = split[i];
                    if(str.equals("0000") || str.equals("000") || str.equals("00")) break;
                }
                if(i==8){
                    System.out.println("IPv6");
                    return;
                }
            }
        }
        System.out.println("Neither");
    }
}

 

posted @ 2020-04-21 00:34  zzmhust  阅读(774)  评论(0)    收藏  举报