回顾前面刷过的算法(6)

今天回顾一下这几道算法


    //最小栈
    //思路: 定义一个带有val、min、next 三个属性的节点,其中min表示除当前节点外剩余节点中最小的节点值,
    //以链表的形式存储节点,每次push节点都是插入到root后一个节点,删除也是root后一个节点,每次插入/删除都需要
    //更新root和插入/删除节点的min值
    class MinStack {

        class Node {
            int val, min;
            Node next;

            public Node() {
                this.min = Integer.MAX_VALUE;
            }

            public Node(int val) {
                this.val = val;
            }

            public Node(int val, Node next) {
                this.val = val;
                this.next = next;
            }
        }

        Node root;

        public void push(int val) {
            Node node = new Node(val, root.next);
            node.min = root.min;
            root.next = node;
            root.min = Math.min(root.min, val);
        }

        public void pop() {
            Node cur = root.next;
            if (cur.val == root.min) {
                root.min = cur.min;
            }
            root.next = cur.next;
            cur.next = null;
        }

        public Node getTop() {
            return root.next;
        }

        public int getMin() {
            return root.min;
        }
    }

    //前K个高频元素
    //思路: 采用桶排序思路,就是先用hashMap统计每个元素出现的次数,然后在以value为索引,key为值存储到一个list
    //集合数组中,我们只需要从尾遍历list即可找到前k个高频元素
    public int[] topKFrequent(int[] nums, int k) {
        HashMap<Integer, Integer> map = new HashMap<>();
        for (int num : nums) {
            if (map.containsKey(num)) {
                map.put(num, map.get(num) + 1);
            } else {
                map.put(num, 1);
            }
        }
        List<Integer>[] list = new List[nums.length + 1];
        for (int key : map.keySet()) {
            int value = map.get(key);
            if (list[value] == null) {
                list[value] = new ArrayList<>();
            }
            list[value].add(key);
        }
        int[] res = new int[k];
        for (int i = nums.length, j = 0; i >= 0 && j < k; i--) {
            if (list[i] != null) {
                for (int num : list[i]) {
                    res[j++] = num;
                }
            }
        }
        return res;
    }

    //比特位计数
    //0  01  10  11  100  101  110  111
    //0  1   2   3   4    5    6    7
    //思路: 维护一个highBit记录当前为2整数次幂元素的最高位是第几位
    //其中存在这么一个关系  bits[i] = bits[i - highBit] + 1;
    //bits[i] 表示元素i的比特位有多少个1
    public int[] countBits(int n) {
        int[] bits = new int[n + 1];
        int highBit = 0;
        for (int i = 1; i <= n; i++) {
            if ((i & (i - 1)) == 0) {
                highBit = i;
            }
            bits[i] = bits[i - highBit] + 1;
        }
        return bits;
    }


    //打家劫舍III
    //思路: 定义两个map存储最大值,f存储选中当前节点时的最大值
    //g存储不选中当前节点时的最大值
    Map<TreeNode, Integer> f = new HashMap<>();
    Map<TreeNode, Integer> g = new HashMap<>();

    public int rob(TreeNode root) {
        dfs(root);
        return Math.max(f.getOrDefault(root, 0), g.getOrDefault(root, 0));
    }

    private void dfs(TreeNode node) {
        if (node == null) {
            return;
        }
        dfs(node.left);
        dfs(node.right);
        f.put(node, node.val + g.getOrDefault(node.left, 0) +
                g.getOrDefault(node.right, 0));
        g.put(node, Math.max(f.getOrDefault(node.left, 0), g.getOrDefault(node.left, 0)) +
                Math.max(f.getOrDefault(node.right, 0), g.getOrDefault(node.right, 0)));
    }

    //寻找重复数
    //思路: 因为数组是【1,n】的,且存在重复数,我们
    //可以把value当作数组索引,然后利用快慢指针思想进行遍历
    public int findDuplicate(int[] nums) {
        int slow = 0, fast = 0;
        do {
            slow = nums[slow];
            fast = nums[nums[fast]];
        } while (slow != fast);
        slow = 0;
        while (slow != fast) {
            slow = nums[slow];
            fast = nums[fast];
        }
        return slow;
    }

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值