题⽬链接:https://leetcode-cn.com/problems/combinations/
给定两个整数 n 和 k,返回 1 ... n 中所有可能的 k 个数的组合。
⽰例: 输⼊: n = 4, k = 2 输出: [ [2,4], [3,4], [2,3], [1,2], [1,3], [1,4], ]
- class Solution {
-
- List
> result = new ArrayList<>();
- // List
path = new ArrayList<>(); LinkedList增添的时间复杂度更低 - LinkedList
path = new LinkedList<>(); -
- public List
> combine(int n, int k) {
- // backtraking(n, k, 0); 返回范围 [1, n] 中所有可能的 k 个数的组合。所以index从1开始
- backtraking(n, k, 1);
- return result;
- }
-
- void backtraking(int n, int k, int index) {
- if(path.size() == k) {
- // result.add(path); new ArrayList<>() 将LinkedList类型的path转换为ArrayList类型
- result.add(new ArrayList<>(path));
- return;
- }
-
- for(int i = index; i <= n; i++){
- path.add(i);
- // backtraking(n, k , index + 1);
- backtraking(n, k ,i + 1);
- path.remove(path.size() - 1);
- // path.removeLast();
- }
- }
- }
链接:https://leetcode-cn.com/problems/combination-sum-iii/
找出所有相加之和为 n 的 k 个数的组合。组合中只允许含有 1 - 9 的正整数,并且每种组合 中不存在重复的数字。 说明: 所有数字都是正整数。 解集不能包含重复的组合。
⽰例 1: 输⼊: k = 3, n = 7 输出: [[1,2,4]]
⽰例 2: 输⼊: k = 3, n = 9 输出: [[1,2,6], [1,3,5], [2,3,4]]
- class Solution {
- List
> result = new ArrayList<>();
- LinkedList
path = new LinkedList<>(); -
- public List
> combinationSum3(int k, int n) {
- backtracking(k, n, 0, 1);
- return result;
- }
-
- void backtracking(int k, int n,int sum, int index) {
- if(sum == n && path.size() == k) {
- result.add(new ArrayList<>(path));
- return;
- }
-
- for(int i = index; i <= 9 && n >= sum + i; i++) {
- path.add(i);
- sum += i;
- backtracking(k, n, sum, i + 1);
- sum -= i;
- path.remove(path.size() - 1);
- }
- }
- }
题⽬链接:https://leetcode-cn.com/problems/letter-combinations-of-a-phone-number/
给定⼀个仅包含数字 2-9 的字符串,返回所有它能表⽰的字母组合。 给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。

⽰例: 输⼊:"23" 输出:["ad", "ae", "af", "bd", "be", "bf", "cd", "ce", "cf"].
说明:尽管上⾯的答案是按字典序排列的,但是你可以任意选择答案输出的顺序。
- class Solution {
- String[] letterMap = new String[]{
- "",//0
- "",//1
- "abc",//2
- "def",//3
- "ghi",//4
- "jkl",//5
- "mno",//6
- "pqrs",//7
- "tuv",//8
- "wxyz"//9
- };
- List
result = new ArrayList<>(); - StringBuilder path = new StringBuilder();
- public List
letterCombinations(String digits) { - if(digits == null || digits.length() == 0) return result;
- backTracking(digits, 0);
- return result;
- }
-
- void backTracking(String digits, int index) {
- if(index == digits.length()) {
- result.add(path.toString());
- return;
- }
- String s = letterMap[digits.charAt(index) - '0'];
- for(int i = 0; i < s.length(); i++){ //对每个按键的水平遍历
- path.append(s.charAt(i));
- backTracking(digits, index + 1); //对不同按键的深度递归
- path.deleteCharAt(path.length() - 1);
- }
- }
- }
题⽬链接:https://leetcode-cn.com/problems/combination-sum/
给定⼀个⽆重复元素的数组 candidates 和⼀个⽬标数 target ,找出 candidates 中所有可以 使数字和为 target 的组合。 candidates 中的数字可以⽆限制重复被选取。
说明: 所有数字(包括 target)都是正整数。 解集不能包含重复的组合。
⽰例 1: 输⼊:candidates = [2,3,6,7], target = 7, 所求解集为: [ [7], [2,2,3] ]
⽰例 2: 输⼊:candidates = [2,3,5], target = 8, 所求解集为: [ [2,2,2,2], [2,3,3], [3,5] ]
- class Solution {
- List
> result = new ArrayList<>();
- LinkedList path = new LinkedList<>();
- public List
> combinationSum(int[] candidates, int target) {
- Arrays.sort(candidates);
- backtracking(candidates, target, 0, 0);
- return result;
- }
-
- void backtracking(int[] candidates, int target, int sum, int index) {
- if(target == sum) {
- // result.add(path);
- result.add(new ArrayList<>(path));
- return;
- }
-
- for(int i = index; i < candidates.length && target >= sum + i; i++){ //target >= sum + i要提前排序
- path.add(candidates[i]);
- sum += candidates[i];
- backtracking(candidates, target, sum, i);
- sum -= candidates[i];
- path.remove(path.size() - 1);
- }
- }
- }
题⽬链接:https://leetcode-cn.com/problems/combination-sum-ii/
给定⼀个数组 candidates 和⼀个⽬标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。 candidates 中的每个数字在每个组合中只能使⽤⼀次。
说明: 所有数字(包括⽬标数)都是正整数。 解集不能包含重复的组合。
⽰例 1: 输⼊: candidates = [10,1,2,7,6,1,5], target = 8, 所求解集为: [ [1, 7], [1, 2, 5], [2, 6], [1, 1, 6] ]
⽰例 2: 输⼊: candidates = [2,5,2,1,2], target = 5, 所求解集为: [ [1,2,2], [5] ]
- class Solution {
- // public List
> combinationSum2(int[] candidates, int target) {
- List
> result = new ArrayList<>();
- LinkedList path = new LinkedList<>();
- boolean[] used;
- public List
> combinationSum2(int[] candidates, int target) {
- used = new boolean[candidates.length];
- Arrays.fill(used, false);
- Arrays.sort(candidates);
- backtracking(candidates, target, 0, 0);
- return result;
- }
-
- void backtracking(int[] candidates, int target, int sum, int index) {
- if(target == sum) {
- // result.add(path);
- result.add(new ArrayList<>(path));
- return;
- }
-
- // for(int i = index; i < candidates.length && target >= sum + i; i++){ //target >= sum + i要提前排序
- for(int i = index; i < candidates.length && target >= sum + candidates[i]; i++){
- // if(i > 0 && candidates[i-1] == candidates[i] && used[i - 1] == false){
- if(i > 0 && candidates[i-1] == candidates[i] && used[i - 1] == false){
- continue;
- }
- path.add(candidates[i]);
- sum += candidates[i];
- used[i] = true;
- backtracking(candidates, target, sum, i + 1);
- used[i] = false;
- sum -= candidates[i];
- path.remove(path.size() - 1);
- }
- }
- }
题⽬链接:https://leetcode-cn.com/problems/palindrome-partitioning/
给定⼀个字符串 s,将 s 分割成⼀些⼦串,使每个⼦串都是回⽂串。 返回 s 所有可能的分割⽅案。
⽰例: 输⼊: "aab" 输出: [ ["aa","b"], ["a","a","b"] ]
- class Solution {
- List
> result = new ArrayList<>();
- LinkedList path = new LinkedList<>();
- public List
> partition(String s) {
- backtracking(s, 0);
- return result;
- }
-
- void backtracking(String s, int index) {
- if(index == s.length()) {
- // result.add(path);
- result.add(new ArrayList(path));
- return;
- }
-
- for(int i = index; i < s.length(); i++) {
- if(isvalid(s, index ,i)) {
- // path.add(s.subStr(i, index));
- // path.add(s.substring(i+1, index));
- path.add(s.substring(index, i+1));
- backtracking(s, i+1);
- path.removeLast();
- }else {
- continue;
- }
-
- }
-
- }
-
- boolean isvalid(String s, int startIndex, int end) {
- for (int i = startIndex, j = end; i < j; i++, j--) {
- if (s.charAt(i) != s.charAt(j)) {
- return false;
- }
- }
- return true;
- }
- }
题⽬地址:https://leetcode-cn.com/problems/subsets/
给定⼀组不含重复元素的整数数组 nums,返回该数组所有可能的⼦集(幂集)。
说明:解集不能包含重复的⼦集。
⽰例: 输⼊: nums = [1,2,3] 输出: [ [3], [1], [2], [1,2,3], [1,3], [2,3], [1,2], [] ]
- class Solution {
- List
> result = new ArrayList<>();
- LinkedList path = new LinkedList<>();
-
- public List
> subsets(int[] nums) {
-
- backStraking(nums, 0);
- return result;
- }
-
- void backStraking(int[] nums, int index) {
- result.add(new ArrayList<>(path));
-
- if(index >= nums.length) {
- return;
- }
-
- for(int i = index; i < nums.length; i++) {
-
- path.add(nums[i]);
- // backStraking(nums, index +1); 怎么能用index呢?!
- backStraking(nums, i +1);
- path.removeLast();
-
- }
- }
- }
题⽬链接:https://leetcode-cn.com/problems/increasing-subsequences/
给定⼀个整型数组, 你的任务是找到所有该数组的递增⼦序列,递增⼦序列的长度⾄少是 2。
⽰例: 输⼊: [4, 6, 7, 7] 输出: [[4, 6], [4, 7], [4, 6, 7], [4, 6, 7, 7], [6, 7], [6, 7, 7], [7,7], [4,7,7]]
说明: 给定数组的长度不会超过15。
· 数组中的整数范围是 [-100,100]。
给定数组中可能包含重复数字,相等的数字应该被视为递增的⼀种情况。
- class Solution {
- List
> result = new ArrayList<>();
- LinkedList
path = new LinkedList<>(); - public List
> findSubsequences(int[] nums) {
- backtracking(nums,0);
- return result;
- }
-
- void backtracking(int[] nums,int index) {
- if(path.size() > 1) { //递增子序列长度至少为2
- result.add(new ArrayList<>(path));
- }
-
- if(index == nums.length){
- return;
- }
-
- boolean[] used = new boolean[201]; //同一层相同结点不能重复
- for(int i = index; i < nums.length; i++) {
- //纵向判断递增
- if(path.size() > 0 && nums[i] < path.get(path.size() - 1)) {
- continue;
- }
- //横向判断元素是否重复(序列无序)
- if(used[nums[i] + 100] == true) {
- continue;
- }
-
- // used[nums[i]] = true; 因为下标没有负数
- used[nums[i] + 100] = true;
- path.add(nums[i]);
- backtracking(nums, i + 1);
- path.removeLast();
-
-
- }
- }
- }
题⽬链接:https://leetcode-cn.com/problems/permutations/
给定⼀个 没有重复 数字的序列,返回其所有可能的全排列。
⽰例: 输⼊: [1,2,3] 输出: [ [1,2,3], [1,3,2], [2,1,3], [2,3,1], [3,1,2], [3,2,1] ]
- class Solution {
- List
> result = new ArrayList<>();
- LinkedList
path = new LinkedList<>(); - public List
> permute(int[] nums) {
- boolean[] used = new boolean[nums.length + 1];
- Arrays.fill(used, false);
- backtracking(nums,used);
- return result;
- }
-
- //同一树枝标记用过 used[i] == true
- //将used作为参数传递 比较的是同一树枝和同一树层
- //将used放在for循环上面,比较的是for循环是否有重复元素
- void backtracking(int[] nums, boolean[] used) {
- if(path.size() == nums.length) {
- result.add(new ArrayList<>(path));
- return;
- }
-
- for(int i = 0; i < nums.length; i++) {
- if(used[i] == true) {
- continue;
- }
- used[i] = true;
- path.add(nums[i]);
- backtracking(nums, used);
- path.remove(path.size() - 1);
- used[i] = false;
- }
- }
- }
题⽬链接:https://leetcode-cn.com/problems/permutations-ii/
给定⼀个可包含重复数字的序列 nums ,按任意顺序 返回所有不重复的全排列。
⽰例 1: 输⼊:nums = [1,1,2] 输出: [[1,1,2], [1,2,1], [2,1,1]]
⽰例 2: 输⼊:nums = [1,2,3] 输出:[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]
提⽰: 1 <= nums.length <= 8 -10 <= nums[i] <= 10
- class Solution {
- List
> result = new ArrayList<>();
- LinkedList
path = new LinkedList<>(); - int len;
- public List
> permuteUnique(int[] nums) {
- len = nums.length;
- boolean[] used = new boolean[nums.length + 1]; //[]是长度 <>是范型 ()是内容
- Arrays.fill(used, false);
- Arrays.sort(nums);
- backTracking(nums,used);
- return result;
- }
-
- void backTracking(int[] nums, boolean[] used){
- if(path.size() == nums.length) {
- result.add(new ArrayList<>(path));
- return;
- }
-
- for(int i = 0; i < len; i++) {
- //纵向判断
- if(used[i] == true) continue;
- //横向判断 原序列需要排序
- if(i > 0 && nums[i] == nums[i-1] && used[i-1] == false) continue;
-
- used[i] = true;
- path.add(nums[i]);
- backTracking(nums, used);
- path.removeLast();
- used[i] = false;
- }
- }
- }
题⽬链接: https://leetcode-cn.com/problems/n-queens/ n
皇后问题研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。
8 皇后问题的⼀种解法:
给定⼀个整数 n,返回所有不同的 n 皇后问题的解决⽅案。 每⼀种解法包含⼀个明确的 n 皇后问题的棋⼦放置⽅案,该⽅案中 'Q' 和 '.' 分别代表了皇后 和空位。
⽰例: 输⼊: 4 输出: [ [".Q..", "...Q", "Q...", "..Q."],["..Q.", "Q...", "...Q", ".Q.."] ] 解释: 4 皇后问题存在两个不同的解法。
- class Solution {
- List
> result = new ArrayList<>();
-
- public List
> solveNQueens(int n) {
- char[][] chessboard = new char[n][n];
- for(char[] c : chessboard) {
- Arrays.fill(c,'.');
- }
- backtracking(n, 0, chessboard);
- return result;
-
- }
-
- void backtracking(int n, int row, char[][] chessboard){
- if(row == n) {
- result.add(Array2List(chessboard));
- return;
- }
-
- for(int col = 0; col < n; col++) { //行和列都是从0开始
- if(isvalid(n,row,col,chessboard)) {
- chessboard[row][col] = 'Q';
- backtracking(n, row + 1, chessboard);
- chessboard[row][col] = '.';
- }
- }
- }
-
- public List
Array2List(char[][] chessboard) { - List
list = new ArrayList<>(); -
- for (char[] c : chessboard) {
- list.add(String.copyValueOf(c));
- }
- return list;
- }
-
- public boolean isvalid(int n, int row, int col, char[][] chessboard) {
- // 检查列
- for (int i=0; i
- if (chessboard[i][col] == 'Q') {
- return false;
- }
- }
-
- // 检查45度对角线
- for (int i=row-1, j=col-1; i>=0 && j>=0; i--, j--) {
- if (chessboard[i][j] == 'Q') {
- return false;
- }
- }
-
- // 检查135度对角线
- for (int i=row-1, j=col+1; i>=0 && j<=n-1; i--, j++) {
- if (chessboard[i][j] == 'Q') {
- return false;
- }
- }
- return true;
- }
- }