0
点赞
收藏
分享

微信扫一扫

day09-算法热题10题

祈澈菇凉 2022-04-13 阅读 48
算法

LeetCode 热题 Hot 100

  • 231. 2 的幂
// 位运算 n&(n-1) 在算法中挺常见的,作用是消除数字 n 的二进制表示中的最后一个 1,用这个技巧可以判断 2 的指数。
class Solution {
   public boolean isPowerOfTwo(int n) {
         if (n <= 0) return false;
         return  (n & (n - 1)) == 0;
    }
}
  • 338. 比特位计数
class Solution {
    public int[] countBits(int n) {
        int[] dp = new int[n + 1];
        Arrays.fill(dp, 0);
        dp[0] = 0;
        for (int i = 1; i < n + 1; i++) {
            // 位运算 n&(n-1) 在算法中挺常见的,作用是消除数字 n 的二进制表示中的最后一个 1
            // dp[i] 肯定是比 dp[i & (i - 1)] 多一个1,累加上来就行
            dp[i] = dp[i & (i - 1)] + 1;
        }
        return dp;
    }
}
  • 347. 前 K 个高频元素
class Solution {
    /**
     * 最小堆
     */
    public int[] topKFrequent(int[] nums, int k) {
        Map<Integer, Integer> freq = new HashMap<>();
        for (int num : nums) {
            int f = freq.getOrDefault(num, 0) + 1;
            freq.put(num, f);
        }
        // 比较出现频率
        PriorityQueue<Integer> minHeap = new PriorityQueue<>((o1, o2) -> freq.get(o1) - freq.get(o2));
        int[] res = new int[k];
        for (Integer elem : freq.keySet()) {
            minHeap.add(elem);
            if (minHeap.size() > k) {
                // 移除最小的那个
                minHeap.remove();
            }
        }
        for (int i = 0; i < k; i++) {
            res[i] = minHeap.remove();
        }
        return res;
    }
}

  • 394. 字符串解码
class Solution {
   /**
     * 4种情况
     * 1: 数字
     * 2: 字母
     * 3: [
     * 4: ]
     */
    public String decodeString(String s) {
        // 乘积栈
        Stack<Integer> times = new Stack<>();
        Stack<String> preStrs = new Stack<>();
        String res = "";
        int time = 0;
        for (char c : s.toCharArray()) {
            if (isNum(c)) {
                time = time * 10 + Integer.parseInt(c + "");
            } else if (c == '[') {
                times.push(time);
                preStrs.push(res);
                time = 0;
                res = "";
            } else if (c == ']') {
                int curTime = times.pop();
                StringBuilder preStr = new StringBuilder(preStrs.pop());
                while (curTime > 0) {
                    preStr.append(res);
                    curTime--;
                }
                res = preStr.toString();
            } else {
                res += c;
            }
        }
        return res;
    }

    private boolean isNum(char c) {
        return c >= '0' && c <= '9';
    }

}
  • 399. 除法求值
暂时不写
  • 406. 根据身高重建队列
class Solution {
public int[][] reconstructQueue(int[][] people) {
        /**
         * 分析题意:身高较高的同学先进行插入操作,然后身高矮的同学按照k的值为索引,插入到编号为k的位置上
         * 他前面肯定有k个高个子比他高或相等
         * 规则: 先按身高h降序排列,然后按照比高个数k升序排列
         * 等排序遍历一趟之后,还有人没有落在最终的位置,我们就按照他的k值作为索引将其插入到k位置上
         */
        // 原数组[[7,0],[4,4],[7,1],[5,0],[6,1],[5,2]]
        // 先排序一遍
        // [[7,0],[7,1],[6,1],[5,0],[5,2],[4,4]]
        // 接着按照k值一个个插入
        // [7,0]
        // [7,0],[7,1]
        // [7,0],[6,1],[7,1]
        // [5,0],[7,0],[6,1],[7,1]
        // [5,0],[7,0],[5,2],[6,1],[7,1]
        // [5,0],[7,0],[5,2],[6,1],[4,4],[7,1]
        // 如果身高相等,我们就按照k升序排列,否则按照h降序排列
        Arrays.sort(people, (o1, o2) -> o1[0] == o2[0] ? o1[1] - o2[1] : o2[0] - o1[0]);
        System.out.println(Arrays.deepToString(people));
        List<int[]> queue = new ArrayList<>();
        for (int[] person : people) {
            queue.add(person[1], person);
        }
        return queue.toArray(new int[0][]);
    }
}
  • 416. 分割等和子集
class Solution {
  /**
     * 对于这个问题,我们可以先对集合求和,得出 sum,然后把问题转化为背包问题:
     * 给一个可装载重量为 sum / 2 的背包和 N 个物品,每个物品的重量为 nums[i]。现在让你装物品,是否存在一种装法,能够恰好将背包装满?
     * 第一步要明确两点,「状态」和「选择」,状态就是「背包的容量」和「可选择的物品」,选择就是「装进背包」或者「不装进背包」。
     * dp 数组的定义:dp[i][j] = x 表示,对于前 i 个物品,
     * 当前背包的容量为 j 时,若 x 为 true,则说明可以恰好将背包装满,若 x 为 false,则说明不能恰好将背包装满。
     * 根据 dp 数组含义,可以根据「选择」对 dp[i][j] 得到以下状态转移:
     * 如果不把 nums[i] 算入子集,或者说你不把这第 i 个物品装入背包,那么是否能够恰好装满背包,取决于上一个状态 dp[i-1][j],继承之前的结果。
     * 如果把 nums[i] 算入子集,或者说你把这第 i 个物品装入了背包,那么是否能够恰好装满背包,取决于状态 dp[i-1][j-nums[i-1]]。
     */
    public boolean canPartition(int[] nums) {
        int sum = 0;
        for (int num : nums) {
            sum += num;
        }
        // 和为奇数时,不可能划分成两个和相等的集合
        if (sum % 2 != 0) return false;
        sum /= 2;
        int n = nums.length;
        boolean[][] dp = new boolean[n + 1][sum + 1];
        for (int i = 0; i <= n; i++) {
            dp[i][0] = true;
        }
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= sum; j++) {
                if (j - nums[i - 1] < 0) {
                    // 背包容量不足,不能装入第 i 个物品
                    dp[i][j] = dp[i - 1][j];
                } else {
                    // 装入或不装入背包
                    dp[i][j] = dp[i - 1][j] || dp[i - 1][j - nums[i - 1]];
                }
            }
        }
        return dp[n][sum];
    }
}

  • 37. 路径总和
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
  public boolean hasPathSum(TreeNode root, int targetSum) {
        if (root == null) return false;
        if (root.left == null && root.right == null) return targetSum == root.val;
        return hasPathSum(root.left, targetSum - root.val)
                ||
                hasPathSum(root.right, targetSum - root.val);

    }
}
  • 37. 路径总和 II
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
   List<List<Integer>> pathList = new LinkedList<>();


    LinkedList<Integer> path = new LinkedList<>();

    public List<List<Integer>> pathSum(TreeNode root, int targetSum) {
        if (root == null) return pathList;
        backtack(root, targetSum);
        return pathList;
    }

    private void backtack(TreeNode root, int targetSum) {
        if (root == null) return;
        int remain = targetSum - root.val;
        if (root.left == null && root.right == null) {
            if (remain == 0) {
                // 找到一条路径
                path.addLast(root.val);
                pathList.add(new LinkedList<>(path));
                path.removeLast();
            }
            return;
        }
        // 维护路径列表
        path.addLast(root.val);
        backtack(root.left, remain);
        path.removeLast();

        path.addLast(root.val);
        backtack(root.right, remain);
        path.removeLast();
    }
}
  • 37. 路径总和 III
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
  
    // 记录前缀和
    // 定义:从二叉树的根节点开始,路径和为 pathSum 的路径有 preSumCount.get(pathSum) 个
    Map<Integer, Integer> preSumCount;
    int res = 0;
    int targetSum;

    public int pathSum(TreeNode root, int targetSum) {
        this.targetSum = targetSum;
        preSumCount = new HashMap<>();
        preSumCount.put(0, 1);
        backtrack(0, root);
        return res;
    }

    private void backtrack(int sum, TreeNode root) {
        if (root == null) return;
        sum += root.val;
        if (preSumCount.containsKey(sum - targetSum) && preSumCount.get(sum - targetSum) >= 1) {
            res += preSumCount.get(sum - targetSum);
        }
        preSumCount.put(sum, preSumCount.getOrDefault(sum, 0) + 1);
        backtrack(sum, root.left);
        backtrack(sum, root.right);
        preSumCount.put(sum, preSumCount.get(sum) - 1);
    }
}
举报

相关推荐

day09-编程题

day08-算法热题10题

day04-算法热题10题

day06-算法热题10题

day01-算法热题前10题

刷题打卡 day09

day09-集合和字符串 作业

0 条评论