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");
}
}