当前位置: 首页 > news >正文

LeetCode Hot100(回溯)

46. 全排列

题意

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

题解

因为是所有的排列组合,我们每一个位置都取一遍数组的所有元素看看有没有重复的即可

代码


import java.util.*;public class Solution {public static void main(String[] args) {int []nums={1,2,3};permute(nums);}static List<List<Integer>>  ans;public static List<List<Integer>> permute(int[] nums) {ans=new ArrayList<>();int []arr=new int[nums.length];dfs(0,arr,nums);return ans;}public static void dfs(int x,int []arr,int []nums){if(x>=nums.length){HashMap<Integer, Integer>mark=new HashMap<>();ArrayList<Integer> brr=new ArrayList<>();for(int i=0;i<arr.length;i++){brr.add(arr[i]);if(mark.containsKey(arr[i])){return;}mark.put(arr[i],1);}ans.add(brr);return;}else{for(int i=0;i<nums.length;i++){int f=arr[x];arr[x]=nums[i];dfs(x+1,arr,nums);}}}}

78. 子集

题意

给你一个整数数组 nums ,数组中的元素 互不相同 。返回该数组所有可能的子集(幂集)。

解集 不能 包含重复的子集。你可以按 任意顺序 返回解集。

题解

我们这边引入数学的一个概念,一个大小为n的数组有2的n次方个子集,这个是怎么来的呢,我们举个例子,对于一个大小为3的数组,他的子集应该有8个,我们用1代表当前元素在子集中,0表示不在,也就是 000,001,010,011,100,101,110,111,有没有发现,将上述所有元素看作2进制,转化过来就是0,1,2,3,4,5,6,7了,那么枚举数字代表状态即可

代码

class Solution {public List<List<Integer>> subsets(int[] nums) {int x=nums.length;int u=1<<x;u--;List<List<Integer>>ans=new ArrayList<>();for(int i=0;i<=u;i++){List<Integer>brr =new ArrayList<>();for(int j=0;j<x;j++){int f=1<<j;if((i&f)!=0){brr.add(nums[j]);}}ans.add(brr);}return ans;}
}

17. 电话号码的字母组合

题意

给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。答案可以按 任意顺序 返回。

给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。

题解

跟第一题深度相似,我们dfs的时候带入当前节点的位置,然后还是每个节点都去枚举所有的数据,停止条件是超出数组范围

代码


import java.util.*;public class Solution {public static void main(String[] args) {int []nums={1,2,3};}public List<String> letterCombinations(String digits) {List<String>arr=new ArrayList<>();arr.add("");arr.add("");arr.add("abc");arr.add("def");arr.add("ghi");arr.add("jkl");arr.add("mno");arr.add("pqrs");arr.add("tuv");arr.add("wxyz");List<String>ans=new ArrayList<>();if(digits.length()==0){return ans;}char []brr=digits.toCharArray();char []crr=new char[brr.length];dfs(ans,brr,arr,crr,0);return ans;}public static void dfs(List<String>ans,char []brr,List<String>arr,char []crr,int x){if(x>=brr.length){String s="";for(int i=0;i<crr.length;i++){s=s+crr[i];}ans.add(s);}else{int f=brr[x]-'0';for(int j=0;j<arr.get(f).length();j++){crr[x]=arr.get(f).charAt(j);dfs(ans,brr,arr,crr,x+1);}}}}

39. 组合总和

题意

给你一个 无重复元素 的整数数组 candidates 和一个目标整数 target ,找出 candidates 中可以使数字和为目标数 target 的 所有 不同组合 ,并以列表形式返回。你可以按 任意顺序 返回这些组合。

candidates 中的 同一个 数字可以 无限制重复被选取 。如果至少一个数字的被选数量不同,则两种组合是不同的。 

对于给定的输入,保证和为 target 的不同组合数少于 150 个。

题解

本来没想到怎么做,翻了一下题解,发现是剪枝dfs,那就是跟之前的做法一样了,也就是每次从头开始深度搜索元素,当和大于target的时候停止即可

代码


import java.util.*;public class Solution {public static void main(String[] args) {int []nums={1,2,3};}static List<List<Integer>>ans;public List<List<Integer>> combinationSum(int[] candidates, int target) {Arrays.sort(candidates);int []arr=new int[target+1];ans=new ArrayList<>();dfs(arr,0,target,0,candidates);return ans;}public static void dfs(int []arr,int x,int y,int j,int []crr){if(x>y){return;}else if(x==y){List<Integer>brr=new ArrayList<>();for(int i=0;i<j;i++){if(i!=0&&arr[i]<arr[i-1]){return;}brr.add(arr[i]);}ans.add(brr);return;}else{for(int i=0;i<crr.length;i++){arr[j]=crr[i];dfs(arr,x+crr[i],y,j+1,crr);}}}}

22. 括号生成

题意

数字 n 代表生成括号的对数,请你设计一个函数,用于能够生成所有可能的并且 有效的 括号组合。

题解

如果你不会判断括号序列,请看题主的之前的栈篇,我们还是通过子集枚举,枚举所有的左端括号的位置,用1代替,0代替右边括号,最后看看是不是括号序列即可

代码


import java.util.*;public class Solution {public static void main(String[] args) {int []nums={1,2,3};generateParenthesis(3);}public static int getx(int y){int sum=0;while(y>0){if((y&1)!=0){sum++;}y>>=1;}return sum;}public static List<String> generateParenthesis(int n) {n=n*2;int u =1<<n;u--;List<String>ans=new ArrayList<>();for(int i=0;i<=u;i++){int z=i;if(getx(z)==n/2){String s="";for(int j=0;j<=n-1;j++){int f=1<<j;if((f&i)!=0){s=s+"(";}else{s=s+")";}}if(isValid(s)){ans.add(s);}}}return ans;}public static boolean isValid(String s) {char []arr=s.toCharArray();Deque<Character> stack =new LinkedList<>();for(int i=0;i<arr.length;i++){if(arr[i]=='('||arr[i]=='['||arr[i]=='{'){stack.push(arr[i]);}else if(stack.isEmpty()){return false;}else{char c=stack.peek();if(arr[i]==')'){if(c!='('){return false;}stack.pop();}}}if(stack.size()!=0){return false;}return true;}}

79. 单词搜索

题意

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

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

题解

也是比较板子的题目,我们先建立个数组代表走的四个方向,然后继续建立数组代表当前位置来没有来过,那么我们进行dfs,看看每一个位置能不能对应上当前的字符串的位置,如果对应上,标记走过,继续向下dfs,如果不可以就停止,结束条件是超过字符串长度

代码


import java.util.*;public class Solution {public static void main(String[] args) {char arr[][]={{'A','B','C','E'},{'S','F','C','S'},{'A','D','E','E'}};String s="ABCB";exist(arr,s);}static int n;static int m;static int mark[][]=new int[20][20];static boolean ans=false;static int []zou1={0,1,-1,0,0};static int []zou2={0,0,0,1,-1};public static boolean exist(char[][] board, String word) {n=board.length;m=board[0].length;char []s=word.toCharArray();for(int i=0;i<n;i++){for(int j=0;j<m;j++){mark[i][j]=0;}}ans=false;for(int i=0;i<n;i++){for(int j=0;j<m;j++){if(ans){return ans;}if(board[i][j] == s[0]){mark[i][j]=1;dfs(i,j,1,s,board);mark[i][j]=0;}}}System.out.println(ans);return ans;}public static void dfs(int i,int j,int wei,char []s,char [][]board){if(wei>=s.length){ans=true;}if(ans){return;}for(int i1=1;i1<=4;i1++){int x1=i+zou1[i1];int y1=j+zou2[i1];if(x1<0||x1>=n||y1<0||y1>=m||mark[x1][y1]==1){continue;}if(board[x1][y1]==s[wei]){mark[x1][y1]=1;dfs(x1,y1,wei+1,s,board);mark[x1][y1]=0;}}}}

131. 分割回文串

题意

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

题解

额,枚举最后结束字符的位置即可,子集枚举

举例 aabb,当前二进制如果为0101,那么就是aa  bb,如果是1111,就是a  a   b  b ,然后判断是不是回文即可

代码        


import java.util.*;public class Solution {public static void main(String[] args) {int []nums={1,2,3};String s="aab";partition(s);}public static List<List<String>> partition(String s) {List<List<String>>ans=new ArrayList<>();char []brr=s.toCharArray();int n=s.length();int u=1<<n;u--;int f3=1<<(n-1);for(int i=1;i<=u;i++){if((i&f3)==0){continue;}boolean mark=true;String s1="";List<String>crr=new ArrayList<>();for(int j=0;j<n;j++){int f=1<<j;if((f&i)!=0){s1=s1+brr[j];if(!check(s1)){mark=false;break;}crr.add(s1);s1="";}else{s1=s1+brr[j];}}if(mark){ans.add(crr);}}return ans;}public static boolean check(String s){char []arr=s.toCharArray();for(int i=0;i<arr.length;i++){if(arr[i]!=arr[arr.length-i-1]){return false;}}return true;}}

51. N 皇后

题意

按照国际象棋的规则,皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。

n 皇后问题 研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。

给你一个整数 n ,返回所有不同的 n 皇后问题 的解决方案。

每一种解法包含一个不同的 n 皇后问题 的棋子放置方案,该方案中 'Q' 和 '.' 分别代表了皇后和空位。

题解

作为hard题并没有hard题的难度

首先我们看看规则,每一行不可以有超过两个,但是至少一个,那么你可以提前把这些状态找出来,肯定是2 4 8 16 ...... 换成二进制就是 00001 00010 00100 ,01000,10000,然后你每次dfs,每一行的状态就从当前里面取出来就可以了,但是还有一个情况,怎么满足斜着也没有,你会发现,如果是沿着y=x的方向的话,他的x-y的差值是固定的,相同,沿着y=-x的方向,y+x的和是相同的,最后枚举出状态判断一下即可

代码


import java.util.*;public class Solution {public static void main(String[] args) {int []nums={1,2,3};solveNQueens(4);}static int[]arr={1,2,4,8,16,32,64,128,256,512,1024,2048};static int x=0;public static  List<List<String>> solveNQueens(int n) {x=n;int []mark=new int[20];List<List<String>>ans=new ArrayList<>();int []brr=new int[20];dfs(ans,1,brr,mark);return ans;}public static int getx(int y){int sum=0;while(y!=1){sum++;y>>=1;}return sum;}public static void dfs(List<List<String>>ans,int wei,int []brr,int []mark){if(wei>x){HashMap<Integer,Integer>a=new HashMap<>();HashMap<Integer,Integer>b=new HashMap<>();HashMap<Integer,Integer>c=new HashMap<>();for(int i=1;i<=x;i++){if(a.containsKey(brr[i])){return;}a.put(brr[i],1);int f=brr[i];int f1=getx(f);if(b.containsKey(i+f1)){return;}b.put(i+f1,1);f=brr[i];f1=getx(f);if(c.containsKey(i-f1)){return;}c.put(i-f1,1);}List<String>crr=new ArrayList<>();for(int i=1;i<=x;i++){String s="";for(int j=1;j<=x;j++){int f=1<<j;if((f&brr[i])!=0){s=s+"Q";}else{s=s+".";}}crr.add(s);}ans.add(crr);return;}for(int i=1;i<=x;i++){if(mark[i]!=0){continue;}brr[wei]=arr[i];mark[i]=1;dfs(ans,wei+1,brr,mark);mark[i]=0;}}
}

如果有不理解的可以问题主

相关文章:

  • 2025 Java开发生态全景图:云原生、AI与性能优化的技术融合
  • 通达信 股道主力资金 幅图分析系统
  • 机器学习17-发展历史补充
  • 一分钟了解Transformer
  • spring-ai 1.0.0 (1)模型调用能力
  • Vue样式绑定与条件渲染详
  • MS91051模拟前端可Pin to Pin兼容LMP91051
  • 数据结构进阶 - 第三章 栈与队列
  • 专题:2025中国游戏科技发展研究报告|附130+份报告PDF、原数据表汇总下载
  • flutter结合ai工具(其他语言通用)
  • SpringBoot 中使用 @Async 实现异步调用​
  • 设计模式 | 原型模式
  • Oracle LogMiner分析日志的三种方法示例
  • 1.5、错误处理
  • 大模型算法面试笔记——注意力Transformer流程/面试题篇
  • Linux命令与脚本:高效系统管理的双刃剑
  • 网络调试的艺术:利用浏览器Network工具优化你的网站
  • 忆联 Docker+MySQL 流控方案:打造安全高效存储底座,释放 AI 极致性能
  • html 照片环 - 图片的动态3D环绕
  • 零样本提示(Zero-shot)与少样本提示(Few-shot):LLM高效调优的核心技术