leetcode——回溯

回溯法:
第几个全排列
括号组合
下一个排列
数字组合
矩阵中对应字符串

矩阵的XO替换
广度优先遍历:字符串字典转换:字符串字典匹配
岛屿问题:
图树判断

门问题

第几个全排列:
给出集合 [1,2,3,…,n],其所有元素共有 n! 种排列。
按大小顺序列出所有排列情况,并一一标记,当 n = 3 时, 所有排列如下:
“123”
“132”
“213”
“231”
“312”
“321”
给定 n 和 k,返回第 k 个排列。
说明:
给定 n 的范围是 [1, 9]。
给定 k 的范围是[1, n!]。

示例 1:
输入: n = 3, k = 3
输出: “213”

示例 2:
输入: n = 4, k = 9
输出: “2314”

解析:最开始的时候使用的是遍历出所有全排列,再得到第几个排列输出。
核心代码

if(flag[i]==0){
	c[len]=(char)('0'+i+1);
	flag[i]=1;
	getTotalOrdering(len+1,flag,c,k);
	falg[i]=0;
}

但是遗憾的是超出了时间限制,所以想到剪枝的方法(虽然是很难剪)。
思想是当第i个数字插入a后,其之后n-i数字对应的排列顺序是(n-i)!
如果k>(n-i)!,说明想要的情况不在第i个数字插入a的情况里,所以直接continue
注意到这个算法已经不是回溯算法了(一插到底直接return)所以falg[i]=0;不用再回设。
且throw new RuntimeException(“参数错误”);代替return,因为如果不这样做则函数没有不判断的return语句,是无法编译通过的(但是如果你参数正确其实不会执行到这步)

class Solution {
    List<String> list=new LinkedList<>();
    public String getPermutation(int n, int k) {
        int flag[]=new int[n];
        char c[]=new char[n];
        return this.getTotalOrdering(0,flag,c,k);
        
    }
    public String getTotalOrdering(int len,int flag[],char c[],int k){
        if(len==flag.length){return String.valueOf(c);}
        for(int i=0;i<flag.length;i++){
                if(flag[i]==0){
                    int ThisOrderingNum=getThisOrderingNum(flag.length-len-1);
                    if(k>ThisOrderingNum){
                        k=k-ThisOrderingNum;
                        continue;}
                    c[len]=(char)('0'+i+1);
                    flag[i]=1;
                    return getTotalOrdering(len+1,flag,c,k);
                }
        }
        throw new RuntimeException("参数错误");
    }
    public int getThisOrderingNum(int len){
        int sum=1;
        if(len==0)return sum;
        for(int i=len;i>0;i--){
            sum*=i;
        }
        return sum;
    }
}

括号组合
给出 n 代表生成括号的对数,请你写出一个函数,使其能够生成所有可能的并且有效的括号组合。

例如,给出 n = 3,生成结果为:

[
“((()))”,
“(()())”,
“(())()”,
“()(())”,
“()()()”
]

class Solution {
    List<String>list=new LinkedList<>();
    public List<String> generateParenthesis(int n) {
        addParenthesis("",n,n);
        return list;
    }
    public void addParenthesis(String str,int a,int b){
        if(b==0)list.add(str);
        else{
            if(a<b)addParenthesis(str+')',a,b-1);
            if(a>0)addParenthesis(str+'(',a-1,b);
        }
    }
}

下一个排列
leetcode31
实现获取下一个排列的函数,算法需要将给定数字序列重新排列成字典序中下一个更大的排列。
如果不存在下一个更大的排列,则将数字重新排列成最小的排列(即升序排列)。
必须原地修改,只允许使用额外常数空间。
以下是一些例子,输入位于左侧列,其相应输出位于右侧列。
1,2,3 → 1,3,2
3,2,1 → 1,2,3
1,1,5 → 1,5,1



import java.util.*;
import java.lang.*;
class Solution {
    public void nextPermutation(int[] nums) {
        int i,j;
        for(i=nums.length-1;i>=1&&nums[i]<=nums[i-1];i--);
        if(i>0){
        int k=i-1;
        for(j=nums.length-1;j>k&&nums[j]<=nums[k];j--);
        swap(nums,k,j);
        }
        reverse(nums,i);
    }
       private void reverse(int[] nums, int start) {
        int i = start, j = nums.length - 1;
        while (i < j) {
            swap(nums, i, j);
            i++;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值