• leetcode刷题总结901-950


    901. 股票价格跨度  

      描述:
        

       思路:单调栈。

        

    class StockSpanner {
        Stack<Integer> prices, weights;
    
        public StockSpanner() {
            prices = new Stack();
            weights = new Stack();
        }
    
        public int next(int price) {
            int w = 1;
            while (!prices.isEmpty() && prices.peek() <= price) {
                prices.pop();
                w += weights.pop();
            }
    
            prices.push(price);
            weights.push(w);
            return w;
        }
    }
    View Code

    904. 水果成篮

      描述:

        

       思路:问题可以看成  最长连续子序列。序列中最多包含两种元素。

    907. 子数组的最小值之和

      描述:

        

       思路:

        

    class Solution {
        public int sumSubarrayMins(int[] A) {
            int MOD = 1_000_000_007;
    
            Stack<RepInteger> stack = new Stack();
            int ans = 0, dot = 0;
            for (int j = 0; j < A.length; ++j) {
                // Add all answers for subarrays [i, j], i <= j
                int count = 1;
                while (!stack.isEmpty() && stack.peek().val >= A[j]) {
                    RepInteger node = stack.pop();
                    count += node.count;
                    dot -= node.val * node.count;
                }
                stack.push(new RepInteger(A[j], count));
                dot += A[j] * count;
                ans += dot;
                ans %= MOD;
            }
    
            return ans;
        }
    }
    
    class RepInteger {
        int val, count;
        RepInteger(int v, int c) {
            val = v;
            count = c;
        }
    }

    910. 最小差值 II

      描述:
        

       思路:关键一点就是,在某一个节点,之前的数全部加K,之后的数全部减K

        

     915. 分割数组

      描述:

        

       思路:辅助数组存储左边最大的元素。

    918. 环形子数组的最大和

      描述:

        

      思路:   

    import java.util.Arrays;
    
    public class Solution {
    
        public int maxSubarraySumCircular(int[] A) {
            int len = A.length;
            // 特例判断
            if (len == 0) {
                return 0;
            }
            if (len == 1) {
                return A[0];
            }
    
            int maxSubArray = maxSubArray(A);
            int minSubArrayExcludeHeadAndTail = minSubArray(A);
    
            int sum = 0;
            for (int value : A) {
                sum += value;
            }
            return Math.max(maxSubArray, sum - minSubArrayExcludeHeadAndTail);
        }
    
        public int maxSubArray(int[] nums) {
            int len = nums.length;
            // dp[i]:以 nums[i] 结尾的「连续」子区间的最大和
            int[] dp = new int[len];
            dp[0] = nums[0];
    
            for (int i = 1; i < len; i++) {
                if (dp[i - 1] >= 0) {
                    dp[i] = dp[i - 1] + nums[i];
                } else {
                    // dp[i - 1] < 0 的时候,前面的部分丢弃
                    dp[i] = nums[i];
                }
            }
    
            // 全局扫一遍,找到最大值
            int res = dp[0];
            for (int i = 1; i < len; i++) {
                res = Math.max(res, dp[i]);
            }
            return res;
        }
    
        public int minSubArray(int[] nums) {
            // 思路和 maxSubArray 完全一致,求最大的地方改成最小
            // 但这里求的区间和不包括头和尾
            int len = nums.length;
    
            // dp[i]:以 nums[i] 结尾的「连续」子区间的最小和
            int[] dp = new int[len];
            dp[0] = nums[0];
    
            // 注意 i 的下标
            for (int i = 1; i < len - 1; i++) {
                if (dp[i - 1] >= 0) {
                    // 加上前面的数,会使得结果更大,因此前面的部分丢弃
                    dp[i] = nums[i];
                } else {
                    dp[i] = dp[i - 1] + nums[i];
                }
            }
    
            // 全局扫一遍,找到最小值
            int res = dp[0];
            for (int i = 1; i < len; i++) {
                res = Math.min(res, dp[i]);
            }
            return res;
        }
    
        public static void main(String[] args) {
            Solution solution = new Solution();
            // int[] A = {1, -2, 3, -2};
            // int[] A = {5, -3, 5};
            int[] A = {3, -1, 2, -1};
            int res = solution.maxSubarraySumCircular(A);
            System.out.println(res);
        }
    }
    View Code

        分两种情况,一种为没有跨越边界的情况,一种为跨越边界的情况

        没有跨越边界的情况直接求子数组的最大和即可;
        跨越边界的情况可以对数组求和再减去无环的子数组的最小和,即可得到跨越边界情况下的子数组最大和;

        

    921. 使括号有效的最少添加

      描述:

        

       思路:栈

    class Solution {
    public:
        int minAddToMakeValid(string S) {
            stack<char> temp;
            for(int i=0;i<S.size();i++)
            {
                if(temp.empty())
                {
                    temp.push(S[i]);
                }
                else{
                    if(S[i]==')'&&temp.top()=='(')
                    {
                        temp.pop();
                    }
                    else{
                        temp.push(S[i]);
                    }
                }
            }
            return temp.size();
        }
    };
    View Code

    923. 三数之和的多种可能

      描述:

        

       思路:可以通过hashmap  <num,count>完成。

        也可以通过动态规划。 dp[n][j][k]表示前n个数中某j个数的和为k的个数。

        首先,dp[i][j][k]表示考虑前i个数时,从中选出j个数,组成k大小的方案数。这里的定义是从01背包的定义拓展而来的,这里加入了一个约束限制,就是要从前i个数中选出j个数组成k大小。这样的好处是,如果选择最后一个数,则根据定义的最优子结构性质,可以很简单的使用dp[i - 1][j - 1][k - A[i]]来计算当前除去最后一个数的总共选法数;如果不选择最后一个数,则直接加上不选择的数量个数,即dp[i - 1][j][k]。

    926. 将字符串翻转到单调递增

      描述:

        

       思路:

        dp[i][0],dp[i][1] 分别代表字符 S[i] 最终选择 0 和 1 的最少翻转次数,
        考虑到递增,那么 dp[i][0] 只能由 dp[i-1][0] 转化而来,所以,状态转移方程如下:

        如果 S[i] 是 '1':
        dp[i][0] = dp[i-1][0] + 1 # 只能从 0 转化来,翻转 '1' 为 '0',翻转次数加 1
        dp[i][1] = min(dp[i-1][0], dp[i-1][1]) # 已经为 '1',无需翻转

        如果 S[i] 是 '0':
        dp[i][0] = dp[i-1][0] # 只能从 0 转化来,无需翻转
        dp[i][1] = min(dp[i-1][0] + 1, dp[i-1][1] + 1) # 翻转 '0' 为 '1',翻转次数加 1

    class Solution:
        def minFlipsMonoIncr(self, S: str) -> int:
            zero, one = 0, 0
            for c in S:
                if c == '1':
                    one, zero = min(zero, one), zero + 1
                else:
                    one = min(zero + 1, one + 1)
            return min(zero, one)
    View Code

    930. 和相同的二元子数组

      描述:

        

      思路:前缀和+hash.

    931. 下降路径最小和

      描述;
        

       思路:动态规划,从底向上。

    939. 最小面积矩形

      描述:

        

       思路:将所有点放入集合中,并枚举矩形对角线上的两个点,并判断另外两个点是否出现在集合中。例如我们在枚举到 (1, 1) 和 (5, 5) 时,我们需要判断 (1, 5) 和 (5, 1) 是否也出现在集合中。

    945. 使数组唯一的最小增量

      描述:

        

       思路:

    class Solution {
        public int minIncrementForUnique(int[] A) {
            // 先排序
            Arrays.sort(A);
            int move = 0;
            // 遍历数组,若当前元素小于等于它的前一个元素,则将其变为前一个数+1
            for (int i = 1; i < A.length; i++) {
                if (A[i] <= A[i - 1]) {
                    int pre = A[i];
                    A[i] = A[i - 1] + 1;
                    move += A[i] - pre;
                }
            }
            return move;
        }
    }
    View Code

    946. 验证栈序列

      描述;
        

       思路:

    class Solution {
        public boolean validateStackSequences(int[] pushed, int[] popped) {
            int N = pushed.length;
            Stack<Integer> stack = new Stack();
    
            int j = 0;
            for (int x: pushed) {
                stack.push(x);
                while (!stack.isEmpty() && j < N && stack.peek() == popped[j]) {
                    stack.pop();
                    j++;
                }
            }
    
            return j == N;
        }
    }
    View Code

    948. 令牌放置

      描述:L    

        

       思路:如果让我们来玩令牌放置这个游戏,在让令牌正面朝上的时候,肯定要去找能量最小的令牌。同样的,在让令牌反面朝上的时候,肯定要去找能量最大的令牌。

    class Solution {
        public int bagOfTokensScore(int[] tokens, int P) {
            Arrays.sort(tokens);
            int lo = 0, hi = tokens.length - 1;
            int points = 0, ans = 0;
            while (lo <= hi && (P >= tokens[lo] || points > 0)) {
                while (lo <= hi && P >= tokens[lo]) {
                    P -= tokens[lo++];
                    points++;
                }
    
                ans = Math.max(ans, points);
                if (lo <= hi && points > 0) {
                    P += tokens[hi--];
                    points--;
                }
            }
    
            return ans;
        }
    }
    View Code
  • 相关阅读:
    win10 uwp 依赖属性
    win10 uwp 依赖属性
    Java实现蓝桥杯VIP 算法训练 阶乘末尾
    PHP fileperms() 函数
    PHP fileowner() 函数
    PHP filemtime() 函数
    PHP fileinode() 函数
    PHP filegroup() 函数
    查看MySQL已经运行的时长
    [HNOI2016]矿区
  • 原文地址:https://www.cnblogs.com/dhName/p/13344427.html
Copyright © 2020-2023  润新知