lecture-7 递归
1、例题--排列 Permutation
Given a collection of distinct numbers, return all possible permutations.
For example,
[1,2,3] have the following permutations:
[1,2,3], [1,3,2], [2,1,3], [2,3,1], [3,1,2], and [3,2,1].
public List<List<Integer>> permute(int[] nums) {
// Implement this method.
}
1)边界条件:组合问题,输入为空,输出为空;其他情况都是正常的。
2)思路:第一个位置先选一个数,第二位置从剩下的两个数里面选一个数,第三个位置只能选最后一个数。
那么N个数的Level-N问题这样化简:第一个位置从N个数里面选择一个,剩余N-1位置和N-1个数,生成一个Level-(N-1)的问题,形成递归。
3)代码实现
public List<List<Integer>> permute(int[] nums) {
List<List<Integer>> numList = new ArrayList<Integer>(); ///错误的new ArrayList<ArrayList<Integer>>()
Arrays.sort(nums);//排序有什么用?跟大小没有关系.. 有重复数字的情况会有用。
for (int i = 0 ; i < nums.length; i++) {
numList.add(nums[i]); ///将数组转换为Arraylist,方便后面操作
}
return permutes(new ArrayList<Integer>(); numList);
}
/*先实现递归函数主体*/
public List<List<Integer>> permutes(ArrayList<Integer> cur, ArrayList<Integer> nums) {
List<List<Integer>> results = new ArrayList<ArrayList<Integer>>();
if (0 == nums.size()) {
///ArrayList<Integer> result = new ArrayList<>(cur); ///不需要这一行,因为上一层函数已经申请了新的内存空间
results.add(result);
return results;
}
for (int i = 0; i < nums.size(); i++) {
List<Integer> newCur = new ArrayList<>(cur);
newCur.add(nums.get(i));
List<Integer> newNum = new ArrayList<>(nums);
newNums.remove(i);
result.addAll(permutes(newCur, newNum));
}
return results;
}
4)时间复杂度:O(n!);空间复杂度:O(n!)---空间复杂度似乎不准
5)其他解法
a)
public List<List<Integer>> permute(int[] nums) {
List<List<Integer>> numList = new List<Integer>();
for (int i = 0 ; i < nums.length; i++) {
numList.add(nums[i]);
}
return permutes(new List<Integer>(); numList);
}
public List<List<Integer>> permutes(List<Integer> cur, List<Integer> num) {
List<List<Integer>> results = new ArrayList<Integer>();
if (0 == num.size()) {
List<Integer> result = new ArrayList<Integer>(cur); //这里申请新内存保持结果,因为上层函数没有申请,只有一个cur在传递。
results.add(result);///可以简化一下 results.add(new ArrayList<Integer>(cur))
return results;
}
for (int i = 0; i < num.size(); i++) {
cur.add(num.get(i));
num.remove(i);
results.addAll(permutes(cur, num));
num.add(cur.get(cur,size() - 1));///没有申请新内存,所以要恢复现场
cur.remove(cur.size() - 1);
}
return results;
}
b)
public ArrayList<ArrayList<Integer>> permute(int[] num) {
ArrayList<ArrayList<Integer>> results = new ArrayList<Integer>();
Arrays.sort(nums);
return permutes(new ArrayList<Integer>(), nums);
}
public ArrayList<ArrayList<Integer>> permutes(ArrayList<Integer> cur, int[] nums) {
ArrayList<ArrayList<Integer>> results = new ArrayList<Integer>();
if (cur.size() == nums.length) {
ArrayList<Integer> result = new ArrayList<Integer>(cur);
results.add(result); ///可以简化一下 results.add(new ArrayList<Integer>(cur))
return results;
}
for (int i = 0; i < nums.length; i++) {
if (!cur.contains(nums[i])) {
cur.add(num[i]);
results.addAll(permutes(cur, nums));
cur.remove(cur.size() - 1);
}
}
}
c)Use the num array to serve as the "cur"
[0..index-1] means we have already set the first index
numbers
[index..length-1] are the numbers that we haven't set
Example: [4, 3, 5, 8, 1]
choose 8, then swap (4, 8) => [8, 3, 5, 4, 1]
choose 3, do nothing => [8, 3, 5, 4, 1]
choose 1, then swap (5, 1) => [8, 3, 1, 4, 5]
choose 5, then swap (4, 5) => [8, 3, 1, 5, 4]
choose 4, do nothing, => [8, 3, 1, 5, 4]
public ArrayList<ArrayList<Integer>> permute(int[] nums) {
ArrayList<ArrayList<Integer>> results = new ArrayList<Integer>();
Arrays.sort(nums);
permutes(results, nums, 0);
return results;
}
public void permutes(ArrayList<ArrayList<Integer>> results, int[] nums, int index) {
if (index == nums.length) {
ArrayList<Integer> result = new ArrayList<>();
for (int i = 0; i < nums.length; i++) {
result.add(nums[i]);
}
results.add(result);
return;
}
for (int i = index; i < nums.length; i++) {
swap(nums, index, i);
permutes(results, nums, index + 1);
swap(nums, i, index);
}
return;
}
public void swap(int[] nums, int i, int j)
2、组合--Combination
Given a collection of distinct numbers, return all possible combinations.
For example,
[2, 6, 8] have the following permutations:
[], [2], [6], [8], [2, 6], [2, 8], [6, 8], [2, 6, 8].
public List<List<Integer>> combine(int[] nums) {
// Implement this method.
}
1)边界条件:空集合;输入为空能在正常流程里面处理吗?
2)思路:对于第一个数2有两种情况,选择或者不选择;然后再对[6,8]进行组合。那么对于Level-N的问题,先对第一个数进行选择/不选择,然后对剩余N-1个数进行组合,这样就化为Level-(N-1),形成了递归。
3)代码实现:
public List<List<Integer>> combine(int[] nums) {
return combines(new ArrayList<Integer>(), nums, 0);
}
public List<List<Integer>> combines(List<Integer> cur, int[] nums, int index) { ---把结果当做出参
List<List<Integer>> results = new ArrayList<>();
if (index == nums.length) {
results.add(new ArrayList<Integer>(cur)); //上一层没有申请内存,这一层申请
return results;
}
results.addAll(combines(cur, nums, index + 1));
cur.add(nums[index]);
results.addAll(combines(cur, nums, index + 1));
cur.remove(cur.size() - 1); //恢复现场
}
4)时间复杂度:O(2^n);空间复杂度:O(2^n)?
其他解法:把结果当做入参
public List<List<Integer>> combine(int[] nums) {
List<List<Integer>> results = new ArrayList<>();
combines(results, new ArrayList<Integer>(), 0);
return results;
}
public void combines(List<List<Integer>> results, List<Integer> cur, int[] nums, int index) {
if (index == nums.length) {
results.add(cur);//直接添加,上一层已经申请了新内存。
return;
}
List<Integer> newCur1 = new ArrayList<>(cur);
combines(results, newCur1, nums, index + 1);
List<Integer> newCur2 = new ArrayList<>(cur);//得申请两个新内存,不然也会互相覆盖。申请两个就不用恢复现场了。
newCur2.add(nums[index]);
combines(results, newCur2, index + 1);
return;
}
lecture-7 递归的更多相关文章
- [C2P3] Andrew Ng - Machine Learning
##Advice for Applying Machine Learning Applying machine learning in practice is not always straightf ...
- Cs231n课堂内容记录-Lecture 8 深度学习框架
Lecture 8 Deep Learning Software 课堂笔记参见:https://blog.csdn.net/u012554092/article/details/78159316 今 ...
- 【cs224w】Lecture 1 & 2 - 图的性质 及 随机图
目录 Lecture 1: Introduction Lecture 2: Properties and Random Graph Degree Distribution Path Length Cl ...
- .NET 基础 一步步 一幕幕[面向对象之方法、方法的重载、方法的重写、方法的递归]
方法.方法的重载.方法的重写.方法的递归 方法: 将一堆代码进行重用的一种机制. 语法: [访问修饰符] 返回类型 <方法名>(参数列表){ 方法主体: } 返回值类型:如果不需要写返回值 ...
- 算法笔记_013:汉诺塔问题(Java递归法和非递归法)
目录 1 问题描述 2 解决方案 2.1 递归法 2.2 非递归法 1 问题描述 Simulate the movement of the Towers of Hanoi Puzzle; Bonus ...
- Android 算法 关于递归和二分法的小算法
// 1. 实现一个函数,在一个有序整型数组中二分查找出指定的值,找到则返回该值的位置,找不到返回 -1. package demo; public class Mytest { public st ...
- 二叉树的递归实现(java)
这里演示的二叉树为3层. 递归实现,先构造出一个root节点,先判断左子节点是否为空,为空则构造左子节点,否则进入下一步判断右子节点是否为空,为空则构造右子节点. 利用层数控制迭代次数. 依次递归第二 ...
- 递归实现n(经典的8皇后问题)皇后的问题
问题描述:八皇后问题是一个以国际象棋为背景的问题:如何能够在8×8的国际象棋棋盘上放置八个皇后, 使得任何一个皇后都无法直接吃掉其他的皇后?为了达到此目的,任两个皇后都不能处于同一条横行.纵行或斜线上 ...
- C语言用分别用递归和循环求数字的阶乘的方法
以下代码均为 自己 实现,嘻嘻! 参考文章:http://blog.csdn.net/talk_8/article/details/46289683 循环法 int CalFactorial(int ...
- C#递归解决汉诺塔问题(Hanoi)
using System;using System.Collections.Generic;using System.Linq;using System.Text; namespace MyExamp ...
随机推荐
- python 3中使用getattr和*args时, 出现传入参数不一致的问题
今天在用python3的getattr时遇到一个问题, 就是老提示传入参数和函数前面不一致, 代码为: class Test: def __init__(self, name): ...
- HDOJ1025(最长上升子序列)
Constructing Roads In JGShining's Kingdom Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65 ...
- C#设计模式(12)——享元模式
一.概念 外观模式提供了一个统一的接口,用来访问子系统中的一群接口.外观定义了一个高层接口,让子系统更容易使用.使用外观模式时,我们创建了一个统一的类,用来包装子系统中一个或多个复杂的类,客户端可以直 ...
- shell入门-grep2
案例介绍 搜索关键词带‘root’的行 并输出行号 [root@wangshaojun ~]# cg -n 'root' 1.txt1:root:x:0:0:root:/root:/bin/bash1 ...
- javaScript之Array方法
Array类型和其他语言一样,是数据的有序列表,但不同的是数组的每一项们可以保存任何类型的数据. 1.检测方法(确定某个对象是不是数组) (1)value instanceof Array (2)Ar ...
- nodejs PK php全方位比较PHP的Node.js的优缺点
全方位比较PHP的Node.js的优缺点 http://www.techug.com/php-vs-node-js
- [hdu1402]A * B Problem Plus(NTT)
解题关键:快速数论变换NTT模板. 注意$ans$数组的$ans[n]$一定要注意置$0$,或者结果从$n-1$开始遍历,这里很容易出错. 代码1:ACdreamer 的板子. 为什么要reverse ...
- R语言:文本(字符串)处理与正则表达式
R语言:文本(字符串)处理与正则表达式 (2014-03-27 16:40:44) 转载▼ 标签: 教育 分类: R 处理文本是每一种计算机语言都应该具备的功能,但不是每一种语言都侧重于处理文本.R语 ...
- Tomcat 如何部署多个应用
Tomcat 如何部署多个应用 https://blog.csdn.net/tdcqfyl/article/details/51966387
- 通俗地讲,Netty 能做什么?
https://www.zhihu.com/question/24322387/answer/78947405 作者:郭无心链接:https://www.zhihu.com/question/2432 ...