暴力递归问题


所有可能的满二叉树

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    vector<TreeNode*> process(int n){//递归,返回n个节点的所有可能满二叉树
        vector<TreeNode*>res;
        if(n==1){
            TreeNode* root=new TreeNode(0);
            res.push_back(root);
            return res;
        }
        for(int i=1;i<n-1;++i){//以i为根节点,0~i-1为左树,i+1~n-1为右子树
            if((i&1)==0||((n-1-i)&1)==0){
                continue;//左右子树的节点个数必须为奇数
            }
            vector<TreeNode*>left=process(i);
            vector<TreeNode*>right=process(n-1-i);
            for(auto l:left){
                for(auto r:right){
                    //遍历左子树和右子树根节点
                    TreeNode* root=new TreeNode(0);
                    root->left=l;
                    root->right=r;
                    res.push_back(root);
                }
            }
        }
        return res;
    }
    vector<TreeNode*> allPossibleFBT(int n) {
        return process(n);
    }   
};

在这里插入图片描述


整数替换

在这里插入图片描述
在这里插入图片描述

class Solution {
public:
    int process(int n){//n 变为 1 所需的 最小替换次数
        if(n==1)return 0;
        if((n&1)==0){//偶数只能/2
            return 1+process(n>>1);
        }
        //奇数: n-1  n+1(存在的问题是:n+1会溢出)
        //问题可以转化为: n:  n-1/2  n/2+1
        return 2+min(process((n-1)>>1),process((n>>1)+1));
    }

    int integerReplacement(int n) {
        return process(n);
    }
};

在这里插入图片描述


反转链表


在这里插入图片描述

在这里插入图片描述

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    public ListNode process(ListNode x){
        if(x==null)return null;
        ListNode head=process(x.next);
        x.next=null;
        if(head==null)return x;
        //找到尾部节点tilt
        ListNode tilt=head;
        while(tilt.next!=null){
            tilt=tilt.next;
        }
        tilt.next=x;
        return head;
    }
    public ListNode reverseList(ListNode head) {
        return process(head);
    }
}

在这里插入图片描述



汉诺塔问题


在这里插入图片描述

在这里插入图片描述

class Solution {
    public void process(List<Integer> A, List<Integer> B, List<Integer> C,int n){
        if(n==0)return;
        //把A n-1个,借助C,移动到B上
        process(A,C,B,n-1);
        //把A最底下一个直接移动到C上;
        C.add(A.remove(A.size()-1));//从后往前去盘子
        //把B上的n-1个,借助A,移动到C上
        process(B,A,C,n-1);
    }
    public void hanota(List<Integer> A, List<Integer> B, List<Integer> C) {
        int n=A.size();
        process(A,B,C,n);
        //Collections.sort(C,new Compare());
    }
}

在这里插入图片描述

移除链表元素


在这里插入图片描述

在这里插入图片描述

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    public ListNode process(ListNode x,int val){
        if(x==null)return null;
        if(x.val!=val){
           x.next=process(x.next,val);
            return x;
        }
        
        x.next=process(x.next,val);
        return x.next;
    }
    public ListNode removeElements(ListNode head, int val) {
        return process(head,val);
    }
}

在这里插入图片描述



合并两个有序链表


在这里插入图片描述
在这里插入图片描述

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    
    public ListNode process(ListNode x,ListNode y){
        if(x==null)return y;
        if(y==null)return x;
        ListNode head=(x.val<=y.val?x:y);
        head.next=process((x.val<=y.val?x.next:x),(x.val<=y.val?y:y.next));
        return head;
    }
    public ListNode mergeTwoLists(ListNode list1, ListNode list2) {
        return process(list1,list2);
    }
}

在这里插入图片描述



汉诺塔问题

在这里插入图片描述

import java.util.Scanner;

public class Hanoi {
	
	public static void Hanoi(int N,String from,String to,String other) {
		if(N==1) {
			System.out.println("Move "+1+" from "+from+" to "+to);
			return;
		}
		Hanoi(N-1,from,other,to);
		System.out.println("Move "+N+" from "+from+" to "+to);
		Hanoi(N-1,other,to,from);
	}
	public static void main(String[] args) {
		Scanner scan=new Scanner(System.in);
		int N=scan.nextInt();
		Hanoi(N,"left","right","mid");
	}

}

在这里插入图片描述



打印全部子序列

在这里插入图片描述

import java.util.*;


public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 用来求出一个字符串的全部子序列,包含空字符串(因为这个不好统一输出的子序列,所以按照上课所讲写这个代码)
     * @param s string字符串 需要打印全部子序列的那个字符串
     * @return string字符串一维数组
     */
    public static void process(char[] chs,int index,String path,List<String> ans) {
		if(index==chs.length) {
			ans.add(path);
			return;
		}
		process(chs,index+1,path,ans);
		process(chs,index+1,path+chs[index]+"",ans);
		
	}
    public String[] getAllSubs (String s) {
        // write code here
        List<String> ans=new ArrayList<>();
		if(s==null)return null;
		char[] chs=s.toCharArray();
		process(chs,0,"",ans);
        String[] list=new String[ans.size()];
        for(int i=0;i<ans.size();++i){
            list[i]=ans.get(i);
        }
		return list;
    }
}

在这里插入图片描述



全排列

在这里插入图片描述

注意: 我这里实现的代码可以同样处理字符串含有重复字母的情况,但是要想按照字典序排列输出,必须提前对目标字符串进行排序。



import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Scanner;
import java.util.Set;

//全排列
public class Main {
	public static List<String> getAllPermutation(String s){
		if(s==null)return null;
		List<Character>chs=new ArrayList<>();
		for(char ch:s.toCharArray()) {
			chs.add(ch);
		}
		
		List<String> ans=new ArrayList<>();
		process(chs,"",ans);
		return ans;
	}
	public static void process(List<Character> chs,String path,List<String> ans) {
		if(chs.isEmpty()) {
			ans.add(path);
			return;
		}
		Set<Character>hashSet=new HashSet<>();
		for(int i=0;i<chs.size();++i) {
			if(!hashSet.contains(chs.get(i))) {
				//会报错,属于指针:List<Character>tmp=chs;
				List<Character>tmp=new ArrayList<>(chs);//复制值
				tmp.remove(i);
				process(tmp,path+chs.get(i),ans);
				hashSet.add(chs.get(i));
			}
			
			
		}
		
	}
	public static void main(String[] args) {
		Scanner scan=new Scanner(System.in);
		String str=scan.nextLine();
		List<String> ans=getAllPermutation(str);
		for(String s:ans) {
			System.out.println(s);
		}
	}
}

在这里插入图片描述



数字转换为字符串

在这里插入图片描述

import java.util.*;


public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 用来计算一个数字有多少种不同的转换方法
     * @param number string字符串 给定的数字
     * @return int整型
     */
    public static int process(char[] chs,int index){
        if(index==chs.length)return 1;
        if(chs[index]=='0')return 0;
        else if(chs[index]=='1'){
            int res=process(chs,index+1);
            if(index+1<chs.length){
                res+=process(chs,index+2);
            }
            return res;
        }
        else if(chs[index]=='2'){
            int res=process(chs,index+1);
            if(index+1<chs.length&&chs[index+1]<='6'){
                res+=process(chs,index+2);
            }
            return res;
        }
        
        return process(chs,index+1);
        
    }
    public int translateNumber (String number) {
        // write code here
        if(number==null)return 0;
        int ans=process(number.toCharArray(),0);
        return ans;
    }
}

在这里插入图片描述



背包问题

在这里插入图片描述

在这里插入图片描述


import java.util.Scanner;

//背包问题
public class Main {
	public static int getMaxValue(int N,int V,int[] C,int[] W) {
		return process(V,0,C,W,0);
	}
	public static int process(int V,int alreadyW,int[] C,int[] W,int index) {
		if(alreadyW>V)return -1;
		if(index==C.length)return 0;
		int v1=process(V,alreadyW,C,W,index+1);//返回index+1之后的货物总价值
		int v2=process(V,alreadyW+W[index],C,W,index+1);//可能是无效解,不能直接加C[index],需要判断一下
		if(v2!=-1) {
			v2+=C[index];
		}
		return Math.max(v1, v2);
		
		
	}
	public static void main(String[] args) {
		Scanner scan=new Scanner(System.in);
		int N=scan.nextInt();
		int V=scan.nextInt();
		int[] C=new int[N];
		int[] W=new int[N];
		for(int i=0;i<N;++i) {
			C[i]=scan.nextInt();
			W[i]=scan.nextInt();
		}
		int ans=getMaxValue(N,V,C,W);
		System.out.println(ans);
		
	}
}

在这里插入图片描述



排成一条线的纸牌博弈问题

在这里插入图片描述


import java.util.Scanner;

//排成一条线的纸牌博弈问题
public class Main {
	public static int getWinnerGrade(int[] cards) {
		return First(cards,0,cards.length-1);
	}
	public static int First(int[] cards,int L,int R) {
		if(L==R)return cards[L];
		return Math.max(cards[L]+Second(cards,L+1,R), cards[R]+Second(cards,L,R-1));
	}
	public static int Second(int[] cards,int L,int R) {
		if(L==R)return 0;
		return Math.min(First(cards,L+1,R), First(cards,L,R-1));
	}
	public static void main(String[] args) {
		Scanner scan=new Scanner(System.in);
		int N=scan.nextInt();
		int[] cards=new int[N];
		for(int i=0;i<N;++i) {
			cards[i]=scan.nextInt();
		}
		int ans=getWinnerGrade(cards);
		System.out.println(ans);
	}
}


在这里插入图片描述

暴力递归解法显然运行超时,最优解是用 动态规划



N皇后问题

在这里插入图片描述
在这里插入图片描述

N皇后问题只能用暴力递归来解,改不成动态规划 。


暴力递归解一


import java.util.Scanner;

//n皇后问题
public class Main {
	public static int getNQueen(int N) {
		if(N<1)return 0;
		int[] col=new int[N];
		return process(N,0,col);
	}
	public static int process(int N,int index,int[] col) {
		if(index==N)return 1;
		int res=0;
		for(int i=0;i<N;++i) {
			if(isValid(N,index,i,col)) {
				col[index]=i;
				res+=process(N,index+1,col);
				
			}
		}
		return res;
	}
	public static boolean isValid(int N,int index,int i,int[] col) {
		for(int j=0;j<index;++j) {
			if(col[j]==i||Math.abs(j-index)==Math.abs(col[j]-i))return false;
		}
		return true;
	}
	public static void main(String[] args) {
		Scanner scan=new Scanner(System.in);
		int N=scan.nextInt();
		int ans=getNQueen(N);
		System.out.println(ans);
	}
}

在这里插入图片描述


暴力递归解二

在解一的基础上进行了常数时间的优化,但是两种暴力递归时间复杂度是一样的。



import java.util.Scanner;

//n皇后问题
public class Main {
	public static int getAns(int N) {
		if(N<1||N>32)return 0;
		int limit=N==32?-1:((1<<N)-1);
		return process1(limit,0,0,0);
	}
	public static int process1(int limit,int colLimit,int leftLimit,int rightLimit) {
		if(limit==colLimit)return 1;
		int pos=limit&(~(colLimit|leftLimit|rightLimit));
		int res=0;
		while(pos!=0) {
			int mostRightOne=pos&(~pos+1);
			res+=process1(limit,colLimit|mostRightOne,(leftLimit|mostRightOne)<<1,(rightLimit|mostRightOne)>>>1);
			pos-=mostRightOne;
		}
		return res;
	}
	public static void main(String[] args) {
		Scanner scan=new Scanner(System.in);
		int N=scan.nextInt();
		int ans=getAns(N);
		System.out.println(ans);
	}
}

在这里插入图片描述



数的划分

在这里插入图片描述
数论知识:

在这里插入图片描述

import java.util.Scanner;

//数的划分
public class Main {
	public static int Partition(int n,int k) {
		return process(n,k);
	}
	public static int process(int n,int k) {
		if(n<k)return 0;
		if(n==k||k==1)return 1;
		return process(n-1,k-1)+process(n-k,k);
	}
	public static void main(String[] args) {
		Scanner scan=new Scanner(System.in);
		int n=scan.nextInt();
		int k=scan.nextInt();
		int ans=Partition(n,k);
		System.out.println(ans);
	}
}

在这里插入图片描述



选数

在这里插入图片描述

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Scanner;
import java.util.Set;

//选数
public class Main {

	public static boolean isPrime(int x) {
		if(x<2)return false;
		if(x==2)return true;
		for(int i=2;i<x;++i) {
			if(x%i==0)return false;
		}
		return true;
	}
	public static int getAns(int n,int k,List<Integer>number) {
		Set<Integer>hashSet=new HashSet<>();
		return process(n,k,0,number,0);
	
	}
	public static int process(int n,int k,int index,List<Integer>number,int alreadyNum) {
		if(k==0) {
			if(isPrime(alreadyNum)) {
				return 1;
			}
			return 0;
		}
		if(index==n)return 0;
		int res=0;
		res+=process(n,k,index+1,number,alreadyNum);
		res+=process(n,k-1,index+1,number,alreadyNum+number.get(index));
		return res;
	}
	public static void main(String[] args) {
		Scanner scan=new Scanner(System.in);
		int n=scan.nextInt();
		int k=scan.nextInt();
		List<Integer>number=new ArrayList<>(n);
		for(int i=0;i<n;++i) {
			number.add(scan.nextInt());
		}
		int ans=getAns(n,k,number);
		System.out.println(ans);
	}
}

在这里插入图片描述



爬楼梯

在这里插入图片描述

import java.util.Scanner;

//爬楼梯
public class Main {
	public static int getAns(int n) {
		return process(n,0);
	}
	public static int process(int n,int index) {
		if(index==n)return 1;
		if(index>n)return 0;
		return process(n,index+1)+process(n,index+2);
	}
	public static void main(String[] args) {
		Scanner scan=new Scanner(System.in);
		int n=scan.nextInt();
		int ans=getAns(n);
		System.out.println(ans);
	}
}

在这里插入图片描述
在这里插入图片描述

我写的暴力递归的代码是正确的,但是最优的算法是用 动态规划



翻转数位

在这里插入图片描述


class Solution {
    //暴力递归
    public int process(int num,int index,int sum,boolean isOk){
        //[index-1...0]目前最长的一串1,而且index-1位置必是1
        if(index==32){
            return sum;
        }
        if(((num>>index)&1)==1){
            return process(num,index+1,sum+1,isOk);
        }
        if(isOk){
            return Math.max(process(num,index+1,0,true),process(num,index+1,sum+1,false));
        }
        return Math.max(sum,process(num,index+1,0,false));
    }
    
    public int reverseBits(int num) {
        return process(num,0,0,true);
    }
}

在这里插入图片描述



传递信息


在这里插入图片描述

在这里插入图片描述


class Solution {
    //暴力递归
    //index:当前的玩家号  rest:当前还剩下rest轮
    public int process(int[][] relation,Map<Integer,List<Integer>>map,int n,int index,int rest){
        if(rest==0){
            return index==n-1?1:0;
        }
        //当前传递尚未结束
        if(!map.containsKey(index)){//index无法再往下传
            return 0;
        }
        int ans=0;
        List<Integer>list=new ArrayList<>(map.get(index));
        for(int i=0;i<list.size();++i){
            ans+=process(relation,map,n,list.get(i),rest-1);
        }
        return ans;
    }
   
    public int numWays(int n, int[][] relation, int k) {

        Map<Integer,List<Integer>>map=new HashMap<>();
        for(int i=0;i<relation.length;++i){
            if(!map.containsKey(relation[i][0])){
                List<Integer>arr=new ArrayList<>();
                arr.add(relation[i][1]);
                map.put(relation[i][0],arr);
            }else{
                map.get(relation[i][0]).add(relation[i][1]);
            }
        }
        return process(relation,map,n,0,k);
        
    }
}

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值