leetcode递归练习总结
Posted adventure.Li
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了leetcode递归练习总结相关的知识,希望对你有一定的参考价值。
一、总结
二、题目
- 递归通用模板
(1)具有返回值型
int型 代表题目:斐波那、跳台阶、阶乘
集合型 代表题目:杨辉三角;Java注意记录时的加入引用与实例问题。
bool型 代表题目:2的幂、4的幂。
/**
* @param n 传入参数
* @param pos 当前递归位置
* @param val 计算参数,子集的异或问题参考
* @param flag 状态判断,N皇后问题
* @return
*/
T recursion(int n,int pos,int val,int []flag){ // flag可以boolean型
T t = new T();// 返回参数,根据需要声明设定
if(pos==flag.length){ // 终止条件,根据题目来定
// 处理
return t;//终止
}
if(flag[pos]==1){// 根据当前状态的情况进行处理
// 处理
}
// 递归进行
// 标志位处理
flag[pos] = 1;
recursion(n,pos+1,val*n,flag);
flag[pos] = 0;//标志位回退,--> 回溯模板
recursion(n,pos+1,val*n,flag);
return t;
}
(2)void型模板
List<String> record = new ArrayList<>();
// 树的遍历结构
void dfs(TreeNode treeNode,int n,int pos){
if(treeNode==null){
// 递归一次结束进行记录
// record.add(treeNode.val+"");
// record进行记录
return;//终止
}
// 进行处理数据treeNode
dfs(treeNode.left,n,pos+1);//向左
dfs(treeNode.right,n,pos+1);//向右
}
- 题目
----斐波那数-----
基本考察,采用简单的递归公式即可解决,解决代码如下。
但是,可以看到直接递归时间复杂度只能击败28.00%,如果题目样例再大一点应该就会超时了,因此此时就需要记忆优化来处理记录重复计算的步骤(也就是空间换时间,建议采用hash表同等情况下空间复杂度更低(比较map来说))。
另外,可能存在很大的数,此时一般会要求取余,直接取余即可。
其他同类型题目:
爬楼梯分析:当爬取一个楼梯则为该问题的n-1的数量,当爬取两个时则为n-2的问题规模,然后再讨论终止态一个或两个楼梯时的情况。
返回bool型
4的幂分析:当能整除4时则进行递推,直到问题规模为1或0,为1则true,为0则false。
boolean isPowerOfFour(int n){
if(n<=0){
return false;
}else{
if(n%4==0){
return isPowerOfFour(n/4);// 若是4的倍数则,进行递归 否则判断
}else if(n==1){// 本来就是1或除4到等于1
return true;
}else// 最终非1,说明非4的幂数
{
return false;
}
}
}
返回集合型
杨辉三角:获取numRows行数据,以列表返回。
List<List<Integer>> generate(int numRows) {
List<Integer> list = new ArrayList<>();
List<List<Integer>> lists = new ArrayList<>();
if(numRows<=1){
for(int i=0;i<numRows;i++)
{
list.add(1);
}
lists.add(list);
return lists;
}else{
lists = generate(numRows-1);
list = lists.get(lists.size()-1);
List<Integer> temp = new ArrayList<>();
temp.add(1);
for(int i=0;i<list.size()-1;i++){
temp.add(list.get(i)+list.get(i+1));
}
temp.add(1);
lists.add(temp);
return lists;
}
}
public List<Integer> getRow(int rowIndex) {
return generate(rowIndex+1).get(rowIndex);
}
—异或所有的子集和–
int res = 0;
// nums集合,pos当前的递归位置,val即为所求的值,通过外部变量进行带值出来
public void dfs(int[]nums,int pos,int val){
if(pos == nums.length){
res+=val;//记录总值,该次递归(或理解为搜索)结束,终止条件,开始处理记录数据
return ;
}
dfs(nums,pos+1,val^nums[pos]);//进行选择,进行对val的异或处理,pos+1
dfs(nums,pos+1,val);//不选择
}
public int subsetXORSum(int[] nums) {
dfs(nums,0,0);
return res;
}
关于子集的求法,还可以采用位运算。
官方的代码采用位运算,较为难理解,因此本人采用以下办法,也就是进行2^n次结果,每次结果需要进行len次选择,选择只有0或1 选取该数或者不选。因此遍历0-2^n-1然后判断选择情况即可。
class Solution {
List<List<Integer>> lists = new ArrayList<>();
//List<Integer> temp = new ArrayList<>();
void dfs(List<Integer> temp,int []nums,int idx){
if(idx==nums.length){
lists.add(new ArrayList<>(temp));// list加入构造??
return;
}
temp.add(nums[idx]);//选择当前
dfs(temp,nums,idx+1);
temp.remove((Object)nums[idx]);// 不选择
dfs(temp,nums,idx+1);
}
public List<List<Integer>> subsets(int[] nums) {
// List<Integer> temp = new ArrayList<>();
// dfs(temp,nums,0);
// return lists;
List<List<Integer>> allSet = new ArrayList<>();
List<Integer> tempSet = new ArrayList<>();
int len = nums.length;
for(int i = 0; i< Math.pow(2,len); i++){
tempSet.clear();//选择之前清理
int n = i;
for(int j=0;j<len;j++){
// 进行len次选择,考虑使用移位运算
if(n%2==1){
tempSet.add(nums[j]);// 进行判断是否选择j
}
n = n>>1;//移位处理
}
allSet.add(new ArrayList<>(tempSet));
}
return allSet;
}
}
玩具蛇问题(对应DFS、回溯,可借鉴N皇后问题)
该玩具可以放在4*4任意一个位置开始,然后进行DFS搜索直到所有位置填满则为一次结构,然后回退,继续搜索。
class Point{
int x,y;
public Point(int x, int y) {
this.x = x;
this.y = y;
}
@Override
public String toString() {
return "Point{" +
"x=" + x +
", y=" + y +
'}';
}
}
List<List<Point>> list = new ArrayList<>();
List<Point> record = new ArrayList<>();//记录一次轨迹
/**
*
* @param matrix
* @param count
* @param x
* @param y
* @return
* * 玩具蛇(国赛第五题)
* * 计算数量即可,使用一个棋盘记录是否选择该位子(->排列组合?是否选择该字符
* * -> 回溯法,当选择不合理时进行回退
* * 1.
*
*/
int dfs(boolean [][]matrix,int count,int x,int y){
if(x>=4||y>=4||x<0||y<0)
return 0;// 选择不合理,计数为0,思考记录路径
if(count==0)
record.clear();
if(matrix[x][y])
{
record.add(new Point(x,y));
return 0;//已走
}
if(count==15)
{
list.add(record);
return 1;// 成功选择完,具有一种可能性
}
int sum=0;
// 表示已经走过该位子
matrix[x][y] = true;
sum+=dfs(matrix,count+1,x-1,y);//往左走
sum+=dfs(matrix,count+1,x+1,y);//往右走
sum+=dfs(matrix,count+1,x,y-1);
sum+=dfs(matrix,count+1,x,y+1);
matrix[x][y]=false;//若四个方向都走完则进行回退
return sum;
}
void test(){
boolean [][]matrix=new boolean[4][4];
int sum=0;
for(int i=0;i<16;i++){// 从16个位子进行分别开始深搜
sum+=dfs(matrix,0,i/4,i%4);
}
System.out.println("RS:"+sum);
list.stream().forEach(e->{
e.stream().forEach(System.out::print);
System.out.println();
});
}
/**
* 排列组合字符串
*/
String str = "abc";
String temp = "";
List<String> recordStr = new ArrayList<>();
int permutation(boolean[] select,int hasSelect,String str,int pos){
if(pos<0||pos>=3){
return 0;
}
if(select[pos]){
System.out.println(pos);
temp=temp+str.substring(pos,pos+1);
return 0;//该位子已选
}
if(hasSelect==3){// 已选三个
recordStr.add(temp);
return 1;
}
int sum = 0;
select[pos]=true;
sum+=permutation(select,hasSelect+1,str,pos+1);
sum+=permutation(select,hasSelect+1,str,pos-1);
select[pos]=false;
return sum;
}
最后,关于Java朋友使用List<>进行记录时,直接插入会出现空白的情况。
if(idx==nums.length){
lists.add(new ArrayList<>(temp));// 不能直接lists.add(temp)
return;
}
原因:temp为对象引用,加入并没加入实例的数据。
以上是关于leetcode递归练习总结的主要内容,如果未能解决你的问题,请参考以下文章