数据结构与算法-2.递增的三元子序列

2、递增的三元子序列

题目

给你一个整数数组 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 <= 10^5
  • -2^31 <= nums[i] <= 2^31 - 1

2.0、暴力解法

内容太过于暴力,就不写了,好像也是挺复杂的

2.1、贪心算法(自己第一次写的)

挺丢人的,写的又臭又长。。。

核心思想就是先找到第一和第二点,然后动态维护这两个点

数据结构与算法-2.递增的三元子序列_第1张图片

bool increasingTriplet(vector& nums)
{
    if (nums.size() < 3)return false;           //如果数组大小小于3,直接返回false

    int firstNode = 0, secondNode = 0;          //数值相同代表空
    int newBeginIndex = 0;
    int tempNode = 0;
    for (size_t i = 1; i < nums.size(); i++)    //找到第一和第二点
    {
        newBeginIndex = i + 1;
        if (nums[i] > nums[i - 1])
        {
            firstNode = nums[i - 1];
            secondNode = nums[i];
            tempNode = secondNode;
            break;
        }
    }
    for (int i = newBeginIndex; i < (int)nums.size(); i++)
    {
        if (nums[i] > secondNode)return true;   //第三点大于第二点直接返回true

        if (tempNode == secondNode)
        {
            if (nums[i] > firstNode)
            {
                secondNode = nums[i];
                tempNode = secondNode;
            }
            else
            {
                tempNode = nums[i];
            }
        }
        else
        {
            if (nums[i] <= tempNode)
                tempNode = nums[i];
            else
            {
                firstNode = tempNode;
                secondNode = nums[i];
            }
        }
    }
    return false;
}

时间复杂度:O(n)

空间复杂度:O(1)

虽然写的很拉,但是就是跑得快(比下面的快),咱也不知道为什么。

2.2、贪心算法(优化)

第一次写的很臃肿,仔细观察可以发现那个tempNode就是个多余

这里就简单粗暴了

  • 有比secondNode大的,直接返回true(得益于最初把firstNode,secondNode都设为最大)
  • 有比firstNode大比secondNode小的(或等于),直接换secondNode,这个和上面图解一样
  • 有比firstNode小的(或等于),直接换firstNode,关键是这个,这里其实就是取代了tempNode的位置
    • 下一个数比secondNode大,返回true
    • 下一个数比firstNode小,firstNode继续换
    • 下一个数比firstNode大,secondNode换

***完全满足上面画的图***可以看作是上面代码的简化版

bool increasingTriplet2(vector& nums)
{
    if (nums.size() < 3)return false;           //如果数组大小小于3,直接返回false

    int firstNode = INT_MAX, secondNode = INT_MAX;

    for (auto& i : nums)
    {
        if (i > secondNode)return true;
        if (i <= firstNode)
            firstNode = i;
        else
            secondNode = i;
    }
    return false;
}

时间复杂度:O(n)

空间复杂度:O(1)

你可能感兴趣的:(数据结构与算法,1024程序员节)