zoukankan      html  css  js  c++  java
  • [Leetcode] 第334题 递增的三元子序列

    一、题目描述

    给定一个未排序的数组,判断这个数组中是否存在长度为 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

    二、题目分析和代码实现

    1、第一种方法——最直接的思路

    1)采用动态规划的方法,dp[i]代表以nums[i]为结尾的递增子序列长度
    2)dp[i]=max{dp[j]+1},j<i&&nums[j]<nums[i]
    3)时间复杂度为n*n

     1 class Solution {
     2 public:
     3     bool increasingTriplet(vector<int>& nums) {
     4         int n = nums.size();
     5         if (n < 3)return false;
     6         vector<int>dp(n, 1);
     7         for (int i = 1; i < n; ++i) {
     8             for (int j = 0; j < i; ++j) {
     9                 if (nums[j] < nums[i])
    10                     dp[i] = max(dp[i], dp[j] + 1);
    11             }
    12             if (dp[i] == 3)return true;
    13         }
    14         return false;
    15     }
    16 };

    2、符合题目要求的方法——最佳思路,但是比较难想

    1)用两个数字m1代表当前最小的数,m2代表遍历到现在第二小的数,m2的位置不一定要在m1之后
    2)那么当发现一个数大于m2的数的时候,就直接返回true
    3)时间复杂度为n,空间复杂度为常数

     1 class Solution {
     2 public:
     3     bool increasingTriplet(vector<int>& nums) {
     4         int n = nums.size();
     5         int m1 = INT_MAX, m2 = INT_MAX;
     6         for (int i = 0; i < n; ++i) {
     7             if (nums[i] <= m1)m1 = nums[i];
     8             else if (nums[i] <= m2)m2 = nums[i];//要注意等号,也就是遇到相等的也要向后移动
     9             else return true;
    10         }
    11         return false;
    12     }
    13 };

    3)另一种方法——思路很赞

    1)Min[i]代表从0到i的最小值,Max[i]代表从i到n的最大值
    2)如果nums[i]大于Min[i-1]并且小于Max[i+1],那么就返回真
    3)时间复杂度为n,空间复杂度为n

     1 class Solution {
     2 public:
     3     bool increasingTriplet(vector<int>& nums) {
     4         int n = nums.size();
     5         if (n < 3)return false;
     6         vector<int> Min(n), Max(n);
     7         int i;
     8         Min[0] = nums[0], Max[n - 1] = nums[n - 1];
     9         for (i = 1; i < n; ++i) {
    10             Min[i] = min(Min[i - 1], nums[i]);
    11             Max[n - 1 - i] = max(Max[n - i], nums[n - 1 - i]);//注意下标
    12         }
    13         for (int i = 1; i < n - 1; ++i) {
    14             if (nums[i] > Min[i - 1] && nums[i] < Max[i + 1])
    15                 return true;
    16         }
    17         return false;
    18     }
    19 };
  • 相关阅读:
    Android listview 的应用
    Android 创建自定义布局
    Android Dialog
    android ProgressBar
    Lilac Pwn stack4-stack_pivoting Writeup
    CTFHUB Pwn ret2shellcode Writeup
    Lilac Pwn stack3-rop Writeup
    函数调用过程与栈帧结构
    线性回归及Python实现
    Google Kick Start Round A 2020
  • 原文地址:https://www.cnblogs.com/zhizhiyu/p/10220426.html
Copyright © 2011-2022 走看看