当前位置: 首页 > news >正文

力扣练习之递增的三元子序列

题目:

给你一个整数数组 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

思路:

对于这个题有三个方法可以解决,但是其中有两个是会被判定为超时的

方法一:暴力枚举法:使用三个for循环,但这样会超时

        int len=nums.size();
        vector<int>res(len);
        vector<int>l(len),r(len);
        for(int i=0;i<len-2;i++){
            for(int j=i+1;j<len-1;j++){
                if(nums[i]<nums[j]){
                    for(int m=j+1;m<len;m++){
                    if(nums[j]<nums[m]){
                        return true;
                    }
                }

                }else continue;
                
            }
        }
        return false;

方法二:双指针

思路:比如当前所在位置是i,所代表的数字为b,那么有一个指针在其左侧,找到左侧最小的数a,另一个指针在右侧,找到右侧最大的数c,如果a<b<c成立,则返回true,否则的话返回false,这个思路是没有问题的,关键在于实现的方式

起初,使用了两个内嵌for循环,还是超时

        for(int i=0;i<len;i++){
            r[i]=nums[i];
            l[i]=nums[i];
        }
        for(int i=0;i<len;i++){
     
            for(int j=0;j<i;j++){
                l[i]=(l[i]>nums[j])?nums[j]:l[i];
            }
            for(int j=i+1;j<len;j++){
                r[i]=(r[i]<nums[j])?nums[j]:r[i];
            }
        }
        for(int i=0;i<len;i++){
            if(l[i]<nums[i]&&nums[i]<r[i]){
                return true;
            }
        }
        return false;

后来看了官方题解,发现思路是一样的,但是他实现的时间复杂度仅需O(n)

 我觉得他的实现方式类似于动态规划,

eg:l[i]肯定是在l[i-1]和nums[i-1]中选择一个较小的,因为l[i-1]代表的就是第i-1个元素值左边最小的数字了,只需要和第i-1个元素值比较一下,选取那个更小的就是第i个元素左侧最小的值了

实现代码为(此处为官方题解,自己写的找不到了,,,):

class Solution {
    public boolean increasingTriplet(int[] nums) {
        int n = nums.length;
        if (n < 3) {
            return false;
        }
        int[] leftMin = new int[n];
        leftMin[0] = nums[0];
        for (int i = 1; i < n; i++) {
            leftMin[i] = Math.min(leftMin[i - 1], nums[i]);
        }
        int[] rightMax = new int[n];
        rightMax[n - 1] = nums[n - 1];
        for (int i = n - 2; i >= 0; i--) {
            rightMax[i] = Math.max(rightMax[i + 1], nums[i]);
        }
        for (int i = 1; i < n - 1; i++) {
            if (nums[i] > leftMin[i - 1] && nums[i] < rightMax[i + 1]) {
                return true;
            }
        }
        return false;
    }
}

还有一种更为简单的是贪心算法,就是假设一定会有第一小和第二小的数字,初始化时分别将其设为first=nums[i] ,second=INT_MAX(别忘了需要加#include<climits>);遍历数组,如果当前值比second大,那说明它是目前第三小的数字,找到符合要求的答案,返回true即可。否则如果当前值比first大,那说明第二小的数字应是当前值,即second=nums[i],再否则的话,如果那说明他目前是第一小的数字,则应first=nums[i]

具体实现代码为:

 int len = nums.size();
        if (len < 3) {
            return false; // 如果数组长度小于 3,直接返回 false
        }

        int first = nums[0]; // 初始化第一个元素
        int second = INT_MAX; // 初始化第二个元素为最大值

        for (int i = 1; i < len; i++) {
            if (nums[i] > second) {
                return true; // 找到递增三元组
            } else if (nums[i] > first) {
                second = nums[i]; // 更新第二个元素
            } else {
                first = nums[i]; // 更新第一个元素
            }
        }

        return false; // 未找到递增三元组
   

 

 

相关文章:

  • Spring系列学习之Spring CredHub
  • 场内、场外期权怎么开户?期权佣金是多少?
  • linux上面安装 向量数据库 mlivus和 可视化面板Attu
  • sql深入学习
  • 自然语言处理:词频-逆文档频率
  • Token相关设计
  • Python之使用动态导包优化软件加载速度
  • Elasticsearch:过滤 HNSW 搜索,快速模式
  • 基于Flask的红袖网小说数据可视化分析系统
  • PostgreSQL中的外键与主键
  • ABAP语言的动态程序
  • ES6笔记总结
  • Vue的data配置项
  • springboot之HTML与图片生成
  • IP属地是通过卫星定位的吗?如何保护用户隐私
  • mysql-analyze table导致waiting for table flush
  • 【AI+智造】在阿里云Ubuntu 24.04上部署DeepSeek R1 14B的完整方案
  • Redis---缓存穿透,雪崩,击穿
  • GNN入门与实践——基于GraphSAGE在Cora数据集上的节点分类研究
  • 思维训练(算法+技巧)
  • 动态网站做登录界面/南京seo推广
  • 是网站建设专业好/关注公众号一单一结兼职
  • 学生成绩管理系统网站建设/网络企业推广
  • wordpress开发工作流/比较好的网络优化公司
  • 百度网站名称和网址/一份完整的市场调查方案
  • 做网站便宜/收录情况