leetcode刷题记录-334. 递增的三元子序列顺带学习贪心算法

739 阅读1分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

前言

今天做完leetcode的每日一题,顺带学习了一下贪心算法的分而治之的思想。

题目描述

今天的题目为leetcode上的 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 = [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 <= 5 * 105
  • -231 <= nums[i] <= 231 - 1  
  • 进阶:你能实现时间复杂度为 O(n) ,空间复杂度为 O(1) 的解决方案吗?

贪心算法

贪心算法的根本思想就是一个问题如果暂时找不到它的最优解,可以考虑把它拆成几个小的问题,分别求出每个小问题的最优解,然后将他们叠加起来,当作整个问题的“最优解”。

贪心算法的三个步骤

  1. 明确什么是我们需要的最优解

  2. 分析子问题,并且明确子问题的最优解

  3. 分别求出子问题的最优解然后叠加出全局最优解

贪心算法的示例

贪心算法有一个经典的例子,就是背包问题:

有一个背包,最多能承载150斤的重量,现在有7个物品,重量分别为[35, 30, 60, 50, 40, 10, 25],它们的价值分别为[10, 40, 30, 50, 35, 40, 30],应该如何选择才能使得我们的背包背走最多价值的物品?

  1. 首先明确我们需要的最优解--带走价值最多的物品
  2. 局部最优解就有多种不同的选择,可以选择价值最高的,或者重量最轻的,又或者性价比最高的
  3. 根据选择的不同选取不同的物品

使用情况

  1. 全局最优解不好取得
  2. 全局最优解的数学模型难以建立
  3. 没必要取得最优解,可以接受接近最优的比较优的解答

看完了贪心算法的简单介绍,接下来回到题目中去运用

题解

分析

题目要求要三个一组的递增子序列,我们会发现三个一组并不好求得,但是我们可以先定好两个大小和下标都满足递增的子序列,然后遍历去查找第三个满足条件的值。

这就是运用了贪心算法的思想,三个子序列不好找,那就拆分问题,优先去找到满足条件的两个子序列,再去查找第三个。

所以我们维护两个变量first和second分别代表递增三元子序列的第一个和第二个数,并且一直满足first<second。接着对数组nums进行遍历操作,去查找满足条件的第三个数。

在初始化的时候,first = nums[0], second = +∞, 在遍历的过程中每一次遍历进行如下查找:

  1. 如果num[i] > second, 那就找到了我们需要的第三个数,返回true
  2. 否则的话,就判断num[i] > first, 那么就将second的值更新
  3. 再不然,就说明num[i]比现在的两个数都要小,将num[i]赋值给first 遍历完成之后都没有找到第三个数,那就说明数组中不存在这个情况,返回false

可以会奇怪,要是在second的位置后面出现了小于second的值,那么first的下标不就会变得比second大了吗,这并没有关系,因为我们知道在这之前存在一个数是小于second的,所以哪怕之后立马出现了第三个数,那么还是会存在这样一个三元子序列满足条件,也会返回true

代码

/**
 * @param {number[]} nums
 * @return {boolean}
 */
var increasingTriplet = function(nums) {
    if (nums.length < 3) {
        return false;
    }
    let first = nums[0], second = Number.MAX_VALUE;
    for (let i = 1; i < nums.length; i++) {
        if (nums[i] > second) {
            return true;
        } else if (nums[i] > first) {
            second = nums[i];
        } else {
            first = nums[i];
        }
    }
    return false;
};