力扣回溯篇

文章目录

      • 46.全排列
      • 78.子集
      • 17.电话号码的字母组合
      • 39.组数总和
      • 79.单词搜索
      • 131.分割回文子串

46.全排列

给定一个不含重复数字的数组 nums ,返回其所有可能的全排列 。你可以按任意顺序返回答案。

输入:nums = [1,2,3]
输出:[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]输入:nums = [0,1]
输出:[[0,1],[1,0]]输入:nums = [1]
输出:[[1]]
class Solution {List<List<Integer>> res = new ArrayList<>(); // 存储结果的列表public List<List<Integer>> permute(int[] nums) {boolean[] used = new boolean[nums.length]; // 记录每个元素是否已经使用过List<Integer> track = new ArrayList<>(); // 存储当前排列的元素backtrack(track, nums, used); // 回溯算法求解全排列return res; // 返回结果列表}private void backtrack(List<Integer> track, int[] nums, boolean[] used){if(track.size() == nums.length){ // 如果当前排列的长度等于数组长度,说明已经找到一个全排列res.add(new ArrayList(track)); // 将当前排列添加到结果列表中return;}for(int i=0 ; i<nums.length ; i++){ // 遍历数组中的每个元素if(used[i]){ // 如果当前元素已经使用过,跳过continue;}used[i] = true; // 标记当前元素为已使用track.add(nums[i]); // 将当前元素添加到当前排列中backtrack(track, nums, used); // 继续寻找下一个元素used[i] = false; // 回溯,将当前元素标记为未使用track.removeLast(); // 回溯,移除当前排列中的最后一个元素}}
}

78.子集

给你一个整数数组 nums ,数组中的元素互不相同 。返回该数组所有可能的
子集(幂集)。解集不能包含重复的子集。你可以按任意顺序返回解集。

输入:nums = [1,2,3]
输出:[[],[1],[2],[1,2],[3],[1,3],[2,3],[1,2,3]]输入:nums = [0]
输出:[[],[0]]
class Solution {List<Integer> t = new ArrayList<Integer>(); // 用于存储当前子集的元素List<List<Integer>> ans = new ArrayList<>(); // 用于存储所有子集的结果public List<List<Integer>> subsets(int[] nums) {dfs(0, nums); // 从第0个元素开始进行深度优先搜索return ans; // 返回所有子集的结果}public void dfs(int cur, int[] nums) {if (cur == nums.length) { // 如果已经遍历完所有元素,将当前子集添加到结果中ans.add(new ArrayList<Integer>(t));return;}t.add(nums[cur]); // 将当前元素添加到子集中dfs(cur + 1, nums); // 继续向下搜索t.remove(t.size() - 1); // 回溯,移除刚刚添加的元素dfs(cur + 1, nums); // 不包含当前元素的子集继续向下搜索}
}

还有一种题解很有意思

  1. 例如[1,2,3],一开始解集为[[]],表示只有一个空集。
  2. 遍历到1时,依次拷贝解集中所有子集,只有[],把1加入拷贝的子集中得到[1],然后加回解集中。此时解集为[[], [1]]。
  3. 遍历到2时,依次拷贝解集中所有子集,有[], [1],把2加入拷贝的子集得到[2], [1, 2],然后加回解集中。此时解集为[[], [1], [2], [1, 2]]。
  4. 遍历到3时,依次拷贝解集中所有子集,有[], [1], [2], [1, 2],把3加入拷贝的子集得到[3], [1, 3], [2, 3], [1, 2, 3],然后加回解集中。此时解集为[[], [1], [2], [1, 2], [3], [1, 3], [2, 3], [1, 2, 3]]。
class Solution {public List<List<Integer>> subsets(int[] nums) {List<List<Integer>> lists = new ArrayList<>(); // 解集lists.add(new ArrayList<Integer>()); // 首先将空集加入解集中for(int i = 0; i < nums.length; i++){int size = lists.size(); // 当前子集数for(int j = 0; j < size; j++){ List<Integer> newList = new ArrayList<>(lists.get(j));// 拷贝所有子集newList.add(nums[i]); // 向拷贝的子集中加入当前数形成新的子集lists.add(newList); // 向lists中加入新子集}}return lists;}
}

17.电话号码的字母组合

给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。答案可以按任意顺序返回。给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。
在这里插入图片描述

输入:digits = "23"
输出:["ad","ae","af","bd","be","bf","cd","ce","cf"]输入:digits = ""
输出:[]输入:digits = "2"
输出:["a","b","c"]
class Solution {public List<String> letterCombinations(String digits) {List<String> combinations = new ArrayList<String>(); // 存储所有可能的组合结果if(digits.length() == 0){ // 如果输入为空,直接返回空列表return combinations;}Map<Character,String> phoneMap = new HashMap<Character,String>(){{ // 创建一个映射表,将数字映射到对应的字母put('2',"abc");put('3',"def");put('4',"ghi");put('5',"jkl");put('6',"mno");put('7',"pqrs");put('8',"tuv");put('9',"wxyz");}};backtracking(combinations,phoneMap,digits,0,new StringBuffer()); // 调用回溯函数进行搜索return combinations; // 返回所有可能的组合结果}public void backtracking(List<String> combinations,Map<Character,String> phoneMap,String digits,int index,StringBuffer combination){if(index == digits.length()){ // 如果已经遍历完所有的数字,将当前组合添加到结果列表中combinations.add(combination.toString());}else{char digit = digits.charAt(index); // 获取当前数字String letters = phoneMap.get(digit); // 获取当前数字对应的字母int lettersCount = letters.length(); // 获取当前数字对应的字母数量for(int i=0;i<lettersCount;i++){ // 遍历当前数字对应的所有字母combination.append(letters.charAt(i)); // 将当前字母添加到组合中backtracking(combinations,phoneMap,digits,index+1,combination); // 继续搜索下一个数字combination.deleteCharAt(index); // 回溯,移除刚刚添加的字母}}}
}

39.组数总和

给你一个 无重复元素 的整数数组 candidates 和一个目标整数 target ,找出 candidates 中可以使数字和为目标数 target 的 所有 不同组合 ,并以列表形式返回。你可以按任意顺序返回这些组合。candidates 中的同一个数字可以无限制重复被选取 。如果至少一个数字的被选数量不同,则两种组合是不同的。
对于给定的输入,保证和为 target 的不同组合数少于 150 个。

输入:candidates = [2,3,6,7], target = 7
输出:[[2,2,3],[7]]
解释:
23 可以形成一组候选,2 + 2 + 3 = 7 。注意 2 可以使用多次。
7 也是一个候选, 7 = 7 。
仅有这两种组合。输入: candidates = [2,3,5], target = 8
输出: [[2,2,2,2],[2,3,3],[3,5]]输入: candidates = [2], target = 1
输出: []
class Solution {public List<List<Integer>> combinationSum(int[] candidates, int target) {List<List<Integer>> ans = new ArrayList<List<Integer>>(); // 存储结果的列表List<Integer> combine = new ArrayList<Integer>(); // 存储当前组合的列表dfs(candidates, target, ans, combine, 0); // 调用深度优先搜索函数return ans; // 返回结果列表}public void dfs(int[] candidates, int target, List<List<Integer>> ans, List<Integer> combine, int idx) {if (idx == candidates.length) { // 如果已经遍历完所有候选数,直接返回return;}if (target == 0) { // 如果目标值减为0,说明找到了一个有效的组合,将其添加到结果列表中ans.add(new ArrayList<Integer>(combine));return;}dfs(candidates, target, ans, combine, idx + 1); // 不选择当前候选数,继续搜索下一个候选数if (target - candidates[idx] >= 0) { // 如果选择当前候选数后,目标值仍然大于等于0,继续搜索combine.add(candidates[idx]); // 将当前候选数添加到当前组合中dfs(candidates, target - candidates[idx], ans, combine, idx); // 继续搜索剩余的目标值combine.remove(combine.size() - 1); // 回溯,移除刚刚添加的候选数}}
}

79.单词搜索

给定一个 m x n 二维字符网格 board 和一个字符串单词 word 。如果 word 存在于网格中,返回 true ;否则,返回 false 。单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母不允许被重复使用。
在这里插入图片描述

输入:board = [["A","B","C","E"],["S","F","C","S"],["A","D","E","E"]], word = "ABCCED"
输出:true

在这里插入图片描述

输入:board = [["A","B","C","E"],["S","F","C","S"],["A","D","E","E"]], word = "SEE"
输出:true
class Solution {public boolean exist(char[][] board, String word) {int h = board.length, w = board[0].length;boolean[][] visited = new boolean[h][w];// 遍历二维数组的每个元素for (int i = 0; i < h; i++) {for (int j = 0; j < w; j++) {// 检查当前位置是否能够匹配单词的前缀boolean flag = check(board, visited, i, j, word, 0);if (flag) {return true;}}}return false;}public boolean check(char[][] board, boolean[][] visited, int i, int j, String s, int k) {// 如果当前位置的字符与单词的第k个字符不匹配,返回falseif (board[i][j] != s.charAt(k)) {return false;} else if (k == s.length() - 1) {// 如果已经匹配到单词的最后一个字符,返回truereturn true;}// 标记当前位置已访问visited[i][j] = true;// 定义四个方向的偏移量int[][] directions = { { 0, 1 }, { 0, -1 }, { 1, 0 }, { -1, 0 } };boolean result = false;// 遍历四个方向for (int[] dir : directions) {int newi = i + dir[0], newj = j + dir[1];// 判断新的位置是否在二维数组范围内if (newi >= 0 && newi < board.length && newj >= 0 && newj < board[0].length) {if (!visited[newi][newj]) {// 递归调用check函数,继续匹配下一个字符boolean flag = check(board, visited, newi, newj, s, k + 1);if (flag) {result = true;break;}}}}// 回溯,将当前位置标记为未访问visited[i][j] = false;return result;}
}
  1. 将输入的字符串word转换为字符数组words。
  2. 遍历二维数组board的每一个元素,对于每一个元素,调用dfs函数进行深度优先搜索。
  3. 在dfs函数中,首先判断当前位置是否越界或者当前位置的字符与word中的对应字符不相等,如果满足这些条件,则返回false。
  4. 如果已经匹配到word的最后一个字符,说明找到了一个有效的路径,返回true。
  5. 将当前位置的字符暂时替换为’\0’,避免重复访问。
  6. 递归地对当前位置的上下左右四个方向进行深度优先搜索,如果有一个方向返回true,说明找到了一个有效的路径,返回true。
  7. 恢复当前位置的字符,继续搜索其他可能的路径。
  8. 如果所有方向都没有找到有效的路径,返回false。
  9. 如果遍历完二维数组board的所有元素都没有找到有效的路径,返回false。
class Solution {public boolean exist(char[][] board, String word) {char[] words = word.toCharArray();for(int i = 0; i < board.length; i++) {for(int j = 0; j < board[0].length; j++) {if (dfs(board, words, i, j, 0)) return true;}}return false;}boolean dfs(char[][] board, char[] word, int i, int j, int k) {if (i >= board.length || i < 0 || j >= board[0].length || j < 0 || board[i][j] != word[k]) return false;if (k == word.length - 1) return true;board[i][j] = '\0';boolean res = dfs(board, word, i + 1, j, k + 1) || dfs(board, word, i - 1, j, k + 1) || dfs(board, word, i, j + 1, k + 1) || dfs(board, word, i , j - 1, k + 1);board[i][j] = word[k];return res;}
}

131.分割回文子串

给你一个字符串 s,请你将 s 分割成一些子串,使每个子串都是回文串。返回 s 所有可能的分割方案。

输入:s = "aab"
输出:[["a","a","b"],["aa","b"]]输入:s = "a"
输出:[["a"]]
class Solution {List<String> path = new ArrayList<>(); // 存储回文子串的路径List<List<String>> result = new ArrayList<>(); // 存储所有可能的回文子串组合public List<List<String>> partition(String s) {backtracking(s, 0); // 从字符串的第一个字符开始进行回溯return result; // 返回所有可能的回文子串组合}void backtracking(String s, int startIndex) {if (startIndex == s.length()) { // 如果已经遍历到字符串的末尾result.add(new ArrayList<>(path)); // 将当前路径添加到结果中return;}for (int i = startIndex + 1; i <= s.length(); i++) { // 遍历字符串,找到所有可能的回文子串String substring = s.substring(startIndex, i); // 获取当前子串if (!isPalindrome(substring)) { // 如果当前子串不是回文,跳过continue;}path.add(substring); // 将当前回文子串添加到路径中backtracking(s, i); // 继续向后遍历path.remove(path.size() - 1); // 回溯,移除当前回文子串}}boolean isPalindrome(String s) { // 判断一个字符串是否是回文int left = 0;int right = s.length() - 1;while (left < right) { // 从两端向中间遍历if (s.charAt(left) != s.charAt(right)) { // 如果两端的字符不相等,说明不是回文return false;}left++;right--;}return true; // 如果遍历完没有发现不相等的字符,说明是回文}
}

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

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

相关文章

Linux:IO多路转接之poll

文章目录 select的缺点pollstruct pollfd解决缺点的方式 代码实现 本篇总结的是poll的相关内容&#xff0c;在总结poll的内容前&#xff0c;先回顾一下select的缺点 select的缺点 select的缺点也比较明显 等待的fd是有上限的&#xff0c;在我们当前这个版本来说&#xff0c;…

【AOSP】手把手教你编译和调试AOSP源码

一、下载AOSP源码 在开始之前&#xff0c;我们先安装编译AOSP需要的一些系统基本依赖&#xff0c;如下命令 sudo apt-get install git-core gnupg flex bison gperf build-essential zip curl zlib1g-dev gcc-multilib g-multilib libc6-dev-i386 lib32ncurses5-dev x11proto…

【图论】【分类讨论】LeetCode3017按距离统计房屋对数目

本文涉及的知识点 图论 分类讨论 本题同解 【差分数组】【图论】【分类讨论】【整除以2】3017按距离统计房屋对数目 LeetCode3017按距离统计房屋对数目 给你三个 正整数 n 、x 和 y 。 在城市中&#xff0c;存在编号从 1 到 n 的房屋&#xff0c;由 n 条街道相连。对所有 …

Centos7下docker安装jenkins【使用docker-compose图文教程】

个人记录 前置条件&#xff1a;安装Docker与Docker-compose Centos7安装Docker与Docker-compose【图文教程】 查看jenkins最新的版本 https://www.jenkins.io/download/ 配置docker-compose.yml vim docker-compose.yml按i进行编辑模式&#xff0c;粘贴如下内容。把image里…

11-pyspark的RDD的变换与动作算子总结

目录 前言 变换算子动作算子 前言 一般来说&#xff0c;RDD包括两个操作算子&#xff1a; 变换&#xff08;Transformations&#xff09;&#xff1a;变换算子的特点是懒执行&#xff0c;变换操作并不会立刻执行&#xff0c;而是需要等到有动作&#xff08;Actions&#xff09;…

java(7)之跳转语句

1、break跳转语句 说到break其实也不是跳转&#xff0c;它更像是一个终结语句&#xff0c;常用于在循环语句需要停止出现例如 while&#xff08;&#xff09;{ if&#xff08;&#xff09;{ break&#xff1b; }} 这样的形式或者 switch&#xff08;&#xff09;{ case…

蓝桥 python笔记14——KMP、字符串哈希、最长回文子串、字典树

目录 KMP 字符串哈希 最长回文子串 字典树 KMP 模式匹配问题&#xff1a; KMP算法&#xff1a; 用动规的思想求Next数组&#xff1a;如果后缀的i位置前缀的j位置&#xff0c;Next[i1]j1&#xff1b;如果后缀的i位置!前缀的j位置&#xff0c;那就用KMP算法&#xff0c;令jNe…

OpenCV图像处理——基于背景减除实现多目标追踪

1. 基本运动检测 基本运动检测方法的核心在于计算视频帧之间的差异&#xff0c;或者是将某一帧设定为“背景”&#xff0c;然后将其与后续的帧进行比较。这个过程在概念上非常简单&#xff1a;首先保存视频的第一帧作为背景参考&#xff0c;随后将这一帧与新接收到的帧进行逐像…

肖恩带你学C语言·文件操作(上)

1. 为什么使用文件 如果没有文件&#xff0c;我们写的程序的数据是存储在电脑的内存中&#xff0c;如果程序退出&#xff0c;内存回收&#xff0c;数据就丢失了&#xff0c;等再次运行程序&#xff0c;是看不到上次程序的数据的&#xff0c;如果要将数据进行持久化的保存&…

【攻防世界】FlatScience

dirsearch 扫描发现四个文件 在login.php 中发现 输入 http://61.147.171.105:61912/login.php/?debug 发现源码 <?php if(isset($_POST[usr]) && isset($_POST[pw])){$user $_POST[usr];$pass $_POST[pw];$db new SQLite3(../fancy.db);$res $db->query(…

Android 360度全景图功能

方法一&#xff1a;OpenGL ES 1.在build.gradle文件中添加依赖 allprojects {repositories {maven { url https://jitpack.io }} } 高版本AS中settings.gradle.kts&#xff1a; dependencyResolutionManagement {repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_RE…

蜂窝物联:智慧大田解决方案

蜂窝物联智慧大田解决方案集成了传感器、自动化控制、农情监测、物联网、无线通讯等技术&#xff0c;对与农作物生长及其物候期观测密切相关的土壤、空气、光照、热量等环境因子进行实时监测&#xff0c;智能预警&#xff1b;对田间灌溉电磁阀、水肥一体机进行远程智能自动化控…

9-浏览器必备插件

9-浏览器必备插件 1.Flash Copilot 浏览器超级助手 解决收藏夹 以及使用的办法 2.fehelper 本身还集成插件&#xff0c;满足开发使用 3.SuperCopy 超级复制 SuperCopy 超级复制 一键破解禁止右键、破解禁止选择、破解禁止复制、破解禁止粘贴&#xff0c;启用复制&#xff0c;…

SpringBoot | Spring Boot“整合Redis“

目录: 1. Redis 介绍2. Redis 下载安装3. Redis “服务开启”和“连接配置”4. Spring Boot整合Redis的“前期准备” :① 编写实体类② 编写Repository 接口③ 在“全局配置文件”中添加 “Redis数据库” 的 “相关配置信息” 5. Spring Boot整合“Redis” (案例展示) 作者简介…

Linux网卡与公网IP地址:一个不可随意配置的世界

在Linux系统的网络配置中&#xff0c;IP地址的配置是基础也是关键。许多人可能好奇&#xff1a;为何不能随意为Linux网卡配置公网IP地址&#xff0c;而私网IP地址似乎就可以随心所欲呢&#xff1f;本文将解开这些问题的答案&#xff0c;探索公网IP地址被严格管控的原因&#xf…

【UnityRPG游戏制作】Unity_RPG项目之界面面板分离和搭建

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;元宇宙-秩沅 &#x1f468;‍&#x1f4bb; hallo 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍&#x1f4bb; 本文由 秩沅 原创 &#x1f468;‍&#x1f4bb; 收录于专栏&#xff1a;Uni…

深度学习500问——Chapter05: 卷积神经网络(CNN)(4)

文章目录 5.18 卷积神经网络凸显共性的方法 5.18.1 局部连接 5.18.2 权值共享 5.18.3 池化操作 5.19 全连接、局部连接、全卷积与局部卷积 5.20 局部卷积的应用 5.21 NetVLAD池化 参考文献 5.18 卷积神经网络凸显共性的方法 5.18.1 局部连接 我们首先了解一个概念&#xff0c…

vue 打包 插槽 inject reactive draggable 动画 foreach pinia状态管理

在Vue项目中&#xff0c;当涉及到打包、插槽&#xff08;Slots&#xff09;、inject/reactive、draggable、transition、foreach以及pinia时&#xff0c;这些都是Vue框架的不同特性和库&#xff0c;它们各自在Vue应用中有不同的用途。下面我将逐一解释这些概念&#xff0c;并说…

8、滑动窗口-无重复字符的最长子串

解析&#xff1a; 遍历 判断map是否包含当前字符&#xff0c;如果包含&#xff1a; 获取重复的index下标在哪里获取len长度重新设置L指针,其中L指针不回退&#xff0c;也就是如果这个重复值在L前面那就忽略&#xff0c;如果是在后面那就设置为index1。 代码如下&#xff1a; …

二叉树算法练习day.2

102.二叉树的层序遍历 链接&#xff1a;. - 力扣&#xff08;LeetCode&#xff09; 题目描述&#xff1a; 给你二叉树的根节点 root &#xff0c;返回其节点值的 层序遍历 。 &#xff08;即逐层地&#xff0c;从左到右访问所有节点&#xff09;。 示例 1&#xff1a; 输入&a…