Leetcode题集合
刷题的一些小小反思。
动态规划
376 摆动序列
https://leetcode-cn.com/problems/wiggle-subsequence/
这道题是求子序列的题目 300 最长递增子序列和这道题一样,都是是使用动态规划,通用递归公式都差不多,都需要两次遍历可以解决。
但是这道题leetcode官方有另外一种解法,不太常规,只需要O(n)复杂度,但是需要证明,为什么i状态下只与i -1状态下的代码有关?目前没搞懂哦。
完全背包问题
这道题的确是一道标准的完全背包问题,但是做了这个题目几次,首先想到的就是用到dfs的回溯法。完全背包问题还需要多多研究。
前缀和
523. 连续的子数组和
一般求连续子数组的和,都可以用到连续前缀和来求解。这道题挺有意思,需要用到连续和加哈希表来求解。
1248. 统计优美子数组
这道题提示我们,遍历所有前缀和数组复杂度可能需要O(n2)。这里使用了频次数组的方法,该方法能够在O(n)时间遍历频次数组
pre[j] - pre[i] = k
pre[j] = pre[i] + k
for(int i =1; i<n ;i ++){
odd += num[i] & 1
if( odd > k)
ans += cnt[pre[i] - k]
cnt[odd] += 1
}
贪心
1011. 在 D 天内送达包裹的能力
这道题刚开始看到题目第一个思路就是使用贪心法解题,但是并不能ac。这道题解法非常巧妙,对days使用二分法+贪心的思想,贪心左边界是数组最大值,右边界是数组的sum。
类似的题目还有 875. 爱吃香蕉的珂珂
双指针
581. 最短无序连续子数组
一道非常不常规的双指针题目,很难想到解法,最容易的想到的是用到排序。但是O(nlogn)时间复杂度,最好的解法是遍历两次使用双指针:
- 找到左右两边需要被移动的l和r,那么它们需要满足什么呢?
- 对于l,
是需要找到它的右侧有元素比它小,那么按照升序排列,这里就需要把最小值排序;就是从右向左遍历,记录当前最小值,和当前点比较,一旦大于,则说明需要移动 - 对于r,类似的道理,就是要找到左侧比它大的元素,则需要把大的元素移动过来;这里采用从左往右的遍历方式,记录最大值,和当前点比较,一旦小于,则说明需要移动。
注意left 和right的初始值要相等,否则若是升序答案就是错误的。
public int findUnsortedSubarray(int[] nums) {
int n = nums.length;
int right = -1;
int max = Integer.MIN_VALUE;
for(int i = 0 ; i < n; i++){
if(nums[i] < max){
right = i;
}else{
max = Math.max(max, nums[i]);
}
}
int left = -1;
int min = Integer.MAX_VALUE;
for(int i = n - 1; i >= 0; i--){
if( nums[i] > min){
left = i;
}else{
min = Math.min(min,nums[i]);
}
}
return right-left>0?right - left + 1:0;
}
滑动窗口
1423. 可获得的最大点数
这道题用滑动窗口+ 前缀和解决,滑动窗口的题目的特征是所求结果的长度是确定的。
单调栈
单调栈及应用
摩天大楼问题
柱状图中的最大矩形
739.每日温度
解析字符串的题目
394. 字符串解码
ps:这题笔试非常喜欢考,背起来。
class Solution {
Stack<Integer> digitStack = new Stack<>();
Stack<StringBuilder> characterStack = new Stack<>();
public String decodeString(String s) {
int multi = 0;
char[] ch = s.toCharArray();
StringBuilder ans = new StringBuilder();
for (char c : ch) {
if(Character.isDigit(c)){
multi = multi*10 + c - '0';
}else if( c == '['){
digitStack.push(multi);
multi = 0;
characterStack.push(ans);
ans = new StringBuilder();
} else if (Character.isAlphabetic(c)){
ans.append(c);
}else if ( c == ']'){
Integer integer = digitStack.pop();
StringBuilder builder = characterStack.pop();
for(int i = 0 ; i< integer ; i++){
builder.append(ans);
}
ans = builder;
}
}
return ans.toString();
}
}