有关回溯法的几道题

  1. 著名的n皇后问题

n 皇后问题研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。

public class NQueue {
    public static int N=8;
    public static  int[] QueueColumm=new int[N];//QueueColumn[i]的值表示第i个皇后放在哪一列;每行代表一个皇后
    public static int M=0;
    public static void nqueue(int nIndex){
        if(nIndex==N){
            M++;
            System.out.println(Arrays.toString(QueueColumm));

        }
        int j=0;
        for(int i=0;i<N;i++){ //寻找当前皇后(nIndex)可能放的位置i->0:i->N-1
            for(j=0;j<nIndex;j++){//判断当前皇后(nIndex)与前[0-nIndex-1]的位置是否冲突
                if(QueueColumm[j]==i||Math.abs(nIndex-j)==Math.abs(i-QueueColumm[j])){ //如果列冲突了;或者对角线冲突了(当前点的横坐标和之前点的横坐标只差绝对值==当前点纵坐标和之前点的纵坐标绝对值相等,则说明对角线冲突),分别对应前后两个条件
                    break;
                }
            }
            if(j==nIndex){//说明不冲突,第nIndex个皇后应该放在i位置上
                QueueColumm[nIndex]=i;
                nqueue(nIndex+1);//这个皇后位置放好以后再递归求解下一个皇后应该放的位置
            }
        }
    }
    public static void main(String[] args){
        nqueue(0);//表示当前n-1个皇后已经排列好,现在排第n个皇后
        System.out.println("方案数为"+M);

    }
}

  1. 给定两个整数 n 和 k,返回 1 … n 中所有可能的 k 个数的组合。
class Solution {
    private List<List<Integer>> res=new ArrayList<>();
    private int n;
    private int k;
    public void combine(int start,List<Integer> list){
        if(list.size()==k)
           res.add(new ArrayList<Integer>(list));
        for(int i=start;i<=n;i++){
            list.add(i);
            combine(i+1,list);
            list.remove(list.size()-1);

        }
    }
    public List<List<Integer>> combine(int n, int k) {
        this.n=n;
        this.k=k;
        combine(1,new ArrayList<Integer>());
        return res;
    }
}
  1. 输入一个字符串,按字典序打印出该字符串中字符的所有排列。例如输入字符串abc,则打印出由字符a,b,c所能排列出来的所有字符串abc,acb,bac,bca,cab和cba。
import java.util.*;
public class Solution {
    private ArrayList<String> list=new ArrayList<>();
    public boolean hasSame(char[] arrays,int i,int k){
        for(int index=i;index<arrays.length;index++){
            if(arrays[index]==arrays[k])
                return true;
        }
        return false;
    }
    public void Permutation(char[] arrays,int k,int length){
        if(k==length)
            list.add(new String(arrays));
        for(int i=k;i<length;i++){
            if(hasSame(arrays,i+1,k))//考虑到有重复元素
                continue;
            char temp=arrays[i];
            arrays[i]=arrays[k];
            arrays[k]=temp;
            Permutation(arrays,k+1,length);
            temp=arrays[k];
            arrays[k]=arrays[i];
            arrays[i]=temp;
        }
            
    }
    public ArrayList<String> Permutation(String str) {
        if(str.length()==0)
            return list;
        Permutation(str.toCharArray(),0,str.length());
        return list;
    }
}

4.输入一颗二叉树的跟节点和一个整数,打印出二叉树中结点值的和为输入整数的所有路径。路径定义为从树的根结点开始往下一直到叶结点所经过的结点形成一条路径。(注意: 在返回值的list中,数组长度大的数组靠前)

import java.util.ArrayList;
/**
public class TreeNode {
    int val = 0;
    TreeNode left = null;
    TreeNode right = null;

    public TreeNode(int val) {
        this.val = val;

    }

}
*/
public class Solution {
    private ArrayList<ArrayList<Integer>> res=new ArrayList<>();
    public void FindPath(TreeNode root,int target,ArrayList<Integer> list){
        if(root==null)
            return;
        int temp=root.val;
        list.add(temp);
        target-=temp;
       
        if(target==0&&root.left==null&&root.right==null)
        {
            res.add(new ArrayList<>(list));
            //这里不能加return;
        }
        FindPath(root.left,target,list);
        FindPath(root.right,target,list);
       
        list.remove(list.size()-1);

        
    }
    public ArrayList<ArrayList<Integer>> FindPath(TreeNode root,int target) {
        FindPath(root,target,new ArrayList<Integer>());
        return res;
    }
}

总结:所有的这些都要依靠递归来完成,递归这个思想真的很重要啊!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

浅唱战无双

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值