递增三元子序列LeetCode334

题目:

给定一个未排序的数组, 判断这个数组中是否存在长度为 3 的递增子序列. 数学表达式如下:

如果存在这样的  i, j, k,  且满足 0 ≤ i < j < kn-1,
使得  arr[i] < arr[j] < arr[k] ,返回 true ; 否则返回 false 。

说明:

要求算法的时间复杂度为 O(n),空间复杂度为 O(1) 。

分析:

时间复杂度为O(n), 也就是不能在遍历时对每个元素都分析整个序列的前后元素的情况, 必定要有一种状态可以在元素之间相互转移;

空间复杂度为O(1), 说明不能再新创建 状态保存数组 或者其他之类的东西

突破点:

任何两个相邻的元素都有大小关系, 而且这种大小关系可以转移

思路:

设计四个指针p[1] ~ p[4],然后来一个外层循环 while(true)

1,先找到第一个连续递增二元子序列(比如【3,1,2,7】中【1,2】就是第一个连续递增二元子序列)。

可以发现之前的那个3没有任何用处。

2,然后看下一个元素也就是p[3],这里要分情况讨论

    ①如果p[3] > p[2],查找成功

    ②否则若p[2] >= p[3] > p[1],想法同第 1 步,可以发现p[2]没用了,直接让p[2] = p[3],然后继续循环

    ③否则若p[3] <= p[1],这里需要再次分情况讨论,讨论p[3]的下一个元素p[4],需要注意的是下面的所有情况中p[3]永远小于等于前面的两个元素

        1)若p[4] > p[2],查找成功,即p[1] < p[2] < p[4]

        2)否则若p[2] > p[4] > p[3],发现 p[3] < p[1] 和 p[4] < p[2] 且p[3], p[4]是一个新的二元递增子序列,思路仍然同第  1 步,前面的p[1]和p[2]没有任何用处了,直接让p[1] = p[3], p[2] = p[4],然后继续循环

        3)否则p[4] < p[3],思路同第 1 步,可以发现p[3]没有任何用处,直接让p[3] = p[4],然后继续循环

代码:

const auto _nouse = [](){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    return nullptr;
}();
class Solution
{
public:
    bool increasingTriplet(vector<int>& nums)
    {
        int size = nums.size();
        if (size < 3)
            return false;
        int p[5] = {0, 0, 1, 2, 3};
        while (max(max(p[1], p[2]), p[3]) < size)
        {
            while (p[3] < size && nums[p[2]] <= nums[p[1]])
            {
                p[1]++;
                p[2]++;
                p[3]++;
            }
            if (p[3] >= size)
                return false;
            if (nums[p[3]] > nums[p[2]])
            {
                return true;
            }
            if (nums[p[3]] > nums[p[1]])
            {
                p[2] = p[3];
                p[3]++;
                continue;
            }
            p[4] = p[3] + 1;
            if (p[4] >= size)
                return false;
            if (nums[p[4]] > nums[p[2]])
            {
                return true;
            }
            if (nums[p[4]] > nums[p[3]])
            {
                p[1] = p[3];
                p[2] = p[4];
                p[3] = p[2]+1;
                p[4] = p[3]+1;
                continue;
            }
            p[3] = p[4];
            p[4]++;
        }
        return false;
    }
};

细节, 比如越界检查和如何返回之类的注意一下就行

提交后, 耗时4ms, 战胜99.27%的C++代码. 不过例子里很多都用的不是O(n)的时间复杂度和O(1)的空间复杂度. 这个需要到时候按情况取舍.要想出完美的答案必定要耗费很多时间

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值