334. Increasing Triplet Subsequence

Given an unsorted array return whether an increasing subsequence of length 3 exists or not in the array.

Formally the function should:

    Return true if there exists i, j, k
    such that arr[i] < arr[j] < arr[k] given 0 ≤ i < j < k ≤ n-1 else return false.

Note: Your algorithm should run in O(n) time complexity and O(1) space complexity.

Example 1:

Input: [1,2,3,4,5]
Output: true

Example 2:

Input: [5,4,3,2,1]
Output: false

题目要求判断给出的数组中是否存在三个元素,nums[i]、nums[j]、nums[k],这三个元素满足nums[i] < nums[j] < nums[k],并且i < j < k。
题目还要求时间复杂度为O(n),空间复杂度为O(1)。
如果暂时不管时间和空间复杂度的事情,如何确定数组中是否存在满足上面条件的三元组呢,brute force则是O(N^3),将所有的三元组全都找出来,判断其中是否存在满足条件的三元组,但是这种方法太蠢了。
如果对于每一个数组的元素C,我们都知道在它之前的元素中的最小值A和在它之后的元素的最大值D呢,这样子如果A < C < D,那么直接返回true就可以啦。我们维护两个数组,former和latter,former[i]表示在i之前的所有元素的最小值,latter[i]表示的是i之后所有元素中的最大值。这样的时间复杂度为O(n),但是空间复杂度为O(n),这点不是太好。

bool increasingTriplet(vector<int>& nums)
{
    int size = nums.size();
    if(size <= 2)return false;
    vector<int> former(size, INT32_MAX), latter(size, INT32_MIN);
    former[0] = nums[0];latter[size - 1] = nums[size - 1];
    for(int i = 1; i < size; i++)
        former[i] = former[i - 1] < nums[i] ? former[i - 1] : nums[i];
    for(int i = size - 2; i >= 0; i--)
        latter[i] = latter[i + 1] > nums[i] ? latter[i + 1] : nums[i];
    for(int i = 1; i < size -1; i++)
        if(former[i] < nums[i] && latter[i] > nums[i])return true;
    return false;
}

下面是一种巧妙的策略。
维护两个指针small和large,这两个指针都被初始化为INT32_MAX。遍历vector,如果某个元素小于small,这将small更新,相当于当前遇到的数组元素的最小值。如果当前元素大于small,却小于large,说明在此之前,small已经从INT32_MAX更新为另一个值了,也就是说当前元素之前有一个元素小于当前元素(注意这句话)。而如果当前元素大于small和large,说明此时的small和large都被更新过了。此时,我们虽然不能确定这个三元组是什么,但是可以保证在当前元素current element之前,存在一个元素满足current element > large,并且在large之前有一个元素小于large(为什么不能说这个三元组就是small, large, current element,这是因为small和large的索引大小关系不能确定)。下面的代码满足了O(n)的时间复杂度和O(1)的空间复杂度。

bool increasingTriplet(vector<int>& nums)
{
    int size = nums.size();
    if(size <= 2)return false;
    int small = INT32_MAX, large = INT32_MAX;
    for(int i = 0; i < size; i++)
    {
        if(nums[i] <= small) {small = nums[i];}
        else if(nums[i] <= large) {large = nums[i];}
        else return true;       
    }
    return false;
}

www.sunshangyu.top

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值