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
*
*
* 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
*
*
* 输出: [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;
}