[LeetCode]-回溯-2

前言

记录 LeetCode 刷题时遇到的回溯相关题目,第二篇。

93. 复原 IP 地址

回溯函数 backTrack(int index,int offset) 表示从原字符串中 offset 位置开始 (包括 offset) 选数来凑出 IP 地址中第 index 个数 (index 从 0 开始)

class Solution {
    int[] numIndex = new int[4]; //存放那四个数
    private char[] chars;
    int sLength;
    List<String> res = new LinkedList<>();
    public void backTrack(int index,int offset){
        if(index == 4){ // 边界1,当index增长到4,说明已经凑出了四个数,但是 offset 不等于字符串长度的话,说明后面还有数字没有被选,所以回溯
            if(offset == sLength) res.add(numIndex[0] + "." + numIndex[1] + "." + numIndex[2] + "." + numIndex[3]);
            return;
        }
        if(offset >= sLength) return;  // 边界2,offset超出字符串范围
        if(chars[offset] == '0'){ // 剪枝1,如果第一位为 0 ,那么这一个数只能取 0
            numIndex[index] = 0;
            backTrack(index + 1,offset + 1);
            return;
        }
        int num = 0;
        //从offset 开始一个数一个数选
        for(int i = offset;i < sLength && i < offset + 3;i++){
            num = num * 10 + chars[i] - '0';
            if(num > 255) break;
            numIndex[index] = num;
            backTrack(index + 1,i + 1);
        }
    }
    public List<String> restoreIpAddresses(String s) {
        sLength = s.length();
        if(sLength < 4 || sLength > 12) return res; // 剪枝2,每个数最多只能为三位,所以整个串最多12位
        chars = s.toCharArray();
        backTrack(0,0);
        return res;
    }
}

面试题 08.08. 有重复字符串的排列组合

参考题解
对于重复的字母,在同一位置不能出现多次,例如 “qqe”,在选择 ‘e’ 以及第一个 ‘q’ 后,后续不能选择 ‘e’ 以及第二个 ‘q’,

class Solution {
    List<String> list = new ArrayList<>();
    public String[] permutation(String S) {
        char[] c = S.toCharArray();
        boolean[] used = new boolean[c.length];
        StringBuilder sb = new StringBuilder();
        backTrack(used,c,sb);
        String[] res = list.toArray(new String[0]);
        return res;
    }
    public void backTrack(int[] used , char[] c, StringBuilder sb){
        if (sb.length() == c.length){
            list.add(sb.toString());
            return;
        }
        for (int i = 0; i < c.length; i++) {
            if (!used[i]){
                char cur = c[i];
                boolean valid = true;
                for (int j = 0; j < i; j++) {
                    if (!used[j] && c[j] == cur){
                        //因为在分支选取字母是从左到右选的,所以在cur左边的字母如果used值为false,
                        //说明这个字母在当前位置已经使用过了,同一个字母在同一位置不应该使用两次
                        valid = false;
                    }
                }
                if (!valid) continue;
                sb.append(c[i]);
                used[i] = true;
                backTrack(used, c, sb);
                sb.deleteCharAt(sb.length()-1);
                used[i] = false;
            }
        }
    }
}

77. 组合

定义回溯函数 backTrack(int i,int count),表示从 i 开始 (包括 i) 往后的数中选取出所有可行的组合,当前已选取了 count 个。那么为了得到问题的解,我们只需调用 backTrack(1,0) 即可

对于 backTrack 函数,如果 count 值为 k,说明当前选出的组合 cur 的数目已经达到 k 了,直接把 cur 放入 res 中;如果 i 大于 n,说明待选数已经超出范围了,进行剪枝;否则就从 i 开始直到 n 进行选数

class Solution {
    public List<List<Integer>> res;
    public List<Integer> cur;
    public int n;
    public int k;
    public List<List<Integer>> combine(int n, int k) {
        res = new ArrayList<>();
        cur = new ArrayList<>();
        this.n = n;
        this.k = k;
        backTrack(1,0);
        return res;
    }
    public void backTrack(int i,int count){
        if(count == k){
            res.add(new ArrayList<>(cur));
            return;
        }
        if(i > n) return;
        for(int j = i;j <= n;j++){
            cur.add(j);
            backTrack(j + 1,count + 1);
            cur.remove(cur.size() - 1); //回退
        }
    }
}

变形

如果给定的 n 个数不是 [1,n] 的范围,而是任意的 n 个数,且会有重复,怎么处理?
最简单的方式就是基于上面回溯的做法,把 count == k 时得到的 cur 添加到一个 Set 中,然后每次在把 cur 添加到 res 前看看 Set 中是否已存在 cur,存在的话就不添加到 res 中

679. 24 点游戏

4 个数进行 24 点游戏,我们可以先选出两个数进行运算,这样四个数就变为 3 个数;然后同理,再选出两个数进行运算,剩下两个数,再对这两个数进行运算,得到最终的结果,判断是否为 24 即可。因此很明显是一个递归的过程,对四个数选出两个数进行计算后对三个数进行递归,然后再对两个数递归…

由于对两个数运算有 6 种方式 (减跟除中两个运算数交换顺序),因此需要进行回溯从而覆盖 6 种运算方式

需要注意的:

  1. 除法运算是实数运算,所以计算结果可能是实数,所以每个数要转化为 double 处理,才不会出现 0 的运算结果
  2. 同样由于是实数运算,最后的运算结果不一定刚好等于 24,而是一个近似于 24 的实数,所以判断最后的运算结果是否为 24 需要通过与 24 做差判断差值是否足够小来判断
class Solution {
    public boolean judgePoint24(int[] cards) {
    	//知道list中最多只会有4个数,直接设置好大小为4,避免扩容
        List<Double> list = new ArrayList<>(4);
        for(int i : cards){
            list.add((double)i);
        }
        return backTrack(list);
    }
    public boolean backTrack(List<Double> list){
        if(list.size() == 1){
            return Math.abs(list.get(0) - 24) <= 1e-6;
        }
        for(int i = 0;i < list.size() - 1;i++){
            for(int j = i + 1;j < list.size();j++){
                boolean flag = false;
                List<Double> tmp = new ArrayList(list);
                //remove后list中i之后的数据会前移,如果先remove掉较小的坐标i的话,j对应的数就发生变化了;所以要先remove掉排在后边的j,这样i对应的数就不会变化
                double b = tmp.remove(j);
                double a = tmp.remove(i);
                tmp.add(a + b);
                flag |= backTrack(tmp);
                tmp.set(tmp.size() - 1,a - b);
                flag |= backTrack(tmp);
                tmp.set(tmp.size() - 1,b - a);
                flag |= backTrack(tmp);
                tmp.set(tmp.size() - 1,a * b);
                flag |= backTrack(tmp);
                tmp.set(tmp.size() - 1,a / b);
                flag |= backTrack(tmp);
                tmp.set(tmp.size() - 1,b / a);
                flag |= backTrack(tmp);
                if(flag) return true;
            }
        }
        return false;
    }
}

17. 电话号码的字母组合

每个数字有对应的几个字母,我们可以先定义一个数组存放每个数字对应的所有字母,然后对原字符串进行回溯,对每一个数字选取一个对应的字母进行替换,接着继续回溯后面的数字。回溯结束后回退,选取第二个字母进行替换,再继续回溯后面的数字,直到选取完所有对应的字母

class Solution {
    List<String> res;
    StringBuilder sb;
    char[][] numToChars = new char[][]{
        {'a','b','c'},
        {'d','e','f'},
        {'g','h','i'},
        {'j','k','l'},
        {'m','n','o'},
        {'p','q','r','s'},
        {'t','u','v'},
        {'w','x','y','z'}
    };
    public List<String> letterCombinations(String digits) {
        if(digits.isEmpty()){
            return new ArrayList<>();
        }
        char[] cs = digits.toCharArray();
        res = new ArrayList<>();
        sb = new StringBuilder();
        backTrack(cs,0);
        return res;
    }
    public void backTrack(char[] cs,int idx){
        if(idx == cs.length){
            res.add(sb.toString());
            return;
        }
        char[] toChars = numToChars[cs[idx] - '2'];
        for(char c : toChars){
            sb.append(c);
            backTrack(cs,idx + 1);
            sb.deleteCharAt(sb.length() - 1);
        }
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/389574.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Android Studio 实现图书借阅(管理)系统

&#x1f345;文章末尾有获取完整项目源码方式&#x1f345; 目录 前言 一、任务介绍 1.1 背景 1.2目的和意义 二、 实现介绍 视频演示 2.1 启动页实现 2.2 注册页面实现 2.3 登陆页面实现 2.4 图书列表的实现 2.5 当前借阅页面实现 2.6 我的页面实现…

你知道.NET的字符串在内存中是如何存储的吗?

一、字符串对象的内存布局 从“值类型”和“引用类型”来划分&#xff0c;字符串自然属于引用类型的范畴&#xff0c;所以一个字符串对象自然采用引用类型的内存布局。引用类型实例的内存布局总的来说整个内存布局分三块&#xff1a;ObjHeader TypeHandle Payload。对于一般…

如何在Windows中配置多个显示器?这里提供详细步骤

Windows可以通过多种方式使用多个显示器,扩展或复制主显示器。你甚至可以关闭主显示器。以下是如何使用简单的键盘快捷键更改辅助显示设置。 使用Windows+P投影菜单 要快速更改Windows 10处理多个显示器的方式,请按Windows+P。屏幕右侧会弹出一个名为“投影”的深灰色菜单。…

Codeforces Round 926 F. Sasha and the Wedding Binary Search Tree

F. Sasha and the Wedding Binary Search Tree 题意 给定一颗二叉搜索树&#xff0c;规定树上的所有点的点权都在范围 [ 1 , C ] [1, C] [1,C] 内&#xff0c;树上的某些节点点权已知&#xff0c;某些节点点权未知&#xff0c;求出合法的二叉搜索树的数量 思路 由于是二叉搜…

Web项目利用MybatisPlus进行分页查询

之前在写博客系统前台页面的时候&#xff0c;遇到了利用mp进行分页查询的情况&#xff0c;由于涉及到的知识点相对较为重要&#xff0c;固写一篇博客以此巩固。 一、功能需求 在首页和分类页面都需要查询文章列表。 首页&#xff1a;查询所有的文章分类页面&#xff1a;查询…

隐函数的求导【高数笔记】

1. 什么是隐函数&#xff1f; 2. 隐函数的做题步骤&#xff1f; 3. 隐函数中的复合函数求解法&#xff0c;与求导中复合函数求解法有什么不同&#xff1f; 4. 隐函数求导的过程中需要注意什么&#xff1f;

透光力之珠——光耦固态继电器的独特特点解析

光耦固态继电器作为现代电子控制领域中的重要组件&#xff0c;以其独特的特点在工业、通信、医疗等多个领域得到广泛应用。本文将深入剖析光耦固态继电器的特点&#xff0c;揭示其在电子控制中的卓越性能。 光耦固态继电器的光电隔离技术 光耦固态继电器以其光电隔离技术而脱颖…

深入了解社区店:定义、模式与优势

在当今的商业环境中&#xff0c;社区店正逐渐成为创业者们关注的热点。本文将以我的鲜奶吧店铺为例&#xff0c;深入探讨社区店的定义、模式和优势&#xff0c;为您提供最有价值的干货信息。 1、社区店的定义 社区店是指位于社区内或周边&#xff0c;以服务社区居民为主要目标…

Diffusion Transformer U-Net for MedicalImage Segmentation

用于医学图像分割的扩散变压器U-Net 摘要&#xff1a; 扩散模型在各种发电任务中显示出其强大的功能。在将扩散模型应用于医学图像分割时&#xff0c;存在一些需要克服的障碍:扩散过程调节所需的语义特征与噪声嵌入没有很好地对齐;这些扩散模型中使用的U-Net骨干网对上下文信…

2.15学习总结

2.15 1.聪明的质监员&#xff08;二分前缀和&#xff09; 2.村村通&#xff08;并查集&#xff09; 3.玉蟾宫(悬线法DP) 4.随机排列&#xff08;树状数组逆序对问题&#xff09; 5.增进感情&#xff08;DFS&#xff09; 6.医院设置&#xff08;floyd&#xff09; 聪明的质监员…

P1010 [NOIP1998 普及组] 幂次方题解

题目 任何一个正整数都可以用2的幂次方表示。例如137。 同时约定次方用括号来表示&#xff0c;即ab可表示为a(b)。 由此可知&#xff0c;137可表示为2(7)2(3)2(0)&#xff0c;进一步&#xff1a;72 ( 用2表示)&#xff0c;并且32。 所以137可表示为2(2(2)22(0))2(22(0))2(0…

ESP32学习(4)——电脑远程控制LED灯

1.思路梳理 首先需要让ESP32连接上WIFI 然后创建udp socket 接着接收udp数据 最后解析数据&#xff0c;控制LED 2.代码实现 import network from socket import * from machine import Pin p2Pin(2,Pin.OUT)def do_connect(): #连接wifi wlan network.WLAN(network.STA_IF)…

optee imx8mm

总仓库 git clone https://github.com/Xsyin/imx8mqevk.git -b container_region 替换imx8mqevk中的optee-client git clone https://github.com/nxp-imx/imx-optee-client.git -b lf-5.15.32_2.0.0 用 5.15.32 kernel 会有如下报错&#xff0c;需要将optee os升级到分支 lf-…

MySQL容器的数据挂载

挂载本地目录或文件 可以发现&#xff0c;数据卷的目录结构较深&#xff0c;如果我们去操作数据卷目录会不太方便。在很多情况下&#xff0c;我们会直接将容器目录与宿主机指定目录挂载。挂载语法与数据卷类似&#xff1a; # 挂载本地目录 -v 本地目录:容器内目录 # 挂载本地…

第9讲重写登录成功和登录失败处理器

重写登录成功和登录失败处理器 common下新建security包&#xff0c;再新建两个类&#xff0c;LoginSuccessHandler和LoginFailureHandler Component public class LoginSuccessHandler implements AuthenticationSuccessHandler {Overridepublic void onAuthenticationSuccess…

请标记你的龙年心愿关键词

昨天外孙陪我游了崇州市白头镇、道民镇&#xff08;竹艺村&#xff09;&#xff0c;见我心情愉悦&#xff0c;今天再陪我去饱览其他风景名胜&#xff0c;所以笔者——本“人民体验官”特别推广人民日报官方微博文化产品《2024年第一批春花开了》《#大年初七#&#xff0c;标记你…

三种输入输出函数

目录 printf函数 scanf函数 getchar函数 putchar函数 gets函数 puts函数 printf函数 当你需要将数据或文本输出到屏幕或其他输出设备时&#xff0c;C语言提供了一个非常有用的函数&#xff0c;即 printf() 函数。它是标准库中定义的函数&#xff0c;用于格式化输出。 pr…

如何监控另一台电脑屏幕画面?如何远程监控电脑屏幕?

在数字化时代&#xff0c;随着远程工作和协作的普及&#xff0c;电脑屏幕监控的需求也日益增长。无论是出于安全考虑、提高员工工作效率&#xff0c;还是确保企业机密的保密性&#xff0c;电脑屏幕监控都成为了企业不可或缺的管理工具。那么&#xff0c;如何监控另一台电脑屏幕…

怎么恢复电脑重装前的数据?介绍几种有效的方法

在日常生活和工作中&#xff0c;电脑已成为我们不可或缺的工具。然而&#xff0c;有时候我们会遇到一些突发情况&#xff0c;比如电脑系统崩溃需要重新安装系统。在这个过程中&#xff0c;我们可能会失去一些重要的数据&#xff0c;比如照片、文档、视频等。这些数据可能包含着…

第三十一回 武行者醉打孔亮 锦毛虎义释宋江-解压文件但不重复解压

武松发现蜈蚣岭寺庙里一个人搂着女的看月亮&#xff0c;就把那个人和他的道童都杀了。原来那个人叫飞天蜈蚣王道人&#xff0c;那女的是被掳来的&#xff0c;她将一包金银给武松&#xff0c;武松没有要。 就像武松在处理问题时展现出的智慧和决断力&#xff0c;现代IT技术同样…
最新文章