栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

力扣334题 递增的三元子序列

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

力扣334题 递增的三元子序列

334. 递增的三元子序列

给你一个整数数组 nums ,判断这个数组中是否存在长度为 3 的递增子序列。

如果存在这样的三元组下标 (i, j, k) 且满足 i < j < k ,使得 nums[i] < nums[j] < nums[k] ,返回 true ;否则,返回 false 。

 

解题思路:回溯、动态规划、贪心 

方法一:回溯(超时)

这个题类似于之前做过的求数组的递增子序列(长度大于3)的情况,并且只需要返回true和false。

代码和提交结果如下:

class Solution {
    public boolean increasingTriplet(int[] nums) {
        List paths = new ArrayList();
        return backTracking(paths,nums,0);
    }
    private boolean backTracking(List paths , int[] nums , int startIndex){
        if(paths.size() >= 3){
            return true;
        }
        for(int i = startIndex ; i < nums.length ; i++){     
            HashSet set = new HashSet();
            if(!set.add(nums[i])||(!paths.isEmpty() && nums[i] <= paths.get(paths.size()-1))){
                continue;
            }                  
                paths.add(nums[i]);
                if(backTracking(paths,nums,i+1)){
                    return true;
                }
                paths.remove(paths.size()-1);            
        }
        return false;
    }
}

总结:数组的长度太长了,1000000,所以回溯超时很正常,刚开始没有看数据量直接写的代码。 

方法二:动态规划

① 创建一个leftMin[nums.length]数组,用来存储数组每个位置的数左边的所有数以及包括自己本身在内的最小值。

② 创建一个rightMax[nums.length]数组,用来存储数组每个位置的数右边的所有数以及包括自己本身在内的最大值。

③ 遍历数组,如果nums[i] > leftMin[i-1] && nums[i] < rightMax[i+1],返回true,遍历完没有发现,返回false。

代码和提交结果如下:

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;
    }
}

方法三:贪心 ,O(n)时间复杂度,也不需要单独开数组

定义两个变量    int one = nums[0];int two = Integer.MAX_VALUE,然后从 i = 1 开始遍历数组,如果nums[i] > two,返回 true ,如果 two > nums[i] > first , two = nums[i] , 如果 nums[i] < first,first = nums[i] ,遍历结束之后如果没能返回 true,则意味着没找到,就返回false。

代码和提交结果如下图所示:

class Solution {
    public boolean increasingTriplet(int[] nums) {
        //贪心
        int first = nums[0];
        int second = Integer.MAX_VALUE;
        for(int 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;
    }
    
}

 总结:回溯在使用的时候一定要注意数据量。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/702516.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号