leetcode 491. Increasing Subsequences

来源:互联网 发布:淘宝鹊桥报名入口 编辑:程序博客网 时间:2024/05/17 21:06

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:

  1. The length of the given array will not exceed 15.
  2. The range of integer in the given array is [-100,100].
  3. The given array may contain duplicates, and two equal integers should also be considered as a special case of increasing sequence.
需要注意的是,题目中要求的是递增子序列。如果 input 是 [4,3,2,1],那么应当返回 空list。

我的思路是用递归with memory来做,返回 一定以某个索引元素开头 的序列集合。如 [3,3,1,4],先求以 index=0 开头的索引集合,发现3连续出现2次,前缀集合就是 [3] , [3,3],然后递归求出后缀:以 下一个>=1大的数 开头的序列集合,就是 [4] 。将前缀分别加到后缀 [4] 上,得到 [3,4] , [3,3,4] 。在求结果集合时,只要把 以每个索引为开头 的情况都考虑一下,就好了。对了,不要忘记 递增子序列长度要大于等于2,因此还要有过滤操作。

为什么最后要用hashset筛除重复序列呢?会出现重复序列吗?答案是肯定的,看如下例子。

如果input是 [1,5,1,1] 的话,以索引0开头的序列会出现:[1] , [1,1] , [1,1,1] ,而以索引2开头的序列会出现:[1] , [1,1] ,这就出现重复了。

public List<List<Integer>> findSubsequences(int[] nums) {List<List<Integer>> result=new ArrayList<List<Integer>>();HashSet<List<Integer>> set=new HashSet<List<Integer>>();HashMap<Integer, List<List<Integer>>> map=new HashMap<Integer, List<List<Integer>>>();for(int i=0;i<nums.length;i++){List<List<Integer>> list=helper(i, nums, map);for(List<Integer> tmp:list){if(tmp.size()>=2){if(!set.contains(tmp)){result.add(tmp);set.add(tmp);}}}}return result;}//返回一定以某个index元素开头的序列集合public List<List<Integer>> helper(int index,int[] nums,HashMap<Integer, List<List<Integer>>> map){if(map.get(index)!=null){return map.get(index);}List<List<Integer>> result=new ArrayList<List<Integer>>();int nextIndex=index+1;int count=1;//得到nums[index]数连续出现个数while(nextIndex<nums.length&&nums[nextIndex]==nums[index]){count++;nextIndex++;}for(int nowCount=1;nowCount<=count;nowCount++){List<Integer> tmp=new ArrayList<Integer>();for(int j=0;j<nowCount;j++){tmp.add(nums[index]);}result.add(tmp);}int prefixSize=result.size();while(nextIndex<nums.length){//得到下一个大于等于当前数的indexwhile(nextIndex<nums.length&&nums[nextIndex]<nums[index]){nextIndex++;}if(nextIndex<nums.length){List<List<Integer>> nextList=helper(nextIndex, nums, map);for(int i=0;i<prefixSize;i++){List<Integer> prefix=result.get(i);for(List<Integer> postFix:nextList){List<Integer> tmp=new ArrayList<Integer>(prefix);tmp.addAll(postFix);result.add(tmp);}}}//得到下一个不等于nextIndex的数int i=nextIndex+1;while(i<nums.length&&nums[i]==nums[nextIndex]){i++;}nextIndex=i;}return result;}
大神的方法比我快,也比我简洁多了。

使用set是为了避免重复,如 [1,2,3,2] 
如果不用set,output将会是 : [[1,2],[1,2,3],[1,2,2],[1,3],
[1,2],[2,3],[2,2]]
如果用set,output将会是 : [[1,2],[2,2],[1,3],[2,3],[1,2,3],[1,2,2]]

public class Solution {     public List<List<Integer>> findSubsequences(int[] nums) {         Set<List<Integer>> res= new HashSet<List<Integer>>();         List<Integer> holder = new ArrayList<Integer>();         findSequence(res, holder, 0, nums);         List result = new ArrayList(res);         return result;     }    public void findSequence(Set<List<Integer>> res, List<Integer> holder, int index, int[] nums) {        if (holder.size() >= 2) {            res.add(new ArrayList(holder));        }        for (int i = index; i < nums.length; i++) {            if(holder.size() == 0 || holder.get(holder.size() - 1) <= nums[i]) {                holder.add(nums[i]);                findSequence(res, holder, i + 1, nums);                holder.remove(holder.size() - 1);            }        }    }}