LeetCode 热题 HOT 100:回溯专题

news2024/11/23 9:42:33

LeetCode 热题 HOT 100:https://leetcode.cn/problem-list/2cktkvj/


文章目录

    • 17. 电话号码的字母组合
    • 22. 括号生成
    • 39. 组合总和
    • 46. 全排列
    • 补充:47. 全排列 II (待优化)
    • 78. 子集
    • 79. 单词搜索
    • 124. 二叉树中的最大路径和
    • 200. 岛屿数量
    • 437. 路径总和 III


17. 电话号码的字母组合

题目链接:https://leetcode.cn/problems/letter-combinations-of-a-phone-number/description/?envType=featured-list&envId=2cktkvj?envType=featured-list&envId=2cktkvj

class Solution {
    List<String> list;
    Map<Character, String> map;

    public List<String> letterCombinations(String digits) {
        ap = new HashMap<>();
        res = new LinkedList<>();
        if(digits.length() == 0){
            return res;
        }
        map.put('2', "abc");
        map.put('3', "def");
        map.put('4', "ghi");
        map.put('5', "jkl");
        map.put('6', "mno");
        map.put('7', "pqrs");
        map.put('8', "tuv");
        map.put('9', "wxyz");
        backTrack(digits, 0, new StringBuilder());
        return list;
    }

    public void backTrack(String digits, int ind, StringBuilder sb){ // 参数:输入的字符串、字符串的索引、拼接的英文字符串
        if(digits.length() == ind){
            list.add(sb.toString());
        }else{
            char ch = digits.charAt(ind);
            String str = map.get(ch); // 获取按键下面的字符序列
            for (int i = 0; i < str.length(); i++) {
                sb.append(str.charAt(i));
                backTrack(digits, ind + 1, sb);
                sb.deleteCharAt(sb.length()-1); // 回溯
            }
        }
    }
}

参考题解:https://leetcode.cn/problems/letter-combinations-of-a-phone-number/solutions/388738/dian-hua-hao-ma-de-zi-mu-zu-he-by-leetcode-solutio/?envType=featured-list&envId=2cktkvj?envType=featured-list&envId=2cktkvj

在这里插入图片描述


22. 括号生成

题目链接:https://leetcode.cn/problems/generate-parentheses/description/?envType=featured-list&envId=2cktkvj?envType=featured-list&envId=2cktkvj

思路一:

class Solution {
    List<String> res;
    public List<String> generateParenthesis(int n) {
        res = new LinkedList<>();
        backTrack(n, 0, 0, "");
        return res;
    }

    public void backTrack(int n, int left, int right, String str){
        if(left < right){
            return;
        }
        if(left == n && right == n){
            res.add(str);
            return;
        }else{
            if(left < n){
                backTrack(n, left+1, right, str+"(");
            }
            backTrack(n, left, right+1, str+")");
        }
    }
}

思路二:

class Solution {
    List<String> res = new ArrayList<>();
    public List<String> generateParenthesis(int n) {
        if(n<=0){
            return res;
        }
        getBracket("", n, n);
        return res;
    }

    public void getBracket(String str, int left, int right){
        if(left == 0 && right == 0){
            res.add(str);
            return;
        }
        if(left == right){
            getBracket(str+"(", left-1, right);
        }else{
            if(left > 0){
                getBracket(str+"(", left-1, right);
            }
            getBracket(str+")", left, right-1);
        }
    }
}

39. 组合总和

题目链接:https://leetcode.cn/problems/combination-sum/description/?envType=featured-list&envId=2cktkvj?envType=featured-list&envId=2cktkvj

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

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

    public void dfs(int[] candidates, int target, int ind){ // 关键点在于索引
        if(target == 0){
            res.add(new ArrayList<>(list));
            return;
        }

        for(int i = ind; i < candidates.length; i ++){
            if(target - candidates[i] >= 0){
                list.add(candidates[i]);
                dfs(candidates, target - candidates[i], i); 
			    // 每次在当前的索引上进行遍历,作用在于:如果没有索引:target=5,5-3-2 作用等同于 5-2-3, 那么会有两种组合[2,3]与[3,2]
                // 但是在索引的约束下,不会出现这种情况 
                list.remove(list.size()-1);
            }
        }
    }
}

参考链接:https://leetcode.cn/problems/combination-sum/solutions/14697/hui-su-suan-fa-jian-zhi-python-dai-ma-java-dai-m-2/?envType=featured-list&envId=2cktkvj?envType=featured-list&envId=2cktkvj
在这里插入图片描述


46. 全排列

题目链接:https://leetcode.cn/problems/permutations/description/?envType=featured-list&envId=2cktkvj?envType=featured-list&envId=2cktkvj

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

    public List<List<Integer>> permute(int[] nums) {
        boolean[] visited = new boolean[nums.length]; // 标志数组
        dfs(nums, 0, visited);
        return res;
    }

    public void dfs(int[] nums, int size, boolean[] visited){
        if(size == nums.length){
            res.add(new ArrayList<>(list));
            return;
        }
        for(int i = 0; i < nums.length; i ++){
            if(!visited[i]){
                visited[i] = true;
                list.add(nums[i]);
                dfs(nums, size+1, visited);
                list.remove(list.size()-1); // 回溯
                visited[i] = false;
            }
        }
    }
}

参考链接:https://leetcode.cn/problems/permutations/solutions/9914/hui-su-suan-fa-python-dai-ma-java-dai-ma-by-liweiw/?envType=featured-list&envId=2cktkvj?envType=featured-list&envId=2cktkvj

在这里插入图片描述


补充:47. 全排列 II (待优化)

题目链接:https://leetcode.cn/problems/permutations-ii/description/?envType=featured-list&envId=2cktkvj%3FenvType%3Dfeatured-list&envId=2cktkvj

class Solution {
    List<List<Integer>> res = new LinkedList<>();
    List<Integer> list = new LinkedList<>();

    public List<List<Integer>> permuteUnique(int[] nums) {
        boolean[] visited = new boolean[nums.length]; // 标志数组
        dfs(nums, 0, visited);
        return res;
    }

    public void dfs(int[] nums, int size, boolean[] visited){
        if(size == nums.length){
            for (List<Integer> result : res) {
                if(result.equals(list)){
                    return;
                }
            }
            res.add(new ArrayList<>(list));
            return;
        }
        for(int i = 0; i < nums.length; i ++){
            if(!visited[i]){
                visited[i] = true;
                list.add(nums[i]);
                dfs(nums, size+1, visited);
                list.remove(list.size()-1);
                visited[i] = false;
            }
        }
    }
}

78. 子集

题目链接:https://leetcode.cn/problems/subsets/description/?envType=featured-list&envId=2cktkvj?envType=featured-list&envId=2cktkvj

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

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

    public void dfs(int[] nums, int i){
        if(i==nums.length){
            res.add(new ArrayList(list));
            return;
        }
        // 选 nums[i]
        list.add(nums[i]);
        dfs(nums, i+1);
        // 不选 nums[i]
        list.remove(list.size()-1);
        dfs(nums, i+1);
    }
}

在这里插入图片描述


79. 单词搜索

题目链接:https://leetcode.cn/problems/word-search/description/?envType=featured-list&envId=2cktkvj?envType=featured-list&envId=2cktkvj

class Solution {

    public boolean exist(char[][] board, String word) {
        for(int i = 0; i < board.length; i ++){
            for(int j = 0; j < board[0].length; j ++){
                if(board[i][j] == word.charAt(0)){
                    if(dfs(board, i, j, word, 0)){ // 路径开头不一定只有一处,所以要遍历整个数组
                        return true;
                    }
                }
            }
        }
        return false;
    }

    public boolean dfs(char[][] board, int i, int j, String word, int ind){
        if(ind >= word.length()){
            return true;
        }
        if(i>=0 && i<board.length && j>=0 && j<board[0].length && board[i][j]==word.charAt(ind) && board[i][j]!='\0'){ // 剪枝
            char tmp = board[i][j];
            board[i][j] = '\0'; // 设置不可访问
            boolean f1 = dfs(board, i, j-1, word, ind+1); // 左
            boolean f2 = dfs(board, i-1, j, word, ind+1); // 上
            boolean f3 = dfs(board, i, j+1, word, ind+1); // 右
            boolean f4 = dfs(board, i+1, j, word, ind+1); // 下
            board[i][j] = tmp; // 回溯
            return f1 || f2 || f3 ||f4;
        }
        return false;
    }
}

124. 二叉树中的最大路径和

题目链接:https://leetcode.cn/problems/binary-tree-maximum-path-sum/description/?envType=featured-list&envId=2cktkvj?envType=featured-list&envId=2cktkvj

  • 二叉树 abc,a 是根结点(递归中的 root),bc 是左右子结点(代表其递归后的最优解)。最大的路径,可能的路径情况:
       a
    /  \
      b    c
    ① b + a + c。
    ② b + a + a 的父结点。(需要再次递归)
    ③ a + c + a 的父结点。(需要再次递归)
  • 其中情况 1,表示如果不联络父结点的情况,或本身是根结点的情况。这种情况是没法递归的,但是结果有可能是全局最大路径和,因此可以在递归过程中通过比较得出。
  • 情况 2 和 3,递归时计算 a+b 和 a+c,选择一个更优的方案返回,也就是上面说的递归后的最优解。
class Solution {
    int max = Integer.MIN_VALUE;

    public int maxPathSum(TreeNode root) {
        if(root == null){
            return 0;
        }
        dfs(root);
        return max;
    }

    /**
     * 返回经过root的单边分支最大和, 即 Math.max(root, root+left, root+right)
     */
    public int dfs(TreeNode root){
        if(root == null){
            return 0;
        }
        // 计算左子树最大值,左边分支如果为负数还不如不选择
        int leftMax = Math.max(0, dfs(root.left));
        // 计算右子树最大值,右边分支如果为负数还不如不选择
        int rightMax = Math.max(0, dfs(root.right));

        // left->root->right 作为路径与已经计算过历史最大值做比较
        max = Math.max(max, leftMax + root.val + rightMax);

        // 返回经过root的单边最大分支给当前root的父节点计算使用
        return root.val + Math.max(leftMax, rightMax);
    }
}

200. 岛屿数量

题目链接:https://leetcode.cn/problems/number-of-islands/description/?envType=featured-list&envId=2cktkvj?envType=featured-list&envId=2cktkvj

class Solution {
    public int numIslands(char[][] grid) {
        int sum = 0;
        for(int i = 0; i < grid.length; i ++){
            for(int j = 0; j < grid[0].length; j ++){
                if(grid[i][j] == '1'){
                    dfs(grid, i, j);
                    sum++;
                }
            }
        }
        return sum;
    }
    
    public void dfs(char[][] grid, int x, int y){
        if(0<=x && x<grid.length && 0<=y && y<grid[0].length && grid[x][y] == '1'){
            grid[x][y] ='0';
            dfs(grid, x, y-1); // 左
            dfs(grid, x-1, y); // 上
            dfs(grid, x, y+1); // 右
            dfs(grid, x+1, y); // 下
        }
    }
}

437. 路径总和 III

题目链接:https://leetcode.cn/problems/path-sum-iii/description/?envType=featured-list&envId=2cktkvj?envType=featured-list&envId=2cktkvj

class Solution {
    // key 是前缀和,value 是前缀和为这个值的路径数量。
    Map<Long, Integer> map = new HashMap<>();
    int target;

    public int pathSum(TreeNode root, int targetSum) {
        this.target = targetSum;
        // 可能路径从根节点开始算
        map.put(0l, 1);
        return dfs(root, 0l);
    }

    public int dfs(TreeNode root, long curSum){
        if(root == null){
            return 0;
        }
        curSum += root.val; // 当前累计的结点值
        int res = 0;
        // 以当前节点为止,去查看从前的 map 集合中是否还存在目标前缀和
        //              1
        //             /
        //            2
        //           /
        //          3
        // 假设目标和为 5
        // 节点 1 的前缀和为:1
        // 节点 3 的前缀和为: 1+2+3 = 6
        // pre(3) - pre(1) = 5
        // 所以从节点 1 到节点 3 之间有一条符合要求的路径
        res += map.getOrDefault(curSum-target, 0);

        // 存储路径的原因是可能节点的前缀和存在相等的情况:
        //              2
        //             /
        //            0
        //           /
        //          4
        // 从节点 2 到节点 4 有两条路径长度等于2
        map.put(curSum, map.getOrDefault(curSum, 0) + 1);

        int left = dfs(root.left, curSum); // 调用左子树
        int right = dfs(root.right, curSum); // 调用右子树

        res = res + left + right;

        map.put(curSum, map.get(curSum)-1); // 恢复状态

        return res;
    }
}

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

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

相关文章

object-fit,object-position让img标签表现得像背景图那样能自适应和调整显示位置

文章目录 一、object-fit的用法二、object-position的用法 图片在网页中有2种表现形式&#xff0c;使用CSS的background-image或者HTML的img标签来实现。 背景图实现如notion的封面图效果可以使用background-position或者background-size轻松实现&#xff0c;首先来看看notion…

2023年安全员-C证证模拟考试题库及安全员-C证理论考试试题

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 2023年安全员-C证证模拟考试题库及安全员-C证理论考试试题是由安全生产模拟考试一点通提供&#xff0c;安全员-C证证模拟考试题库是根据安全员-C证最新版教材&#xff0c;安全员-C证大纲整理而成&#xff08;含2023年…

【Java 进阶篇】JDBC Statement:执行 SQL 语句的重要接口

在Java应用程序中&#xff0c;与数据库进行交互是一项常见的任务。为了执行数据库操作&#xff0c;我们需要使用JDBC&#xff08;Java Database Connectivity&#xff09;来建立与数据库的连接并执行SQL语句。Statement接口是JDBC中的一个重要接口&#xff0c;它用于执行SQL语句…

leetCode 376.摆动序列 贪心算法

如果连续数字之间的差严格地在正数和负数之间交替&#xff0c;则数字序列称为 摆动序列 。第一个差&#xff08;如果存在的话&#xff09;可能是正数或负数。仅有一个元素或者含两个不等元素的序列也视作摆动序列。 例如&#xff0c; [1, 7, 4, 9, 2, 5] 是一个 摆动序列 &…

AI智能问答系统源码/AI绘画商业系统/支持GPT联网提问/支持Midjourney绘画

一、AI创作系统 SparkAi创作系统是基于国外很火的ChatGPT进行开发的AI智能问答系统和AI绘画系统。本期针对源码系统整体测试下来非常完美&#xff0c;可以说SparkAi是目前国内一款的ChatGPT对接OpenAI软件系统。那么如何搭建部署AI创作ChatGPT&#xff1f;小编这里写一个详细图…

.360、.halo勒索病毒数据恢复|金蝶、用友、管家婆、OA、速达、ERP等软件数据库恢复

导言&#xff1a; 在网络犯罪的阴影下&#xff0c;.360和.halo勒索病毒显得格外神秘而危险&#xff0c;它们都属于BeijingCrypt勒索病毒家族旗下的病毒&#xff0c;两者加密特征一致&#xff0c;加密勒索信内容一致。本文91数据恢复将深度解析.360、.halo勒索病毒的内部机制&a…

【算法速查】一篇文章带你快速入门八大排序(上)

君兮_的个人主页 即使走的再远&#xff0c;也勿忘启程时的初心 C/C 游戏开发 Hello,米娜桑们&#xff0c;这里是君兮_&#xff0c;首先在这里祝大家中秋国庆双节同乐&#xff01;&#xff01;今天用一篇文章为大家把八大排序算法都过一遍&#xff0c;当然由于篇幅的原因不是每…

华为云云耀云服务器L实例评测|Ubuntu系统MySQL 8.1.0 Innovation压测

文章目录 前言&#x1f4e3; 1.前言概述&#x1f4e3; 2.云服务器性能监控&#x1f4e3; 3.MySQL8.1版本安装✨ 3.1 安装包下载✨ 3.2 解压安装包✨ 3.3 登录验证 &#x1f4e3; 4.ubuntu安装sysbench&#x1f4e3; 5.云服务器压测✨ 5.1 IO测试✨ 5.2 CPU性能测试 &#x1f4e…

React18+Ts项目配置husky、eslint、pretttier、commitLint

前言 我的项目版本如下&#xff1a; React&#xff1a; V18.2.0Node.js: V16.14.0TypeScript&#xff1a;最新版工具&#xff1a; VsCode 本文将采用图文详解的方式&#xff0c;手把手带你快速完成在React项目中配置husky、prettier、commitLint&#xff0c;实现编码规范的统…

Javaweb作业小结

简单的XML文档 用JS求连乘积 function product(N) { let p 1; for (let i 1; i < N; i) { p * 2 * i - 1; } return p; } // 调用函数并输出结果 const N 7; // 这里的 N 是你想要的奇数的个数 const result product(N); console.log(p ${result}); Servlet映射关系…

动态规划:两个数组的dp问题(C++)

动态规划&#xff1a;两个数组的dp问题 前言两个数组的dp问题1.最长公共子序列&#xff08;中等&#xff09;2.不同的子序列&#xff08;困难&#xff09;3.通配符匹配&#xff08;困难&#xff09;4.正则表达式&#xff08;困难&#xff09;5.交错字符串&#xff08;中等&…

Go结构体深度探索:从基础到应用

在Go语言中&#xff0c;结构体是核心的数据组织工具&#xff0c;提供了灵活的手段来处理复杂数据。本文深入探讨了结构体的定义、类型、字面量表示和使用方法&#xff0c;旨在为读者呈现Go结构体的全面视角。通过结构体&#xff0c;开发者可以实现更加模块化、高效的代码设计。…

背包问题

目录 开端 01背包问题 AcWing 01背包问题 Luogu P2925干草出售 Luogu P1048采药 完全背包问题 AcWing 完全背包问题 Luogu P1853投资的最大效益 多重背包问题 AcWing 多重背包问题 I AcWing 多重背包问题 II Luogu P1776宝物筛选 混合背包问题 AcWing 混合背包问题…

JavaSE学习之--抽象类和接口

&#x1f495;"没有眼泪我们就会迷路&#xff0c;彻底变成石头&#xff0c;我们的心会变成冰凌&#xff0c;吻会变成冰块。"&#x1f495; 作者&#xff1a;Mylvzi 文章主要内容&#xff1a;JavaSE学习之--抽象类和接口 一.抽象类 1.抽象类的定义 我们知道&#x…

数仓精品理论-做大数据还有没有前途?

数仓精品理论-做大数据还有没有前途&#xff1f; 做大数据还有没有前途&#xff1f;大数据三要三不要我来讲讲大数据前景 做大数据还有没有前途&#xff1f; 先说&#xff0c;答案是肯定的&#xff0c;但一定要记住三要三不要。 datapulse官网&#xff1a; github:https://data…

cesium gltf控制

gltf格式详解 glTF格式本质上是一个JSON文件。这一文件描述了整个3D场景的内容。它包含了对场景结构进行描述的场景图。场景中的3D对象通过场景结点引用网格进行定义。材质定义了3D对象的外观,动画定义了3D对象的变换操作(比如选择、平移操作)。蒙皮定义了3D对象如何进行骨骼…

黑豹程序员-架构师学习路线图-百科:HTML-网页三剑客

为什么需要HTML 在网站技术发达之前&#xff0c;千年来我们获取信息是通过书籍。电脑流行后我们看文章、小说通过txt文件。看图通过单独的图片流量工具看单个的图片文件。 而HTML把文字和图片一起展示&#xff0c;让今天的电子书成为可能。 另外一点&#xff0c;我们的信息是…

【操作系统】了解Linux操作系统中PCB进程管理模块与进程PID

本篇要分享的内容是有关于操作系统中进程的内容。 目录 1.进程的简单理解 2.了解task_struct&#xff08;进程控制模块&#xff09;内容分类 3.task_struct&#xff08;进程控制模块&#xff09;中的PID 4.调用查看PID的函数 1.进程的简单理解 首先我们需要理解的是什么是…

简单讲解 glm::mat4

文章目录 前言一、下载glm库二、基本数学知识1. 三维中的 4 x 4 矩阵2.旋转3. 位移4. 缩放5. 组合 三、行向量或列向量四、总结 前言 glm库是OpenGL的官方数学库&#xff0c;里面内置多种跟几何变换相关的函数&#xff0c;熟练掌握glm库可以省下很多麻烦。 因为最近在项目中主…

鞋类 整鞋试验方法 剥离强度

声明 本文是学习GB-T 3903.3-2011 鞋类 整鞋试验方法 剥离强度. 而整理的学习笔记,分享出来希望更多人受益,如果存在侵权请及时联系我们 1 范围 GB/T 3903 的本部分规定了整鞋鞋底与鞋帮或外底与外中底之间剥离强度的试验方法。 本部分适用于采用模压、硫化、注塑、灌注、胶…