首页 > 其他分享 >剑指Offer题目笔记25(使用回溯法解决其他类型问题)

剑指Offer题目笔记25(使用回溯法解决其他类型问题)

时间:2024-04-03 13:00:01浏览次数:27  
标签:25 dfs Offer 字符 seg 括号 result 回溯 字符串

面试题85:

面试题85

问题:

​ 输入一个正整数n,输出所有包含n个左括号和n个右括号的组合,要求每个组合的左括号和右括号匹配。

解决方案:

​ 使用回溯法。因为要生成n个左括号和n个右括号,故需要走2n步,每一步生成一个括号,每一步都面临两个选项,既可能生成左括号也可能生成右括号。有限制条件,第一:左括号和右括号的个数不能大于n;第二:已生成右括号的个数不能大于已生成左括号。

源代码:
class Solution {
    public List<String> generateParenthesis(int n) {
        List<String> result = new LinkedList<>();
        dfs(n,n,"",result);
        return result;
    }
	//left表示未生成左括号个数、right表示未生成右括号个数
    private void dfs(int left,int right,String s,List<String> result){
        if(left == 0 && right == 0){
            result.add(s);
            return;
        }

        if(left > 0){
            dfs(left-1,right,s + "(",result);
        }
		//当生成左括号的个数大于生成右括号的个数时,出现生成右括号的情况。
        if(left < right){
            dfs(left,right-1,s+")",result);
        }
    }
}

面试题86:

面试题86

问题:

​ 输入一个字符串,要求将它分割成若干子字符串,使每个子字符串都是回文。

解决方案:

​ 使用回溯法。当处理到字符串中的某个字符时,如果包括该字符在内后面还有n个字符,那么此时面临n个选项,即分割出长度为1的子字符串(只包含该字符)、分割出长度为2子字符串(即包含该字符及它后面的一个字符),以此类推,分割出长度为n的子字符串(即包含该字符在内的后面的所有字符)。由于题目要求分割出来的每个子字符串都是回文,因此需要逐一判断这n个子字符串是不是回文,只有回文子字符串才是符合条件的分割。分割出一段回文子字符串之后,接着分割后面的字符串。

源代码:
class Solution {
    public List<List<String>> partition(String s) {
        List<List<String>> result = new LinkedList<>();
        dfs(s,0,new LinkedList<>(),result);
        return result;
    }

    private void dfs(String s,int start,LinkedList<String> list,List<List<String>> result){
        if(start == s.length()){
            result.add(new LinkedList<>(list));
        }else{
        	//分割出包括该字符在内后面还有n个字符,长度为1的子字符串(只包含该字符)、分割出长度为2子字符串(即包含该字符及它后面的一个字符)。
            for(int i = start;i < s.length();i++){
                if(isBack(s,start,i)){
                    list.add(s.substring(start,i+1));
                    //继续对分割剩余部分进行判断
                    dfs(s,i+1,list,result);
                    list.removeLast();
                }
            }       
        }
    }
	//判断从字符串str下标start到end的子字符串是否是回文字符串。
    private boolean isBack(String str,int start,int end){
        while(start < end){
            if(str.charAt(start++) != str.charAt(end--)){
                return false;
            }
        }

        return true;
    }
}

面试题87:

面试题87

问题:

​ 输入一个只包含数字的字符串,列出所有可能恢复出来的IP地址。

解决方案:

​ 使用回溯法。逐个扫描输入字符串中的字符以恢复IP地址。针对字符串中的每个数字,通常面临两个选项。第1个选项是将当前字符拼接到当前分段数字的末尾,拼接之后的数字应该在0到255之间。第2个选项是当前字符作为一个新的分段数字的开始。需要注意的是,一个IP地址最多只有4个分段数字,并且当开始一个新的分段数字时前一个分段数字不能是空的。

源代码:
class Solution {
    public List<String> restoreIpAddresses(String s) {
        List<String> result = new LinkedList<>();
        dfs(s,0,0,"","",result);
        return result;
    }
	//i用于记录已经扫描到字符串的下标、segI表示当前分段数字的下标、seg表示当前分段字符串、ip表示已经拼接好的部分IP地址
    private void  dfs(String s,int i,int segI,String seg,String ip,List<String> result){
        if(i == s.length() && segI == 3 && isValidSeg(seg)){
            result.add(ip + seg);
        //例如字符串s为10203040
        }else if(i < s.length() && segI <= 3){
            //当ch为2时,seg为10
            char ch = s.charAt(i);
            if(isValidSeg(seg + ch)){
                //情况一:添加当前char字符到该分段,seg字符串变为102
                dfs(s,i+1,segI,seg + ch,ip,result);
            }

            if(seg.length() > 0 && segI < 3){
                //情况二:不添加当前char字符到该分段,seg字符串变为2,IP地址为10.
                dfs(s,i + 1,segI + 1,"" + ch,ip + seg + ".",result);
            }
        }
    }
	//判断当前分段数字是否有效
    private boolean isValidSeg(String seg){
        return Integer.valueOf(seg) <= 255 && (seg.equals("0") || seg.charAt(0) != '0');
    }
}

标签:25,dfs,Offer,字符,seg,括号,result,回溯,字符串
From: https://blog.csdn.net/weixin_68854858/article/details/137341587

相关文章

  • [ABC259F] Select Edges 题解
    很容易想到树形dp。考虑在有根树内,每个点都有两种状态:不选自己和父亲的边;要选自己和父亲的边。那么单独对于子树内部而言,就要分两种情况:最多可以向\(d_i\)个孩子连边,对应上述第一种情况,我们称之为\(f_i\);最多可以向\(d_i-1\)个孩子连边,对应上述第二种情况,我们称之......
  • VL25 输入序列连续的序列检测
    解析:本题目较为简单,有两种思路,一种是状态机方法,一种是移位寄存器方法,因为题目未要求使用哪种方法,因此这里采用较为简洁的移位寄存器方法。//--------------------------------------------------------------------------------------------------------//Module:sequence......
  • 25_文件IO和标准IO
    文件IO和标准IO介绍​ 文件IO是Linux系统提供的接口,针对文件和磁盘进行操作,不带缓存机制;​ 标准IO是C语言函数库里的标准I/O模型,在stdio.h中定义,通过缓冲区操作文件,带缓存机制。Linux系统中一切皆文件,包括普通文件,目录,设备文件(不包含网络设备),管道,f......
  • 025、郡斋雨中与诸文士燕集
    025、郡斋雨中与诸文士燕集唐●韦应物兵卫森画戟,燕寝凝清香。海上风雨至,消遥池阁凉。烦疴近消散,嘉宾复满堂。自惭居处崇,未睹斯民康。理会是非遣,性达形迹忘。鲜肥属时禁,蔬果幸见尝。俯饮一杯酒,仰聆金玉章。神欢体自轻,意欲凌风翔。吴中盛文史,群彦今汪洋。方知大藩地,岂曰......
  • 初始化kubeadm init失败,再次初始化时显示6443、10259、10257、10250、2379、2380被占
    第一次使用kubeadminit初始化时,因kubelet.service和和kubelet未启动等部分原因导致初始化失败,当再次初始化时显示6443、10259、10257、10250、2379、2380这几个端口被占用,一个个使用sudolsof-i:port查看太麻烦,直接使用kubeadmreset将当前节点恢复为未安装Kubernetes的状......
  • P3258 [JLOI2014] 松鼠的新家
    原题链接题解1.小模拟+树上差分+lcacode#include<bits/stdc++.h>usingnamespacestd;inta[300006]={0};vector<int>G[300005];intdepth[500005]={0};intfa[500005][30]={0};inttree[500005]={0};voiddfs(intnow,intpre){fa[now][0]=pre;depth[n......
  • Offer必备算法20_队列_宽搜bfs_四道力扣题详解(由易到难)
    目录①力扣429.N叉树的层序遍历解析代码②力扣103.二叉树的锯齿形层序遍历解析代码③力扣662.二叉树最大宽度解析代码④力扣515.在每个树行中找最大值解析代码本篇完。①力扣429.N叉树的层序遍历429.N叉树的层序遍历难度中等给定一个N叉树,返回其节......
  • 2580. 统计将重叠区间合并成组的方案数(中等)
    核心思想先按第一个元素排序,原区间重合的合并为一个,计算合并完后的区间个数。每个区间都有2个选择,res不断乘2。classSolution{publicintcountWays(int[][]ranges){longres=1;finalintMOD=(int)(1e9+7);Arrays.sort(ranges,(......
  • SCP收容物021~025
      注:此文接SCP收容物016~020,本文只供开玩笑 ,与steve_gqq_MC合作---------------------------------------------------------------------------------------------------------------------------------目录scp-021scp-022scp-023scp-024scp-025scp-021物品......
  • 代码随想录算法训练营第二十五天(回溯2)|216. 组合总和 III、17. 电话号码的字母组合(JA
    文章目录216.组合总和III解题思路源码17.电话号码的字母组合解题思路源码216.组合总和III找出所有相加之和为n的k个数的组合,且满足下列条件:只使用数字1到9每个数字最多使用一次返回所有可能的有效组合的列表。该列表不能包含相同的组合两次,组合可......