Skip to content

Commit dbe806f

Browse files
Default Changelist
1 parent 3a4eb62 commit dbe806f

File tree

10 files changed

+562
-29
lines changed

10 files changed

+562
-29
lines changed

huawei/src/main/java/code/HJ18.java

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
package main.java.code;
2+
3+
import java.io.*;
4+
import java.util.*;
5+
import java.util.stream.Collectors;
6+
7+
public class HJ18 {
8+
/**
9+
* HJ18 识别有效的IP地址和掩码并进行分类统计
10+
* 识别有效的IP地址和掩码并进行分类统计
11+
* 题目描述
12+
* 请解析IP地址和对应的掩码,进行分类识别。要求按照A/B/C/D/E类地址归类,不合法的地址和掩码单独归类。
13+
* 所有的IP地址划分为 A,B,C,D,E五类
14+
* A类地址1.0.0.0~126.255.255.255;
15+
* B类地址128.0.0.0~191.255.255.255;
16+
* C类地址192.0.0.0~223.255.255.255;
17+
* D类地址224.0.0.0~239.255.255.255;
18+
* E类地址240.0.0.0~255.255.255.255
19+
* 私网IP范围是:
20+
* 10.0.0.0~10.255.255.255
21+
* 172.16.0.0~172.31.255.255
22+
* 192.168.0.0~192.168.255.255
23+
* 子网掩码为二进制下前面是连续的1,然后全是0。(例如:255.255.255.32就是一个非法的掩码)
24+
* 注意二进制下全是1或者全是0均为非法
25+
* 注意:
26+
* 1. 类似于【0.*.*.*】和【127.*.*.*】的IP地址不属于上述输入的任意一类,也不属于不合法ip地址,计数时可以忽略
27+
* 2. 私有IP地址和A,B,C,D,E类地址是不冲突的
28+
* 输入描述:
29+
* 多行字符串。每行一个IP地址和掩码,用~隔开。
30+
* 输出描述:
31+
* 统计A、B、C、D、E、错误IP地址或错误掩码、私有IP的个数,之间以空格隔开。
32+
* 示例1
33+
* 输入
34+
* 10.70.44.68~255.254.255.0
35+
* 1.0.0.1~255.0.0.0
36+
* 192.168.0.2~255.255.255.0
37+
* 19..0.~255.255.255.0
38+
* 输出
39+
* 1 0 1 0 0 2 1
40+
*/
41+
public static class Main {
42+
/**
43+
* 该代码在牛客网上通过,在idea中无法运行
44+
* 先判断子网掩码是否正确,方法是将子网掩码转换成32位0/1组成的二进制字符串,那么怎样判断掩码合法呢,只需要判断该二进制中第一个0和最后一个1的位置即可,只要第一个0在的位置比最后一个1的位置较前则掩码非法,反则合法;然后如果掩码合法,接着判断IP是否合法
45+
*/
46+
public static void main(String[] args) {
47+
Scanner sc = new Scanner(System.in);
48+
int isA = 0;
49+
int isB = 0;
50+
int isC = 0;
51+
int isD = 0;
52+
int isE = 0;
53+
int isEroor = 0;
54+
int isPrivate = 0;
55+
while (sc.hasNextLine()) {
56+
String str = sc.nextLine();
57+
String[] ips = str.split("~");
58+
//判断掩码是否合法
59+
boolean isMask = false;
60+
String[] maskArr = ips[1].split("\\.");
61+
StringBuilder binaryMask = new StringBuilder();
62+
//形成掩码二进制字符串
63+
for (String s : maskArr) {
64+
StringBuilder binaryStr = new StringBuilder(Integer.toBinaryString(Integer.parseInt(s)));
65+
//凑成4组8位二进制
66+
for (int j = 0; j < 8 - binaryStr.length(); j++) {
67+
binaryStr.insert(0, "0");
68+
}
69+
binaryMask.append(binaryStr);
70+
}
71+
//比较二进制字符串中第一个0的位置和最后一个1的位置来判断掩码是否合法
72+
isMask = binaryMask.indexOf("0") >= binaryMask.lastIndexOf("1");
73+
//掩码合法后再来判断IP是否合法
74+
if (isMask) {
75+
String[] strArr = ips[0].split("\\.");
76+
if (strArr.length == 4) {
77+
int[] ipArr = new int[4];
78+
for (int i = 0; i < 4; i++) {
79+
if (strArr[i].equals("")) {
80+
ipArr[i] = -1;
81+
} else {
82+
ipArr[i] = Integer.parseInt(strArr[i]);
83+
}
84+
}
85+
if ((0 <= ipArr[0] && ipArr[0] <= 255) && (0 <= ipArr[1] && ipArr[1] <= 255) && (0 <= ipArr[2] && ipArr[2] <= 255) && (0 <= ipArr[3] && ipArr[3] <= 255)) {
86+
if (ipArr[0] >= 1 && ipArr[0] <= 126) {
87+
isA++;
88+
if (ipArr[0] == 10)
89+
isPrivate++;
90+
} else if (ipArr[0] >= 128 && ipArr[0] <= 191) {
91+
isB++;
92+
if (ipArr[0] == 172 && (ipArr[1] >= 16 && ipArr[1] <= 31))
93+
isPrivate++;
94+
} else if (ipArr[0] >= 192 && ipArr[0] <= 223) {
95+
isC++;
96+
if (ipArr[0] == 192 && ipArr[1] == 168)
97+
isPrivate++;
98+
} else if (ipArr[0] >= 224 && ipArr[0] <= 239) {
99+
isD++;
100+
} else if (ipArr[0] >= 240) {
101+
isE++;
102+
}
103+
} else {
104+
isEroor++;
105+
}
106+
} else {
107+
isEroor++;
108+
}
109+
} else {
110+
isEroor++;
111+
}
112+
}
113+
System.out.println(isA + " " + isB + " " + isC + " " + isD + " " + isE + " " + isEroor + " " + isPrivate);
114+
sc.close();
115+
}
116+
}
117+
}

huawei/src/main/java/code/HJ24.java

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
package main.java.code;
2+
3+
import java.io.*;
4+
5+
public class HJ24 {
6+
/**
7+
* HJ24 合唱队
8+
* 合唱队
9+
* 题目描述
10+
* 计算最少出列多少位同学,使得剩下的同学排成合唱队形
11+
* 说明:
12+
* N位同学站成一排,音乐老师要请其中的(N-K)位同学出列,使得剩下的K位同学排成合唱队形。
13+
* 合唱队形是指这样的一种队形:设K位同学从左到右依次编号为1,2…,K,他们的身高分别为T1,T2,…,TK,则他们的身高满足存在i(1<=i<=K)使得T1<T2<......<Ti-1<Ti>Ti+1>......>TK。
14+
* 你的任务是,已知所有N位同学的身高,计算最少需要几位同学出列,可以使得剩下的同学排成合唱队形。
15+
* 注意不允许改变队列元素的先后顺序
16+
* 请注意处理多组输入输出!
17+
* 输入描述:
18+
* 整数N
19+
* 输出描述:
20+
* 最少需要几位同学出列
21+
* 示例1
22+
* 输入
23+
* 8
24+
* 186 186 150 200 160 130 197 200
25+
* 输出
26+
* 4
27+
*/
28+
public static class Main {
29+
public static void main(String[] args) throws IOException {
30+
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
31+
String str = null;
32+
while ((str = br.readLine()) != null) {
33+
if (str.equals("")) continue;
34+
int n = Integer.parseInt(str);
35+
int[] heights = new int[n];
36+
String[] str_heights = br.readLine().split(" ");
37+
// 当仅有一个人时,其自己组成一个合唱队,出列0人
38+
if (n <= 1) System.out.println(0);
39+
else {
40+
for (int i = 0; i < n; i++) heights[i] = Integer.parseInt(str_heights[i]);
41+
// 记录从左向右的最长递增子序列和从右向左的最长递增子序列
42+
int[] seq = new int[n], rev_seq = new int[n];
43+
int[] k = new int[n]; // 用于记录以i为终点的从左向右和从右向走的子序列元素个数
44+
seq[0] = heights[0]; // 初始化从左向右子序列首元素为第一个元素
45+
int index = 1; // 记录当前子序列的长度
46+
for (int i = 1; i < n; i++) {
47+
if (heights[i] > seq[index - 1]) { // 当当前元素大于递增序列最后一个元素时
48+
k[i] = index; // 其左边元素个数
49+
seq[index++] = heights[i]; // 更新递增序列
50+
} else { // 当当前元素位于目前维护递增序列之间时
51+
// 使用二分搜索找到其所属位置
52+
int l = 0, r = index - 1;
53+
while (l < r) {
54+
int mid = l + (r - l) / 2;
55+
if (seq[mid] < heights[i]) l = mid + 1;
56+
else r = mid;
57+
}
58+
seq[l] = heights[i]; // 将所属位置值进行替换
59+
k[i] = l; // 其左边元素个数
60+
}
61+
}
62+
// 随后,再从右向左进行上述操作
63+
rev_seq[0] = heights[n - 1];
64+
index = 1;
65+
for (int i = n - 2; i >= 0; i--) {
66+
if (heights[i] > rev_seq[index - 1]) {
67+
k[i] += index;
68+
rev_seq[index++] = heights[i];
69+
} else {
70+
int l = 0, r = index - 1;
71+
while (l < r) {
72+
int mid = l + (r - l) / 2;
73+
if (rev_seq[mid] < heights[i]) l = mid + 1;
74+
else r = mid;
75+
}
76+
rev_seq[l] = heights[i];
77+
k[i] += l;
78+
}
79+
}
80+
int max = 1;
81+
for (int num : k)
82+
if (max < num) max = num;
83+
// max+1为最大的k
84+
System.out.println(n - max - 1);
85+
}
86+
}
87+
}
88+
}
89+
}

huawei/src/main/java/code/HJ41.java

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
package main.java.code;
2+
3+
import java.util.*;
4+
5+
public class HJ41 {
6+
/**
7+
* HJ41 称砝码
8+
* 称砝码
9+
* 题目描述
10+
* 现有一组砝码,重量互不相等,分别为m1,m2,m3…mn;
11+
* 每种砝码对应的数量为x1,x2,x3...xn。现在要用这些砝码去称物体的重量(放在同一侧),问能称出多少种不同的重量。
12+
* 注:
13+
* 称重重量包括0
14+
* 输入描述:
15+
* 输入包含多组测试数据。
16+
* 对于每组测试数据:
17+
* 第一行:n --- 砝码数(范围[1,10])
18+
* 第二行:m1 m2 m3 ... mn --- 每个砝码的重量(范围[1,2000])
19+
* 第三行:x1 x2 x3 .... xn --- 每个砝码的数量(范围[1,6])
20+
* 输出描述:
21+
* 利用给定的砝码可以称出的不同的重量数
22+
* 示例1
23+
* 输入
24+
* 2
25+
* 1 2
26+
* 2 1
27+
* 输出
28+
* 5
29+
*/
30+
31+
public static class Main {
32+
/**
33+
* 修正:看别人的做法,是第一个砝码的多种重量放入set,然后是下一个砝码多种可能重量。
34+
* !!!这里面比较重要的是根据的是 <目前已有的重量> ,用这些重量加上下一个砝码的所有可能的重量,
35+
* 以重量为根据,而不是以砝码的多种排列组合为依据.
36+
* 所以说这个三重循环,第一个是遍历到第几个砝码,第二个是当前的set里面的重量,第三个是当前砝码的所有可能重量
37+
*/
38+
public static void main(String[] args) {
39+
Scanner sc = new Scanner(System.in);
40+
while (sc.hasNext()) {
41+
List<Integer> weightList = new ArrayList<>();
42+
List<Integer> numList = new ArrayList<>();
43+
Set<Integer> set = new HashSet<>();
44+
int num = sc.nextInt();
45+
for (int i = 0; i < num; i++) {
46+
weightList.add(sc.nextInt());
47+
}
48+
for (int i = 0; i < num; i++) {
49+
numList.add(sc.nextInt());
50+
}
51+
set.add(0);
52+
for (int i = 0; i < num; i++) { //i循环是选择第几个砝码,依次放入set
53+
List<Integer> currentList = new ArrayList<>(set);
54+
for (Integer integer : currentList) { //循环是当前set里面的重量,因为set无法用index遍历所以换成List
55+
for (int k = 1; k <= numList.get(i); k++) { //k循环是当前砝码的可能重量,全部加到set目前所有的数值上面
56+
set.add(integer + weightList.get(i) * k); //因为是要计算所有当前的set重量,所以用了无序的HashSet也没事
57+
}
58+
}
59+
}
60+
System.out.println(set.size());
61+
}
62+
}
63+
}
64+
}

huawei/src/main/java/code/HJ47.java

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
package main.java.code;
2+
3+
import java.io.*;
4+
import java.util.Scanner;
5+
import java.util.ArrayList;
6+
7+
public class HJ47 {
8+
/**
9+
* 只通过70%是因为当遇到重复项时,我们应该丢弃后出现的(这是题目要求),这时应该用一对变量来保存
10+
* 第一次出现的重复值,
11+
* 比如(n没啥用)
12+
* 4 n
13+
* 23 5
14+
* 46 25 (程序中用KEY和VALUE来保存他们)
15+
* 46 32 (舍弃该对数值)
16+
* 82 46 (应用82和46进行比较)
17+
* 对着这个例子把我的程序走一遍就全懂了!就是这么简单,花了我一上午
18+
*/
19+
public static class Main {
20+
/**
21+
* 测试用例:
22+
* 输入:
23+
* 2
24+
* 4 4
25+
* 7 10
26+
* 输出:
27+
* 4 4
28+
* 5 6
29+
* 6 8
30+
* 7 10
31+
*/
32+
public static void main(String[] args) {
33+
Scanner sc = new Scanner(System.in);
34+
while (sc.hasNext()) {
35+
int n = sc.nextInt();
36+
int m = sc.nextInt();
37+
//二维数组存储键值对
38+
int[][] data = new int[n][2];
39+
for (int i = 0; i < n; i++) {
40+
data[i][0] = sc.nextInt();
41+
data[i][1] = sc.nextInt();
42+
}
43+
ArrayList<String> list = new ArrayList<String>();
44+
//若出现重复值,利用这两个变量存储前一个值,丢弃后出现的重复值(如题目要求)
45+
int KEY = data[0][0];
46+
int VALUE = data[0][1];
47+
list.add(KEY + " " + VALUE);
48+
for (int i = 1; i <= n - 1; i++) {
49+
int diff = data[i][0] - KEY - 1;
50+
if (diff > 0) {
51+
for (int j = 1; j <= diff; j++) {
52+
int key = KEY + j;
53+
int value = VALUE + (data[i][1] - VALUE) / (data[i][0] - KEY) * j;
54+
list.add(key + " " + value);
55+
}
56+
list.add(data[i][0] + " " + data[i][1]);
57+
KEY = data[i][0];
58+
VALUE = data[i][1];
59+
//两个键相等则直接跳过,此时KEY,VVALUE保存的还是上一个值
60+
} else if (diff == -1)
61+
continue;
62+
else {
63+
list.add(data[i][0] + " " + data[i][1]);
64+
KEY = data[i][0];
65+
VALUE = data[i][1];
66+
}
67+
}
68+
for (String s : list)
69+
System.out.println(s);
70+
}
71+
}
72+
}
73+
}

0 commit comments

Comments
 (0)