Leetcode题集合

Leetcode题集合

刷题的一些小小反思。

动态规划

376 摆动序列

https://leetcode-cn.com/problems/wiggle-subsequence/

这道题是求子序列的题目 300 最长递增子序列和这道题一样,都是是使用动态规划,通用递归公式都差不多,都需要两次遍历可以解决。

但是这道题leetcode官方有另外一种解法,不太常规,只需要O(n)复杂度,但是需要证明,为什么i状态下只与i -1状态下的代码有关?目前没搞懂哦。

完全背包问题

518. 零钱兑换 II

这道题的确是一道标准的完全背包问题,但是做了这个题目几次,首先想到的就是用到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)时间复杂度,最好的解法是遍历两次使用双指针:

  1. 找到左右两边需要被移动的l和r,那么它们需要满足什么呢?
  2. 对于l,
    是需要找到它的右侧有元素比它小,那么按照升序排列,这里就需要把最小值排序;就是从右向左遍历,记录当前最小值,和当前点比较,一旦大于,则说明需要移动
  3. 对于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();
    }

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值