leetcode 491. Increasing Subsequences

257 篇文章 17 订阅

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){
		//得到下一个大于等于当前数的index
		while(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);
            }
        }
    }
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值