每日两道leetcode(做过一遍回过头来又忘了qwq)

334. 递增的三元子序列 - 力扣(LeetCode)

题目

给你一个整数数组 nums ,判断这个数组中是否存在长度为 3 的递增子序列。

如果存在这样的三元组下标 (i, j, k) 且满足 i < j < k ,使得 nums[i] < nums[j] < nums[k] ,返回 true ;否则,返回 false 。

示例 1:

输入:nums = [1,2,3,4,5]
输出:true
解释:任何 i < j < k 的三元组都满足题意

示例 2:

输入:nums = [5,4,3,2,1]
输出:false
解释:不存在满足题意的三元组

示例 3:

输入:nums = [2,1,5,0,4,6]
输出:true
解释:三元组 (3, 4, 5) 满足题意,因为 nums[3] == 0 < nums[4] == 4 < nums[5] == 6

提示:

  • 1 <= nums.length <= 5 * 105
  • -231 <= nums[i] <= 231 - 1

进阶:你能实现时间复杂度为 O(n) ,空间复杂度为 O(1) 的解决方案吗?

思路

  1. O(n)时间O(1)空间的实在想不出来,只想出来O(n)O(n)的思路,可以利用前序最小值和后序最大值数组来寻找;O(n^2)O(n)则是套两层循环。
  2. 接下来开始学习官方题解的思路:
    1. 看懂之后真的太绝了,官方题解定义了两个指针first和second,但是他们不是单纯地表示一个序列。
    2. 假设有新的最小数出现了,会将first先更新过去作为新的序列头,但是second先不变维持原序列已经到达2长度的状态。
    3. 若出现新的值比新的first大,若大于second那么second就已经形成序列了,若不大于second,则新的更小的序列出现,应该贪心地取小的。若遍历完都没发现这样的序列,则返回false。

官方题解注释

class Solution {
public:
    bool increasingTriplet(vector& nums) {
        int n = nums.size();
        if (n < 3) return false;
        int first = nums[0], second = INT_MAX, num;
        for (int i = 1; i < n; i++) {
            num = nums[i];
            if (num > second) return true; // 若当前数比second大,说明找到了新序列了。
            else if (num > first) second = num; // 若只是比first大,说明找到了到当前位置上更小的上升序列,应贪心地更新,以更有可能匹配到更大数。
            else first = num; // 如果出现新的最小数,则更新first,这不影响前一序列的比较,因为second还没更新,first此时作为一个新序列的探索,也就是两个指针其实可以覆盖到一个半的序列。
        }
        return false;
    }
};

复杂度分析

  • 时间复杂度:O(n)。
  • 空间复杂度:O(1)。

知识积累

  • INT_MAX和INT_MIN是C++在库中的预定义宏,分别表示32位有符号整数(int)所能表示的最大值和最小值。

你可能感兴趣的:(leetcode训练,leetcode,算法,职场和发展,c++,贪心算法)