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、贪心算法(自己第一次写的)
挺丢人的,写的又臭又长。。。
核心思想就是先找到第一和第二点,然后动态维护这两个点
bool increasingTriplet(vector<int>& 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<int>& 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)