力扣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<Integer> paths = new ArrayList();
        return backTracking(paths,nums,0);
    }
    private boolean backTracking(List<Integer> paths , int[] nums , int startIndex){
        if(paths.size() >= 3){
            return true;
        }
        for(int i = startIndex ; i < nums.length ; i++){     
            HashSet<Integer> 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;
    }
    
}

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值