返回

C/C++ 1403:拨开迷雾,探索非递增顺序的最小子序列

后端

题目

给你一个整数数组 nums,请你找出并返回一个非递增顺序的最小子序列,该子序列包含 nums 的所有元素。

示例 1:

输入:nums = [4,3,10,9,8]
输出:[10,9,8,4,3]

示例 2:

输入:nums = [4,4,7,6,7]
输出:[7,7,6,4,4]

示例 3:

输入:nums = [1,3,2]
输出:[3,2,1]

提示:

  • 1 <= nums.length <= 2000
  • 1 <= nums[i] <= 1000

题目整理

  • 输入:整数数组 nums
  • 输出:一个非递增顺序的最小子序列,该子序列包含 nums 的所有元素

题目的解题思路

  • 贪心算法:

    • 使用贪心算法,从左到右遍历数组,维护一个栈。
    • 如果栈为空,或者栈顶元素不大于当前元素,则将当前元素压入栈中。
    • 否则,弹出栈顶元素,继续遍历数组。
    • 最后,栈中剩下的元素就是非递增顺序的最小子序列。
  • 动态规划:

    • 定义状态 dp[i] 为前 i 个元素的非递增顺序的最小子序列的长度。
    • 则有状态转移方程:
      dp[i] = max(dp[j] + 1) for j < i and nums[j] >= nums[i]
      
    • 最终答案为 max(dp[i])

具体的实现和代码

贪心算法

class Solution {
public:
    vector<int> minSubsequence(vector<int>& nums) {
        sort(nums.begin(), nums.end());
        vector<int> res;
        int sum = 0;
        for (int i = 0; i < nums.size(); i++) {
            sum += nums[i];
        }
        int currSum = 0;
        for (int i = nums.size() - 1; i >= 0; i--) {
            currSum += nums[i];
            res.push_back(nums[i]);
            if (currSum > sum - currSum) {
                break;
            }
        }
        return res;
    }
};

动态规划

class Solution {
public:
    vector<int> minSubsequence(vector<int>& nums) {
        int n = nums.size();
        vector<int> dp(n + 1, 0);
        for (int i = 1; i <= n; i++) {
            dp[i] = nums[i - 1];
            for (int j = 0; j < i; j++) {
                if (nums[j] <= nums[i - 1]) {
                    dp[i] = max(dp[i], dp[j] + nums[i - 1]);
                }
            }
        }
        int maxLen = *max_element(dp.begin(), dp.end());
        vector<int> res;
        for (int i = n; i >= 1; i--) {
            if (dp[i] == maxLen) {
                res.push_back(nums[i - 1]);
                maxLen -= nums[i - 1];
            }
        }
        return res;
    }
};

结语

通过对 1403. 非递增顺序的最小子序列 这道题目的详细解析,我们不仅掌握了它的解题思路和具体实现,还领略了算法世界中的魅力。希望这篇文章能对您有所帮助,也期待您继续关注我的创作,共同探索算法世界中的奥秘。