【LeetCode Hot100 回溯】组合、排列、子集、分割、N皇后、单词搜索、括号生成、电话号码的字母组合

news2025/1/5 23:02:36

回溯

    • 组合问题
    • 组合总和
    • 全排列
    • 子集
    • 分割回文串
    • N皇后
    • 电话号码的字母组合
    • 单词搜索
    • 括号生成

组合问题

给定两个整数 n 和 k,返回 1 … n 中所有可能的 k 个数的组合。
示例: 输入: n = 4, k = 2 输出: [ [2,4], [3,4], [2,3], [1,2], [1,3], [1,4], ]

树形结构
在这里插入图片描述
代码
使用startIndex控制遍历,每一次递归相当于树形图中的下一层,startIndex相当于递归的深度

class Solution {
    private List<Integer> path =  new ArrayList<>();
    private List<List<Integer>> res = new ArrayList<>();

    public List<List<Integer>> combine(int n, int k) {
        backTracing(n, k, 1);
        return res;
    }

    public void backTracing(int n, int k, int start) {
        if (path.size() == k) {
            res.add(new ArrayList<>(path));
            return;
        }
        // 剪枝,循环的遍历:至多从 n - (k - path.size) + 1 的位置开始搜索
        for (int i=start; i <= n - (k - path.size()) + 1; i++) {
            path.add(i);
            backTracing(n, k, i + 1);  //  i + 1 是因为组合中不能有重复
            path.removeLast();
        }
    }
}

组合总和

给定一个无重复元素的数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。
candidates 中的数字可以无限制重复被选取。
说明:
所有数字(包括 target)都是正整数。
解集不能包含重复的组合。
示例 1:
输入:candidates = [2,3,6,7], target = 7,
所求解集为: [ [7], [2,2,3] ]

树形结构
在这里插入图片描述
代码
因为该题目中,同一个数字可以无限制重复被选取,所以在递归函数调用时与上一题不同,i不需要+1

class Solution {
    private List<Integer> path = new ArrayList<>();
    private List<List<Integer>> res = new ArrayList<>();

    public List<List<Integer>> combinationSum(int[] candidates, int target) {
        backtracing(candidates, target, 0, 0);
        return res;
    }

    public void backtracing(int[] candidates, int target, int sum, int start) {
        if (sum > target) return;
        if (sum == target) {
            res.add(new ArrayList<>(path));
            return;
        }
        for (int i = start; i < candidates.length; i++) {
            path.add(candidates[i]);
            backtracing(candidates, target, sum + candidates[i], i);
            path.removeLast();  // 回溯,移除路径 path 最后一个元素
        }
    }
}

全排列

给定一个 没有重复 数字的序列,返回其所有可能的全排列。
示例:
输入: [1,2,3]
输出: [ [1,2,3], [1,3,2], [2,1,3], [2,3,1], [3,1,2], [3,2,1] ]

树形结构
在这里插入图片描述
代码
排列问题,for循环i从0开始;组合问题是从startIndex开始;使用used数组标注该元素是否使用过

class Solution {
    private List<Integer> path = new ArrayList<>();
    private List<List<Integer>> res = new ArrayList<>();
    private boolean[] used;
    public List<List<Integer>> permute(int[] nums) {
        used = new boolean[nums.length];
        backTracing(nums);
        return res;
    }

    public void backTracing(int[] nums) {
        if (path.size() == nums.length) {
            res.add(new ArrayList<>(path));
            return;
        }
        // 排列问题,for循环i从0开始;组合问题是从startIndex开始
        for(int i = 0; i < nums.length; i++) {
            // 如果取过了就跳过
            if (used[i]) {
                continue;
            }
            path.add(nums[i]);
            used[i] = true;
            backTracing(nums);
            used[i] = false;
            path.removeLast();
        }
    }
}

子集

给定一组不含重复元素的整数数组 nums,返回该数组所有可能的子集(幂集)。
说明:解集不能包含重复的子集。
示例: 输入: nums = [1,2,3] 输出: [ [3], [1], [2], [1,2,3], [1,3], [2,3], [1,2], [] ]

树形结构
在这里插入图片描述
代码
因为是子集,只要递归到就可以直接加入结果。之前都是叶节点加入结果集,这一题在递归函数一开始就可以加入结果集。

class Solution {

    private List<Integer> path = new ArrayList<>();
    private List<List<Integer>> res = new ArrayList<>();

    public List<List<Integer>> subsets(int[] nums) {
        backTracing(nums, 0);
        return res;
    }

    public void backTracing(int[] nums, int startIndex) {
        res.add(new ArrayList<>(path));

        if (path.size() == nums.length) {
            return;
        }

        for (int i = startIndex; i < nums.length; i++) {
            path.add(nums[i]);
            backTracing(nums, i + 1);
            path.removeLast(); 
        }
    }
}

分割回文串

给定一个字符串 s,将 s 分割成一些子串,使每个子串都是回文串。
返回 s 所有可能的分割方案。
示例: 输入: “aab” 输出: [ [“aa”,“b”], [“a”,“a”,“b”] ]

树形结构
在这里插入图片描述
代码
使用startIndex控制分割位置,[startIndex, i] 就是要截取的子串。
判断这个子串是不是回文,如果是回文,就加入在path中,path用来记录切割过的回文子串。

class Solution {

    List<List<String>> res = new ArrayList<>();
    List<String> path = new ArrayList<>();

    public List<List<String>> partition(String s) {
        backTracing(s, 0);
        return res;
    }

    public void backTracing(String s, int startIndex) {
        if (startIndex == s.length()) {
            res.add(new ArrayList<>(path));
            return;
        }
        StringBuilder sb = new StringBuilder();
        for (int i = startIndex; i < s.length(); i++) {
            sb.append(s.charAt(i));
            if (check(sb)) {
                path.add(sb.toString());
                backTracing(s, i + 1);
                path.removeLast();
            }
        }
    }

    public boolean check(StringBuilder sb) {
        for (int i = 0; i < sb.length() / 2; i++) {
            if (sb.charAt(i) != sb.charAt(sb.length() - 1 - i)) {
                return false;
            }
        }
        return true;
    }
}

N皇后

n 皇后问题 研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。
给你一个整数 n ,返回所有不同的 n 皇后问题 的解决方案。
每一种解法包含一个不同的 n 皇后问题 的棋子放置方案,该方案中 ‘Q’ 和 ‘.’ 分别代表了皇后和空位。
在这里插入图片描述
树形结构
在这里插入图片描述
代码

class Solution {

    List<List<String>> res = new ArrayList<>();

    public List<List<String>> solveNQueens(int n) {
        char[][] board = new char[n][n];
        for (char[] c : board) {
            Arrays.fill(c, '.');
        }
        backtracing(n, 0, board);
        return res;
    }

    public void backtracing(int n, int row, char[][] board) {
        if (row == n) {  // 终止条件
            res.add(array2List(board));
            return;
        }
        for (int col = 0; col < n; col++) {
            if (isValid(row, col, n, board)) {
                board[row][col] = 'Q';
                backtracing(n, row + 1, board);
                board[row][col] = '.';
            }
        }
    }

    public boolean isValid(int row, int col, int n, char[][] board) {
        // 判断列
        for (int i = 0; i < row; i++) {
            if (board[i][col] == 'Q') {
                return false;
            }
        }

        // 判断45° 斜线
        for (int i = row - 1, j = col - 1; i >= 0 && j >= 0; i--, j--) {
            if (board[i][j] == 'Q') {
                return false;
            }
        }

        // 判断 135 ° 斜线, 注意 j <= n - 1
        for (int i = row - 1, j = col + 1; i >= 0 && j <= n - 1; i--, j++) {
            if (board[i][j] == 'Q') {
                return false;
            }
        }
        return true;
    }

    public List<String> array2List(char[][] board) {
        List<String> list = new ArrayList<>();
        for (char[] c : board) {
            list.add(String.copyValueOf(c));
        }
        return list;
    }
}

电话号码的字母组合

给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。答案可以按 任意顺序 返回。
给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。
在这里插入图片描述
示例 1:
输入:digits = “23”
输出:[“ad”,“ae”,“af”,“bd”,“be”,“bf”,“cd”,“ce”,“cf”]

树形结构
例如:输入:“23”,抽象为树形结构,如图所示:
在这里插入图片描述
代码

class Solution {

    private List<String> res = new ArrayList<>();
    private String[] numString = {"", "", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"};
    private StringBuilder temp = new StringBuilder();  // 相当于path

    public List<String> letterCombinations(String digits) {
        if (digits == null || digits.length() == 0) {
            return res;
        }
        backtracing(digits, 0);
        return res;
    }

    public void backtracing(String digits, int index) {
        if (index == digits.length()) {  // 叶节点的位置终止
            res.add(temp.toString());  // StringBuilder 转成String类型
            return;
        }
        String str = numString[digits.charAt(index) - '0'];
        for(int i=0; i < str.length(); i++) {  
            temp.append(str.charAt(i));
            backtracing(digits, index + 1);
            temp.deleteCharAt(temp.length() - 1);
        }
    }
}

单词搜索

给定一个 m x n 二维字符网格 board 和一个字符串单词 word 。如果 word 存在于网格中,返回 true ;否则,返回 false 。

单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母不允许被重复使用。

代码

class Solution {

    private int[][] directs = new int[][]{{-1,0}, {1,0}, {0,1}, {0,-1}};  // 定义四个方向
    private int m;  // board 的行数
    private int n;  // borad 的列数
    private char[] ws;  // word的字符数组
    private boolean[][] used; // board中的某元素是否使用过
    private char[][] boad;  
 
    public boolean exist(char[][] board, String word) {
        this.m = board.length;
        this.n = board[0].length;
        this.ws = word.toCharArray();
        this.used = new boolean[m][n];
        this.boad = board;
        for(boolean[] u : used) {
            Arrays.fill(u, false);
        }
        for (int i=0; i<m; i++) {
            for (int j=0; j < n; j++) {
                if (boad[i][j] == ws[0]) {
                    used[i][j] = true;
                    if (backtracing(i, j, 1)) {
                        return true;
                    } else {
                        used[i][j] = false;
                    }
                }
            }
        }
        return false;
    }

    public boolean backtracing(int i, int j, int index) {
        if (index == ws.length) {
            return true;
        }
        for (int[] direct : directs) {
            int newX = i + direct[0];
            int newY = j + direct[1];

            // 超出边界
            if (!isInArea(newX, newY)) {
                continue;
            }
            // 被使用过
            if (used[newX][newY]) {
                continue;
            }
            // 不是要找的值
            if (boad[newX][newY] != ws[index]) {
                continue;
            }
            // 开始递归
            used[newX][newY] = true;
            if (backtracing(newX, newY, index + 1)) { // 下一层递归成功
                return true;
            } else {
                used[newX][newY] = false;
            }
        }
        return false;
    }

    public boolean isInArea(int i, int j) {
        if (i >= 0 && i < m && j >= 0 && j < n) {
            return true;
        }
        return false;
    }
}

括号生成

数字 n 代表生成括号的对数,请你设计一个函数,用于能够生成所有可能的并且有效的括号组合。
示例 1:
输入:n = 3
输出:[“((()))”,“(()())”,“(())()”,“()(())”,“()()()”]
示例 2:
输入:n = 1
输出:[“()”]

代码
这题不采用和之前一样的代码结构,采用选与不选的方法

class Solution {

    private int n;
    private char[] path ;
    private List<String> ans = new ArrayList<>();

    public List<String> generateParenthesis(int n) {
        this.n = n;
        path = new char[n * 2];
        dfs(0, 0);
        return ans;    
    }

    // 用选与不选的思路进行递归
    // i 是第 i 个位置, open是左括号的数量
    private void dfs(int i, int open) {
        if (i == 2 * n) {
            ans.add(new String(path));
            return;
        }
        // 左括号的数量<n ,说明还能继续添加左括号
        if (open < n) {
            path[i] = '(';
            dfs(i + 1, open + 1);  // 下次递归
        }
        // 位置 i 时,右括号的位置 < 左括号的位置,说明还能继续添加右括号(如果右括号>左括号就不合法了)
        if (i - open < open) {
            path[i] = ')';
            dfs(i + 1, open);
        }
    }
}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Docker--Docker Container(容器) 之 操作实例

容器的基本操作 容器的操作步骤其实很简单&#xff0c;根据拉取的镜像&#xff0c;进行启动&#xff0c;后可以查看容器&#xff0c;不用时停止容器&#xff0c;删除容器。 下面简单演示操作步骤 1.创建并运行容器 例如&#xff0c;创建一个名为"my-nginx"的交互…

未来网络技术的新征程:5G、物联网与边缘计算(10/10)

一、5G 网络&#xff1a;引领未来通信新潮流 &#xff08;一&#xff09;5G 网络的特点 高速率&#xff1a;5G 依托良好技术架构&#xff0c;提供更高的网络速度&#xff0c;峰值要求不低于 20Gb/s&#xff0c;下载速度最高达 10Gbps。相比 4G 网络&#xff0c;5G 的基站速度…

Python爬虫入门实例:Python7个爬虫小案例(附源码)

引言 随着互联网的快速发展&#xff0c;数据成为了新时代的石油。Python作为一种高效、易学的编程语言&#xff0c;在数据采集领域有着广泛的应用。本文将详细讲解Python爬虫的原理、常用库以及实战案例&#xff0c;帮助读者掌握爬虫技能。 一、爬虫原理 爬虫&#xff0c;又…

LeetCode - 初级算法 数组(只出现一次的数字)

只出现一次的数字 这篇文章讨论如何找到一个数组中只出现一次的数字,确保算法的时间复杂度为线性,且只使用常量额外空间。 免责声明:本文来源于个人知识与公开资料,仅用于学术交流。 描述 给定一个非空整数数组 nums,除了某个元素只出现一次以外,其余每个元素均出现两…

【视频笔记】基于PyTorch从零构建多模态(视觉)大模型 by Umar Jamil【持续更新】

视频链接: 基于PyTorch从零构建多模态(视觉)大模型 by Umar Jamil 从头编写一个视觉语言模型:PloyGamma,是谷歌的一个模型 1:原始图像 2:视觉编码器(本文是viT),通过对比学习进行训练。这个对比学习最开始是CLIP,后来被谷歌改成了SigLIP 3:线性投影层 4:如何将图…

Doris 2.1 Deleting Data 学习笔记

1 Deleting Data with DELETE Command 1.1 Delete by Specifying a Filter Predicate DELETE FROM table_name [table_alias] [PARTITION partition_name | PARTITIONS (partition_name [

基于51单片机(STC12C5A60S2)和8X8彩色点阵屏(WS2812B驱动)的小游戏《贪吃蛇》(普中开发板矩阵按键控制)

目录 系列文章目录前言一、效果展示二、原理分析三、各模块代码1、定时器02、矩阵按键3、8X8彩色点阵屏 四、主函数总结 系列文章目录 前言 《贪吃蛇》&#xff0c;一款经典的、怀旧的小游戏&#xff0c;单片机入门必写程序。 以《贪吃蛇》为载体&#xff0c;熟悉各种屏幕的使…

爆肝1个月:DDR4 的信号完整性(万字长文SI)

前言&#xff1a; 大学里面&#xff0c;总有很多课程&#xff0c;很浪费时间&#xff0c;学了没点用处&#xff0c;问过老师&#xff0c;为什么信号完整性&#xff0c;示波器使用等课程不开呢&#xff0c;这种是对工作真实有帮助的&#xff1f; 老师&#xff1a;因为老师…

使用Xjar给SpringBoot项目jar包加密

1. 新建一个SpringBoot项目 2. 在pom文件添加依赖&#xff0c;github地址&#xff1a;https://github.com/core-lib/xjar <dependencies><!-- 添加 XJar 依赖 --><dependency><groupId>com.github.core-lib</groupId><artifactId>xjar&l…

UNI-APP_i18n国际化引入

官方文档&#xff1a;https://uniapp.dcloud.net.cn/tutorial/i18n.html vue2中使用 1. 新建文件 locale/index.js import en from ./en.json import zhHans from ./zh-Hans.json import zhHant from ./zh-Hant.json const messages {en,zh-Hans: zhHans,zh-Hant: zhHant }…

AI大模型系列之七:Transformer架构讲解

目录 Transformer网络是什么&#xff1f; 输入模块结构&#xff1a; 编码器模块结构&#xff1a; 解码器模块: 输出模块结构&#xff1a; Transformer 具体是如何工作的&#xff1f; Transformer核心思想是什么&#xff1f; Transformer的代码架构 自注意力机制是什么…

【Linux】:多线程(读写锁 自旋锁)

✨ 倘若南方知我意&#xff0c;莫将晚霞落黄昏 &#x1f30f; &#x1f4c3;个人主页&#xff1a;island1314 &#x1f525;个人专栏&#xff1a;Linux—登神长阶 ⛺️ 欢迎关注&#xff1a;&#x1f44d;点赞 &#…

SELECT的使用

目录 1、SQL的查询命令 1.1 SELECT语句 1.2 投影查询 1.3 选择查询 1.4 聚合函数查询 1.5 简单分组查询(GROUP BY) 1.6 内连接查询 1.7 外连接查询 1.8 子查询 1. 无关子查询 2. 相关子查询 带exists的相关子查询&#xff1a; 1.9 集合查询 1. UNION(并) 2. INT…

Vue项目结构推荐(复杂国际化项目与一般项目结构)

Vue项目结构推荐 一、一般项目结构二、复杂国际化项目结构总结/建议 下面结构是基于Vue和TypeScript开发的项目结构下src包下的结构&#xff0c;若只用到vue与js。则去掉typescript部分的包即可。 一、一般项目结构 assets&#xff1a;存放静态资源&#xff0c;如图片、字体、样…

BOC调制信号matlab性能仿真分析,对比功率谱,自相关性以及抗干扰性

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 5.算法完整程序工程 1.算法运行效果图预览 (完整程序运行后无水印) 2.算法运行软件版本 matlab2022a 3.部分核心程序 &#xff08;完整版代码包含详细中文注释和操作步骤视频&#xff09…

电影院售票 - 策略模式(Strategy Pattern)

策略模式&#xff08;Strategy Pattern&#xff09; 策略模式&#xff08;Strategy Pattern&#xff09;策略模式概述策略模式结构图策略模式主要包含的角色 talk is cheap&#xff0c; show you my code总结 策略模式&#xff08;Strategy Pattern&#xff09; 策略模式&…

重学 Android 自定义 View 系列(十):带指针的渐变环形进度条

前言 该篇文章根据前面 重学 Android 自定义 View 系列(六)&#xff1a;环形进度条 拓展而来。 最终效果如下&#xff1a; 1. 扩展功能 支持进度顺时针或逆时针显示在进度条末尾添加自定义指针图片使用线性渐变为进度条添加颜色效果 2. 关键技术点解析 2.1 进度方向控制的…

【北京迅为】iTOP-4412全能版使用手册-第七十章 Linux内核移植

iTOP-4412全能版采用四核Cortex-A9&#xff0c;主频为1.4GHz-1.6GHz&#xff0c;配备S5M8767 电源管理&#xff0c;集成USB HUB,选用高品质板对板连接器稳定可靠&#xff0c;大厂生产&#xff0c;做工精良。接口一应俱全&#xff0c;开发更简单,搭载全网通4G、支持WIFI、蓝牙、…

CG顶会论文阅读|《科技论文写作》硕士课程报告

文章目录 一、基本信息1.1 论文基本信息1.2 课程基本信息1.3 博文基本信息 二、论文评述&#xff08;中英双语&#xff09;2.1 研究问题&#xff08;Research Problem&#xff09;2.2 创新点&#xff08;Innovation/Contribution&#xff09;2.3 优点&#xff08;Why this pape…

.NET周刊【12月第4期 2024-12-22】

国内文章 dotnet 简单使用 ICU 库进行分词和分行 https://www.cnblogs.com/lindexi/p/18622917 本文将和大家介绍如何使用 ICU 库进行文本的分词和分行。 dotnet 简单聊聊 Skia 里的 SKFontMetrics 的各项属性作用 https://www.cnblogs.com/lindexi/p/18621674 本文将和大…