Java 求解递增子序列

Posted 南淮北安

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java 求解递增子序列相关的知识,希望对你有一定的参考价值。

一、题目

给定一个整型数组, 你的任务是找到所有该数组的递增子序列,递增子序列的长度至少是 2 。

二、题解

而本题求自增子序列,是不能对原数组进行排序的,排完序的数组都是自增子序列了

所以不能使用之前的去重逻辑:加一个标记数组去重

(1)递归函数参数
本题求子序列,很明显一个元素不能重复使用,所以需要 startIndex,调整下一层递归的起始位置。

(2)终止条件
本题其实类似求子集问题,也是要遍历树形结构找每一个节点,所以和回溯算法:求子集问题!一样,可以不加终止条件,startIndex每次都会加1,并不会无限递归。

但本题收集结果有所不同,题目要求递增子序列大小至少为2,所以代码如下:

if (deque.size() > 1) 
	// 不能直接 return,因为还没取完
	lists.add(new ArrayList<>(deque));

(3)单层搜索逻辑

从图中可以看出,同层使用过的元素就不能再使用了

因为本题只要同层重复使用元素,递增子序列就会重复,所以需要一个去重逻辑,但是和以前的相邻元素去重不一样,这里可以设置一个 set 集合,每一层每个元素存入一次

// 每一层都会创建一个 set 集合
Set<Integer> set = new HashSet<>();

还有一种情况就是如果选取的元素小于子序列最后一个元素,那么就不能是递增的,所以也要pass掉。

for (int i = startIndex; i < nums.length; i++) 
            if ((!deque.isEmpty() && deque.getLast() > nums[i])
                    || set.contains(nums[i])) 
                continue;
            

三、代码

class Solution 
    List<List<Integer>> lists = new ArrayList<>();
    Deque<Integer> deque = new LinkedList<>();

    public List<List<Integer>> findSubsequences(int[] nums) 
        backTrackeing(nums, 0);
        return lists;
    

    private void backTrackeing(int[] nums, int startIndex) 

        if (deque.size() > 1) 
            // 不能直接 return,因为还没取完
            lists.add(new ArrayList<>(deque));
        
        // 每一层都会创建一个 set 集合
        Set<Integer> set = new HashSet<>();
        for (int i = startIndex; i < nums.length; i++) 
            if ((!deque.isEmpty() && deque.getLast() > nums[i])
                    || set.contains(nums[i])) 
                continue;
            
            set.add(nums[i]);
            deque.addLast(nums[i]);
            backTrackeing(nums, i + 1);
            deque.removeLast();
        
    

四、总结

本题要求找数组的递增 子序列,所以和以前的不一样,不能排序,每一层节点只能存入一次,可以借助 set 集合

能够排序的:排序+标志数组
不能够排序:set 集合

以上是关于Java 求解递增子序列的主要内容,如果未能解决你的问题,请参考以下文章

Java 求解最长递增子序列

Java 求解最长连续递增序列

动态规划之最大递增子序列

动态规划求解最长递增子序列的长度

求解最长递增子序列(LIS) | 动态规划(DP)+ 二分法

动态规划之----最长递增子序列