[路飞]_递增的三元子序列

561 阅读1分钟

334. 递增的三元子序列

题目

给你一个整数数组 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 = [2,1,5,0,4,6]
输出:true
解释:三元组 (3, 4, 5) 满足题意,因为 nums[3] == 0 < nums[4] == 4 < nums[5] == 6

题解

双循环

对于数组nums = [2,1,5,0,4,6];

  • 通过从左到右遍历,构建当前值之前最小值数组left=[2,1,1,0,0,0];
  • 通过从右到左遍历,构建当前值之前最大值数组right=[6,6,6,6,6,6];
  • 再次从[1,nums.length-1]枚举nums值,如果在枚举过程中当前下标x;存在nums[i] > left[i] && nums[i] < right[i]; 返回true;

时间复杂度,因为枚举3次nums,所以时间复杂度为O(n);
空间复杂度;因为构建两个数组left,right,所以空间复杂度为O(n)

根据上述思路编辑代码如下

代码

var increasingTriplet = function (nums) {
  const len = nums.length
  const right = []
  right[len - 1] = nums[len - 1]
  for (let i = len - 2; i >= 0; i--) {
    const c = Math.max(right[i + 1], nums[i])
    right[i] = c
  }
  const left = [nums[0]]
  for (let i = 1; i < len; i++) {
    const c = Math.min(nums[i], left[i - 1])
    left[i] = c
  }
  for (let i = 1; i < len - 1; i++) {
    if (nums[i] > left[i] && nums[i] < right[i]) return true
  }
  return false
  
}

贪心

对于nums数组;找到3个连续递增的数;假设这3个数为x,y,z;

枚举过程中,在x < y的条件下,尽可能的降低y的值,保证找到z的可能性最大;

所以有任意nums[i],如果nums[i] <= x;更新x;如果num[i] >x && nums[i] <= y;更新y;如果nums[i] > y 返回true;否则返回false;

贪心,只用一次枚举即可解决问题

代码

var increasingTriplet = function (nums) {
  let n1 = nums[0]
  let n2 = Infinity
  for (let i = 1; i < nums.length; i++) {
    if (n1 >= nums[i]) {
      n1 = nums[i]
    } else if (n2 >= nums[i]) {
      n2 = nums[i]
    } else {
      return true
    }
  }
  return false
}