Leetcode刷题 2021.03.02
Leetcode338 比特位计数
给定一个非负整数 num。对于 0 ≤ i ≤ num 范围中的每个数字 i ,计算其二进制数中的 1 的数目并将它们作为数组返回。
一开学真的忙这忙那,周五论文要查重,下周二就要送去盲审了。今天导师找了改了一波,还好问题不是很多,主要就是一些格式问题吧。下周二以后就要全力冲刺春招了!
这种要输出每一个数的肯定就是复用之前的信息了,其实也就是找规律吧。如果是奇数,那1的个数就是前面一个数加1,如果是偶数,就是这个数除以2的个数。因为相当于右移了一位,1的数量是不会变的。
class Solution {
public int[] countBits(int num) {
int[] res = new int[num + 1];
for(int i = 1; i <= num; i++){
if (i % 2 != 0){
res[i] = res[i - 1] + 1;
}else{
res[i] = res[i / 2];
}
}
return res;
}
}
Leetcode82 删除排序链表中的重复元素 II
给定一个排序链表,删除所有含有重复数字的节点,只保留原始链表中 没有重复出现 的数字。
在刷字节题库,很少有还没做的题,除非是那些很复杂的,要是面试出的话估计调试就要调试半小时。发现这道基础的链表题还没做过,比较简单。链表题不行就多用几个变量,在纸上画一画就行了。
class Solution {
public ListNode deleteDuplicates(ListNode head) {
if (head == null || head.next == null) return head;
//伪头节点,常见做法了
ListNode dummyHead = new ListNode();
dummyHead.next = head;
ListNode prev = dummyHead, cur = head;
while (cur != null){
//用一个flag表示是否有重复结点
boolean flag = false;
while (cur.next != null && cur.val == cur.next.val){
flag = true;
cur = cur.next;
}
//如果有,全要全部删掉
if (flag){
prev.next = cur.next;
//否则prev指针后移就行
}else{
prev = prev.next;
}
cur = cur.next;
}
return dummyHead.next;
}
}
Leetcode305 岛屿数量 II
假设你设计一个游戏,用一个 m 行 n 列的 2D 网格来存储你的游戏地图。
起始的时候,每个格子的地形都被默认标记为「水」。我们可以通过使用 addLand 进行操作,将位置 (row, col) 的「水」变成「陆地」。
你将会被给定一个列表,来记录所有需要被操作的位置,然后你需要返回计算出来 每次 addLand 操作后岛屿的数量。
注意:一个岛的定义是被「水」包围的「陆地」,通过水平方向或者垂直方向上相邻的陆地连接而成。你可以假设地图网格的四边均被无边无际的「水」所包围。
请仔细阅读下方示例与解析,更加深入了解岛屿的判定。
开了会员以后才做的题。和岛屿数量一相比,每一次操作以后要输出岛屿数量。所以每一次都dfs一遍的话应该会超时,考虑并查集。看注释吧。。
class Solution {
public List<Integer> numIslands2(int m, int n, int[][] positions) {
List<Integer> res = new ArrayList<>();
//把每一个点都看成是一个点,初始化parent都是-1,岛屿的个数也初始化为0
UnionFind uf = new UnionFind(m * n);
for(int[] ele : positions){
int dx = ele[0], dy = ele[1];
//获取和岛屿相邻的点,要满足不越界,并且是岛屿的点才合并否则没有意义
List<Integer> temp = new ArrayList<>();
if (dx - 1 >= 0 && uf.isValid((dx - 1) * n + dy)) temp.add((dx - 1) * n + dy);
if (dx + 1 < m && uf.isValid((dx + 1) * n + dy)) temp.add((dx + 1) * n + dy);
if (dy - 1 >= 0 && uf.isValid(dx * n + dy - 1)) temp.add(dx * n + dy - 1);
if (dy + 1 < n && uf.isValid(dx * n + dy + 1)) temp.add(dx * n + dy + 1);
int index = dx * n + dy;
//先设置该点是岛屿,岛屿数量加1
if (!uf.isValid(index)){
uf.setParent(dx * n + dy);
}
//依次进行合并,合并的时候,岛屿数量要减一
for(int i : temp){
uf.union(i, index);
}
res.add(uf.getSize());
}
return res;
}
class UnionFind{
private int[] parent;
private int size;
public int getSize(){
return this.size;
}
public UnionFind(int n){
parent = new int[n];
for(int i = 0; i < n; i++){
parent[i] = -1;
}
}
public void setParent(int i){
parent[i] = i;
this.size++;
}
public boolean isValid(int i){
return parent[i] >= 0;
}
public int find(int i){
if (parent[i] == i) return i;
return parent[i] = find(parent[i]);
}
public void union(int i, int j){
int root1 = find(i);
int root2 = find(j);
if (root1 == root2) return;
parent[root1] = root2;
size--;
}
}
}