Leetcode刷题 2021.03.03

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--;
        }
    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值