前言
上次没有参加,以为可以避免参加,这次是回学校以后参加的,果然自己蠢得不行,写题目都没有思路,于是被自己的智商吊打,不过事情已经过了,只能抱着每一次挫折都是前进的冲锋号来鼓励自己了,然后参照他人的题解,将题目做一个复盘吧!
1. 降序链表公共部分
题目:
降序排列的链表,求出当前链表的公共部分
6
6 5 4 3 2 1
5
6 5 3 2 1
题目很清晰了,只是用链表来混淆视听实质就是求两个的公共数字。
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n =scanner.nextInt();
List<Integer> res = new ArrayList<>();
Set<Integer> set = new HashSet<>();
for (int i = 0; i < n; i++) {
set.add(scanner.nextInt());
}
int m = scanner.nextInt();
for (int i = 0; i < m; i++) {
int tmp = scanner.nextInt();
if(!set.add(tmp)){
res.add(tmp);
}
}
for (Integer re : res) {
System.out.print(re+" ");
}
}
}
2. 消息覆盖的人数
题目:
通知传递,n个人(序号0~n),m个小组,每个小组有k个人,1个人也能在不同的小组。由0发起的一个通知,每个人都能把通知告诉自己同组的人,求最后收到通知的人数。
50 5
2 1 2
5 10 11 12 13 14
2 0 1
2 49 2
4 6 7 8 2
最后结果7 => 0 1 2 6 7 8 49
这是道并查集问题,以为会有通用的解法,实质上还是使用暴力解法。利用一个HashMap
将所有人关联到的对象放入到一个Set
中,然后最后将0中的元素遍历,利用Set
存储即可
public class Solution {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
int m = scanner.nextInt();
Map<Integer, Set<Integer>> map = new HashMap<>();
for (int i = 0; i < m; i++) {
int k = scanner.nextInt();
Set<Integer> set = new HashSet<>();
// 在处理过程中遍历所有的元素
// 这是当前这个分组中所有的元素
for (int j = 0; j < k; j++) {
set.add(scanner.nextInt());
}
// 建立一个图,即获取当前元素的一个set集合
for (Integer integer : set) {
Set<Integer> set1 = map.get(integer);
if (set1 == null || set1.isEmpty()) {
map.put(integer, set);
continue;
}
// 如果当前已经有的话再添加一次
set1.addAll(set);
map.put(integer, set1);
}
}
System.out.println(map);
// 现在需要遍历所有的然后加入即可
Queue<Integer> queue = new LinkedList<>(map.get(0));
// 使用一个set来存储结果
Set<Integer> result = new HashSet<>();
while (!queue.isEmpty()) {
Integer poll = queue.poll();
Set<Integer> integers = map.get(poll);
// 结果集中不包含的才可以放入,否则排除
for (Integer integer : integers) {
if (!result.contains(integer)) {
queue.add(integer);
result.add(integer);
}
}
}
System.out.println(result);
System.out.println(result.size());
}
}
3. 取出出现次数最多的k个字符和出现次数最少的k个字符
题目:
输入N个字符串(有重复),输出这N个字符串中出现次数最多的前K个及出现次数最少的前K个和他们的出现的次数,注意出现次数一样的时候都要进行字典排序
这里主要是一个重排序的问题,因为要求最多,和最少,此时需要进行两次排序即可,第一遍排序取出最多的,第二遍排序取出最小的k个即可。
这里注意,在比较器中,基本默认的排序都是从小到大排,即在比较器中的逻辑就是 i1 > i2 返回正数。如果想要从大到小就要颠覆这个即i1 > i2 返回负数,反之亦然。同时这里由于涉及到字典序的问题,即如果数字出现次数相同,按照字典序排。
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
int k = scanner.nextInt();// 出现次数最多的k个,和出现次数最小的k个
Map<String, Integer> map = new HashMap<>();
for (int i = 0; i < n; i++) {
String val = scanner.next();
map.put(val, map.getOrDefault(val, 0) + 1);
}
List<Word> list = new ArrayList<>();
for (String s : map.keySet()) {
list.add(new Word(s, map.get(s)));
}
// 重写比较器
list.sort((o1, o2) -> {
// 先比较出现次较多
// 默认是小的排在前面,但是如果想让大的排在前面的话,需要使用小于则返回1
if (o1.rank < o2.rank) return 1;
if (o1.rank > o2.rank) return -1;
return o1.str.compareTo(o2.str);
});
// 输出后k个
for (int i = 0; i < k; i++) {
Word word = list.get(i);
System.out.println(word.str + " " + word.rank);
}
list.sort((o1, o2) -> {
// 先比较出现次比较少的两个
if (o1.rank > o2.rank) return 1;
if (o1.rank < o2.rank) return -1;
return o1.str.compareTo(o2.str);
});
for (int i = 0; i < k; i++) {
Word word = list.get(i);
System.out.println(word.str + " " + word.rank);
}
}
}
class Word {
String str;
int rank;
public Word(String str, int rank) {
this.str = str;
this.rank = rank;
}
}
4. 求数组的中位数
题目:
给定一个偶数的数组,求去掉下表为i的数字的时候,整个数组的中位数是多少,注意是无序的。
思路:刚开始是想的利用list
来,每次移除,然后排序,然后输出中位数,无奈时间复杂度过高。后面参考别人的写法,发现其实去掉下标i
,中位数其实就是在中间的两个数之间摆动,占用了前面的位置,则输出后面的为中位数,占用了后面的则输出前面的为中位数。
public class Solution {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
int[] a = new int[n];
for (int i = 0; i < n; i++) {
a[i] = scanner.nextInt();
}
if (n == 2) {
System.out.println(a[0]);
}
// 拷贝一份数组
int[] t = Arrays.copyOf(a, n);
Arrays.sort(t);
int l = t[n / 2 - 1];
int r = t[n / 2];
// 这一步处理的很妙,因为中位数无非就是两个,只有轮到两个被删除的时候
// 此时中位数才会被替换为对方,所以只需要判断当前值是否小于前一个中位数
// 如果是的话,当前数在前面,则后面多一个位置,则中位数输出后面的
// 如果当前的数不小于前一个中位数,表示当前数字在后面,则前面多出一个位置,输出前面的
for (int i = 0; i < n; i++) {
if (a[i] <= l) {
System.out.println(r);
} else {
System.out.println(l);
}
}
}
}
5. 最少的次数给红黑棋子排序
这道题不会,题目大致意思也理解,不会
Keep thinking, keep coding!
继续保持加油吧,每一天都会有一个新的起点,每一天充满期待,生活就会变得多彩!