快手笔试题 JAVA_快手笔试题

1. 蓄水池问题

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

import java.util.*;/***@authorzzm

* @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 classKSwaterPool {statictree[] trees;public static voidmain(String[] args) {

Scanner scanner= newScanner(System.in);int n =scanner.nextInt();

trees= new tree[n+1];for (int i = 1; i <= n; i++) trees[i] = newtree();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(intt) {

tree tree=trees[t];if (!tree.hasWater) {

tree.hasWater= true;for (inta : tree.chile) full(a);

}

}private static void poll(intt) {

tree tree=trees[t];if(tree.hasWater) {

tree.hasWater= false;for (inta : tree.father) poll(a);

}

}

}classtree {

Listfather;

Listchile;booleanhasWater;

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

hasWater= false;

}

}

2. 全班最大考试成绩

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

import java.util.*;/***@authorzzm

* @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 classKSexam {public static voidmain(String[] args) {

Scanner scanner= newScanner(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.*;/***@authorzzm

* @data 2020/5/22 8:29

* 给定一个数组,每个元素范围是0~K(K < 整数最大值2^32),将该数组分成两部分,使得 |S1- S2|最小,其中S1和S2分别是数组两部分的元素之和。*/

public classMain {static int min =Integer.MAX_VALUE;public static voidmain(String[] args) {

Scanner scanner= newScanner(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, intindex) {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[] maps = new HashMap[n]; maps 记录当前位置数为结尾的 所有等差数列的最大长度

注意:Arrays.fill(maps, new HashMap<>())  会给数组填充同一个  map!!

import java.util.*;/***@authorzzm

* @data 2020/5/22 9:03

* 给定一个未排序数组,找出其中最长的等差数列(无需保证数字顺序)。*/

public classMain {public static voidmain(String[] args) {

Scanner scanner= newScanner(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[] maps = newHashMap[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.*;/***@authorzzm

* @data 2020/5/22 11:29*/

public classMain {public static voidmain(String[] args) {

Scanner scanner= newScanner(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");

}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值