码迷,mamicode.com
首页 > 编程语言 > 详细

浅谈递归--数组添加

时间:2020-09-09 18:50:07      阅读:38      评论:0      收藏:0      [点我收藏+]

标签:list   sort   十分   i++   image   info   字符串   rar   ret   

首先,我们上一篇说到了递归的二叉树套路,但是递归还有一种更常见的类型,就是题目我们要找到所有有可能的集合,这种类型我称之为"数组添加"。当然我现在这么说,可能你们看得也很懵,但是我举几个例子你们就懂了。我从leetcode里面找来了几道题目:

①给定一个数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。

candidates 中的每个数字在每个组合中只能使用一次。

输入: candidates = [10,1,2,7,6,1,5], target = 8,
所求解集为:
[
  [1, 7],
  [1, 2, 5],
  [2, 6],
  [1, 1, 6]
]

  这一道题需要找的是所有能够组成目标数的数组的集合,因为组成target的数字数量是没有限定的,所以如果我们用循环语句去写的话,那代码会十分的臃肿和庞大。此时我们就用递归来解决这个问题。而这种类型的题目就是十分典型的“数组添加”类型。

  我们解决这道题的思路就是,当我们选好candidates[index]当可能组成target的集合时,我们以这个数字为开头,去不断尝试candidates[index]的下一个下标当集合的第二个数字。递归就解决了臃肿的循环代码,因为题目给的不同集合时长度不同,循环的长度也不确定。(在这里我们优化一下代码,我们先把集合排好序,因为这个例子不太好画图,所以我把数据改了一下)

  技术图片

 

 

 而当我们在第一个数字选择①时,我们的递归过程就是这样,而当我们选择第二个小标②时,又是一次递归过程,所以我们的递归里面有一个循环语句,而base case就是把我们已经收集到的集合list的sum== target,就将list加到整个大的List<List<Integer>>,这就是几乎所有这种题目的套路,递归,base case就是把集合收集到,最后加到返回的list集合里面。

public List<List<Integer>> combinationSum2(int[] candidates, int target) {
        Arrays.sort(candidates);
        List<List<Integer>> resList = new ArrayList<>();
        List<Integer> list = new ArrayList<>();
        process(candidates, target , 0, list, resList);
        return resList;
    }
    public void process(int[] candidates, int target,int index ,List<Integer> list,List<List<Integer>> resList){
        if(target == 0){
            resList.add(list);
            return;
        }
        if(index == candidates.length||target<0){
            return;
        }
    //递归里面的循环语句
for(int i = index ; i < candidates.length ; i++){ if(i>index && candidates[i]==candidates[i-1]){ continue; } List<Integer> temp = new ArrayList<>(list); temp.add(candidates[i]); process(candidates,target-candidates[i],i+1,temp,resList); } }

②给定一个 没有重复 数字的序列,返回其所有可能的全排列。

输入: [1,2,3]
输出:
[
  [1,2,3],
  [1,3,2],
  [2,1,3],
  [2,3,1],
  [3,1,2],
  [3,2,1]
]

这个题目跟上一题是差不多的,也是在递归体里面需要加循环语句,而全排列就是也是我们去选可能的集合,当我们选择集合的下标0的数字当第一个数字时,还有当我们选择集合的下标1的数字当第一个数字时.......这个就是递归里面的循环语句的意思.我们也不难发现,我们的base case也是把我们可能的集合添加的最后要返回的大集合List<List<Integer>>。而这里的swap()也是当我们递归的时候的时候需要把它交换的数字给交换回来。

public List<List<Integer>> permute(int[] nums) {
        List<List<Integer>> resList = new ArrayList<>();
		List<Integer> list = new ArrayList<>();
		process(nums, resList, list, 0);
		return resList;
	}
	public void process(int[] nums , List<List<Integer>> resList , 
						 List<Integer> list , int index) {
		if (index == nums.length) {
			resList.add(list);
		}
		for (int i = index; i < nums.length; i++) {
			swap(nums, index, i);
			List<Integer> tem = new ArrayList<>(list);
			tem.add(nums[index]);
			process(nums, resList, tem, index+1);
            swap(nums, index, i);
		}
	}
	public void swap(int[] nums, int i ,int j){
		int temp = nums[i];
		nums[i] = nums[j];
		nums[j] = temp;
	}

  

 

③给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。就是手机上的九宫格输入法。

输入:"23"
输出:["ad", "ae", "af", "bd", "be", "bf", "cd", "ce", "cf"].

这道题也跟上面的类似,当时它递归里面的循环语句不一样,他不是用for语句,而是用到了switch语句。这里不多赘述了。

public static List<String> letterCombinations(String digits){
		List<String> list = new ArrayList<>();
		char[] ch = digits.toCharArray();
		char[] path = new char[ch.length];
		process(ch, path, 0, list);
		return list;
	}
	public static void process(char[] ch, char[] path, int index, List<String> list){
 		if (index == ch.length) {
			list.add(new String(path));
			return;
		}
		switch (ch[index]) {
		case ‘2‘:
			path[index] = ‘a‘;
			process(ch, path,index+1, list);
			path[index] = ‘b‘;
			process(ch, path,index+1, list);
			path[index] = ‘c‘;
			process(ch, path,index+1, list);
			break;
		case ‘3‘:
			path[index] = ‘d‘;
			process(ch, path,index+1, list);
			path[index] = ‘e‘;
			process(ch, path,index+1, list);
			path[index] = ‘f‘;
			process(ch, path,index+1, list);
			break;
		case ‘4‘:
			path[index] = ‘g‘;
			process(ch, path,index+1, list);
			path[index] = ‘h‘;
			process(ch, path,index+1, list);
			path[index] = ‘i‘;
			process(ch, path,index+1, list);
			break;
		case ‘5‘:
			path[index] = ‘j‘;
			process(ch, path,index+1, list);
			path[index] = ‘k‘;
			process(ch, path,index+1, list);
			path[index] = ‘l‘;
			process(ch, path,index+1, list);
			break;
		case ‘6‘:
			path[index] = ‘m‘;
			process(ch, path,index+1, list);
			path[index] = ‘n‘;
			process(ch, path,index+1, list);
			path[index] = ‘o‘;
			process(ch, path,index+1, list);
			break;
		case ‘7‘:
			path[index] = ‘p‘;
			process(ch, path,index+1, list);
			path[index] = ‘q‘;
			process(ch, path,index+1, list);
			path[index] = ‘r‘;
			process(ch, path,index+1, list);
			path[index] = ‘s‘;
			process(ch, path,index+1, list);
			break;
		case ‘8‘:
			path[index] = ‘t‘;
			process(ch, path,index+1, list);
			path[index] = ‘u‘;
			process(ch, path,index+1, list);
			path[index] = ‘v‘;
			process(ch, path,index+1, list);
			break;
		case ‘9‘:
			path[index] = ‘w‘;
			process(ch, path,index+1, list);
			path[index] = ‘x‘;
			process(ch, path,index+1, list);
			path[index] = ‘y‘;
			process(ch, path,index+1, list);
			path[index] = ‘z‘;
			process(ch, path,index+1, list);
			break;
		default:
			break;
		}
	}

  

浅谈递归--数组添加

标签:list   sort   十分   i++   image   info   字符串   rar   ret   

原文地址:https://www.cnblogs.com/carryup/p/13580285.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!