给定一个未排序的数组,判断这个数组中是否存在长度为 3 的递增子序列。
数学表达式如下:
如果存在这样的 i, j, k, 且满足 0 ≤ i < j < k ≤ n-1,
使得 arr[i] < arr[j] < arr[k] ,返回 true ; 否则返回 false 。
说明: 要求算法的时间复杂度为 O(n),空间复杂度为 O(1) 。
示例 1:
输入: [1,2,3,4,5] 输出: true
示例 2:
输入: [5,4,3,2,1] 输出: false
解题思路:
逻辑题。
- 找到一个递增数num[pos],例如,[5,4,3,4,5,6,]中第4个数4就是第一个递增数。
- 第一个递增数的前面必然是当前遇到的最小数。如果不是那么nums[pos-1]才是第一个递增数。如果连递增数都没有,就不可能有三连递增。
- 这里我们确定了二元递增的两个数,nums[left],nums[right],其中left=pos-1,right=pos。以及最小数的位置temp,一开始nums[temp]=nums[pos-1]。
- 随后接着访问pos+1,nums[pos+1]需要根据数值de得大小分类处理。
- nums[pos+1]>nums[right],那么找到了三元序列。
- nums[pos+1]>nums[left]&&nums[pos+1]<=nums[right]。修改二元序列得右值,right = pos+1;
- nums[pos+1]<=nums[temp]。修改位于left之后最小数得位置。temp=pos+1。
- nums[pos+1]>nums[temp]&&nums[pos+1]<=nums[left],说明,发现了位置跟后,数值更小得得二元序列,二元序列需要改变位置。left = temp,right=pos+1。
重复上述步骤直到访问所有元素。
class Solution { public: bool increasingTriplet(vector<int>& nums) { int size = nums.size(); //找到第一个升序 int i = 0, pos = -1, min = INT_MAX; while (i < size-1) { if (nums[i] < nums[i + 1]) { pos = i; break; } min = (nums[i] < min ? nums[i] : min); i++; } if (pos == -1) return false; int left = i, right = i + 1; pos = right + 1; int temp = left; while (pos < size) { if (nums[pos]>nums[right]) return true; if (nums[pos] <= nums[temp]) temp = pos; if (nums[pos] > nums[temp] && nums[pos] <= nums[left]) { left = temp; right = pos; } if (nums[pos] >nums[left] && nums[pos] <= nums[right]) right = pos; pos++; } return false; } }; |