day10-算法热题10题

LeetCode 热题 Hot 100

class Solution {
   public boolean isAnagram(String s, String t) {
        int sLen = s.length();
        int tLen = t.length();
        if (sLen != tLen) return false;
        // 若 s 和 t 中每个字符出现的次数都相同,则称 s 和 t 互为字母异位词。
        // 用数组来做
        int[] sArray = new int[26], tArray = new int[26];
        for (int i = 0; i < sLen; i++) {
            // 当前这个char相对于'a'的位置0~25,
            // sArray[0]++ "anagram",
            sArray[s.charAt(i) - 'a']++;
            tArray[t.charAt(i) - 'a']++;
        }
        return Arrays.equals(sArray,tArray);
    }
}
class Solution {
    
    /**
     * s1 = "ab" s2 = "eidbaooo"
     * 滑动窗口
     * 一开始我们都以小的字符串数量进行匹配
     */
    public boolean checkInclusion(String s1, String s2) {
        int s1Len = s1.length();
        int s2Len = s2.length();
        if (s1Len > s2Len) return false;
        int[] s1Array = new int[26];
        int[] s2Array = new int[26];
        for (int i = 0; i < s1Len; i++) {
            s1Array[s1.charAt(i) - 'a']++;
            s2Array[s2.charAt(i) - 'a']++;
        }
        int left = 0, right = s1Len - 1;
        while (right < s2Len) {
            if (Arrays.equals(s1Array, s2Array)) return true;
            right++;
            if (right != s2Len) {
                // 频率++
                s2Array[s2.charAt(right) - 'a']++;
            }
            // 把之前出现过的清空掉
            s2Array[s2.charAt(left) - 'a']--;
            // 窗口往前移动
            left++;
        }
        return false;
    }
}
class Solution {
      /**
     * 滑动窗口
     * 输入: s = "cbaebabacd", p = "abc"
     * 输出: [0,6]
     */
    public List<Integer> findAnagrams(String s, String p) {
        List<Integer> res = new ArrayList<>();
        int sLen = s.length();
        int pLen = p.length();
        if (pLen > sLen) return res;
        int[] sArray = new int[26], pArray = new int[26];
        // 初始化
        for (int i = 0; i < pLen; i++) {
            sArray[s.charAt(i) - 'a']++;
            pArray[p.charAt(i) - 'a']++;
        }
        // 窗口长度为p的长度
        int left = 0, right = pLen - 1;
        while (right < sLen) {
            // 比较两个是否相等
            if (Arrays.equals(pArray, sArray)) {
                res.add(left);
            }
            // 右边的移动
            right++;
            if (right != sLen) {
                sArray[s.charAt(right) - 'a']++;
            }
            sArray[s.charAt(left) - 'a']--;
            left++;
        }
        return res;
    }
}
class Solution {
  public List<Integer> findDisappearedNumbers(int[] nums) {
        var res = new ArrayList<Integer>();
        boolean[] hasNum = new boolean[nums.length + 1];
        for (int num : nums) {
            hasNum[num] = true;
        }
        for (int i = 1; i <= nums.length; i++) {
            if (!hasNum[i]) res.add(i);
        }
        return res;
    }
}
class Solution {
   public int hammingDistance(int x, int y) {
        return bitCount(x ^ y);
    }

    private int bitCount(int i) {
        int count = 0;
        while (i > 0) {
            if (i % 2 == 1) {
                count++;
            }
            i >>= 1;
        }
        return count;
    }
}
class Solution {
       /**
     * 输入:nums = [1,1,1,1,1], target = 3
     * 输出:5
     * 解释:一共有 5 种方法让最终目标和为 3 。
     * -1 + 1 + 1 + 1 + 1 = 3
     * +1 - 1 + 1 + 1 + 1 = 3
     * +1 + 1 - 1 + 1 + 1 = 3
     * +1 + 1 + 1 - 1 + 1 = 3
     * +1 + 1 + 1 + 1 - 1 = 3
     * 有多种解法,可以用回溯算法剪枝求解,也可以用转化成背包问题求解,这里用前者吧,
     * 容易理解一些,背包问题解法可以查看详细题解。
     * 对于每一个 1,要么加正号,要么加符号,把所有情况穷举出来,即可计算结果。
     */
    Map<String, Integer> memo = new HashMap<>();

    public int findTargetSumWays(int[] nums, int target) {
        if (nums.length == 0) return 0;
        return backtrace(nums, 0, target);
    }

    private int backtrace(int[] nums, int idx, int target) {
        // base case
        if (idx == nums.length) {
            return target == 0 ? 1 : 0;
        }
        // 把它俩转成字符串才能作为哈希表的键
        // 0,3
        String key = idx + "," + target;
        // 避免重复计算
        if (memo.containsKey(key)) {
            return memo.get(key);
        }
        // 还是穷举
        int result = backtrace(nums, idx + 1, target - nums[idx]) + backtrace(nums, idx + 1, target + nums[idx]);
        memo.put(key, result);
        return result;
    }
}
/**
 * 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 {
 /**
     * 维护一个外部累加变量 sum,在遍历 BST 的过程中增加 sum,
     * 同时把 sum 赋值给 BST 中的每一个节点,就将 BST 转化成累加树了。
     */

     int sum = 0;
    public TreeNode convertBST(TreeNode root) {
        if (root == null) return null;
        // 先看right
        convertBST(root.right);
        root.val += sum;
        sum = root.val;
        convertBST(root.left);
        return root;
    }
}
/**
 * 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 {
    /**
     * 所谓二叉树的直径,就是左右子树的最大深度之和,那么直接的想法是对每个节点计算左右子树的最大高度,
     * 得出每个节点的直径,从而得出最大的那个直径。
     */
    int max = Integer.MIN_VALUE;

    public int diameterOfBinaryTree(TreeNode root) {
        depth(root);
        return max;
    }

    public int depth(TreeNode root) {
        if (root == null) return 0;
        int leftDepth = depth(root.left);
        int rightDepth = depth(root.right);
        max = Math.max(max, leftDepth + rightDepth);
        return Math.max(leftDepth, rightDepth) + 1;
    }
}
class Solution {
     /**
     * 子数组求和的经典技巧就是前缀和,原理就是对数组进行预处理,
     * 计算前缀和数组,从而在 O(1) 时间计算子数组和。
     * 0 <= i <= j <= n
     * sum(i,j) = k
     * <p>
     * <p>
     * s(0,j) - sum(0,i-1) = k
     * prefix_sum(0,i-1)
     */
    public int subarraySum(int[] nums, int k) {
        if (nums == null || nums.length == 0) return 0;
        // 前缀和一共出现了几次
        Map<Integer, Integer> map = new HashMap<>();
        // 一开始0出现了一次
        map.put(0, 1);
        int count = 0;
        int prefixSum = 0;
        for (int num : nums) {
            prefixSum += num;
            // diff = prefixSum(i-1)
            int diff = prefixSum - k;
            count += map.getOrDefault(diff, 0);
            map.put(prefixSum, map.getOrDefault(prefixSum, 0) + 1);
        }
        return count;
    }
}
class Solution {
   public int findUnsortedSubarray(int[] nums) {
        if (nums == null || nums.length == 0) return 0;
        int[] newArray = Arrays.copyOf(nums, nums.length);
        Arrays.sort(newArray);
        int start = 0;
        int end = nums.length - 1;
        while (start < end) {
            if (nums[start] == newArray[start]) {
                start++;
            } else if (nums[end] == newArray[end]) {
                end--;
            } else {
                return end - start + 1;
            }
        }
        return 0;
    }

}
/**
 * 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 TreeNode mergeTrees(TreeNode root1, TreeNode root2) {
        if (root1 == null && root2 == null) return null;
        if (root1 == null) return root2;
        if (root2 == null) return root1;
        // 两棵树都有的节点,叠加节点值
        TreeNode root = new TreeNode(root1.val + root2.val);
        // 递归合并左右子树
        root.left = mergeTrees(root1.left, root2.left);
        root.right = mergeTrees(root1.right, root2.right);
        return root;
    }
}
暂时不写
class Solution {
  public int countSubstrings(String s) {
        if (s == null || s.length() == 0) return 0;
        int len = s.length();
        // 从第i~j位是不是回文串 状态容器
        boolean[][] dp = new boolean[len][len];
        //回文串的数量
        int count = 0;
        for (int i = len - 1; i >= 0; i--) {
            for (int j = i; j < len; j++) {
                //如果i和j指向的字符不一样,那么dp[i][j]就
                //不能构成回文字符串
                if (s.charAt(i) != s.charAt(j)) continue;
                dp[i][j] = j - i <= 2 || dp[i + 1][j - 1];
                if (dp[i][j]) count++;
            }
        }
        return count;
    }
}
  /**
     * temperatures = [73,74,75,71,69,72,76,73]
     * index value
     * 2   ->  75
     * <p>
     * <p>
     * 输出: [1,1,4,2,1,1,0,0]
     * 单调栈
     */
    public int[] dailyTemperatures(int[] temperatures) {
        if (temperatures == null || temperatures.length == 0) return new int[]{};
        int[] answer = new int[temperatures.length];
        // 存下标
        Stack<Integer> idxStack = new Stack<Integer>();
        for (int i = 0; i < temperatures.length; i++) {
            // 当前值大于栈顶元素?大于的话就是 当前索引减去栈顶的索引 否则 是0
            while (!idxStack.isEmpty() && temperatures[i] > temperatures[idxStack.peek()]) {
                // 然后出栈
                answer[idxStack.peek()] = i - idxStack.pop();
            }
            idxStack.push(i);
        }
        return answer;
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

枫吹过的柚

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值