Leetcode 491. Increasing Subsequences 上升序列 解题报告

1 解题思想

hi,好久不见,最近有点忙,更新的很慢。
这道题是给了一个已经排好序的数组,让你找出所有的子序列,这些子序列要求同样是不下降的(就是i+1的数肯定大于等于i),相同的序列不能重复出现,但是允许某个数重复(所以是不重复)。

我给的是最简单的一个方式,直接回溯,递归去找,使用一个hashset去帮助筛选重复。这里我只加了一个小的优化,就是next,比如3776这样的,当指针在3时,会首先尝试第一个7,然后直接跳过第二个7到6,这样可以节省搜索。

这不是最优解,其实有个解法是:
统计独立出现的所有数和其频率
根据这个数再去生成结果,可以节省很多搜索时间,例如:
337789
Step1:统计 3:2,7:2,8:1,9:1
Step2:递归还原,每一步两个选择(意思是都要尝试),若当前的那个数使用的次数还够,那么-1后重复Step2,若还有下一个数,那么跳过当前数直接到下一个数

每一步Step2的时候,检查下长度,就可以加入到结果中了,而且这个不需要hashSet,不会重复的。

抱歉,我刚写的时候理解的不是很好,所以给的答案不是后面想到那种方式。
微博同名

2 原题

Given an integer array, your task is to find all the different possible increasing subsequences of the given array, and the length of an increasing subsequence should be at least 2 .

Example:
Input: [4, 6, 7, 7]
Output: [[4, 6], [4, 7], [4, 6, 7], [4, 6, 7, 7], [6, 7], [6, 7, 7], [7,7], [4,7,7]]
Note:
The length of the given array will not exceed 15.
The range of integer in the given array is [-100,100].
The given array may contain duplicates, and two equal integers should also be considered as a special case of increasing sequence.

3 AC解

public class Solution {
    /**
     * 这道题有个很好玩的点:那就是在hashset当中放入数组时,其检查的是这个数组里面的数值是否是一样的,而不是单纯按照对象的地址
     * */
    public List<List<Integer>> findSubsequences(int[] nums) {
        Set<List<Integer>> res= new HashSet<List<Integer>>();
        List<Integer> tmp = new ArrayList<Integer>();
        int[] next = new int[nums.length];
        for(int i=0;i<nums.length;i++){
            int my_next = i+1;
            while(my_next<nums.length && nums[i]==nums[my_next])
                my_next++;
            next[i] = my_next;
        }
        helper(res,tmp,nums,next,0);
        return new ArrayList<List<Integer>>(res);
    }

    /**
     * 采用回溯的方式不停地递归,寻找解决方法
     * 其实还有更简单的方式,但这里就不多说了
     * */
    private void helper(Set<List<Integer>> res,List<Integer> tmp,int[] nums,int[] next,int index){
        if(tmp.size() > 1){
            res.add(new ArrayList<Integer>(tmp));
        }
        int i=index;
        for(;i<nums.length;){
            if(tmp.size()==0 || tmp.get(tmp.size() - 1) <= nums[i]){
                tmp.add(nums[i]);
                helper(res,tmp,nums,next,i+1);
                tmp.remove(tmp.size() - 1);
            }
            //快速跳到下一个上
            i = next[i];
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值