题目来自《代码随想录》
1. 组合问题
77. 组合
https://leetcode-cn.com/problems/combinations/
- 不剪枝
- 剪
注意: ① res.add(path);//!!这里不能直接加path!!因为path会变空!! ② com(n, k, i+1); //这里不能是s+1!得是i+1!!!
List<List<Integer>> res = new ArrayList<>();
LinkedList<Integer> path = new LinkedList<>();
public List<List<Integer>> combine(int n, int k) {
com(n, k, 1);
return res;
}
public void com(int n, int k, int s) {
if(path.size() == k) {
res.add(new ArrayList<>(path));
System.out.println("输出的path为:" + path.toString());
return;
}
for(int i=s; i<=n; i++) {
path.add(i);
System.out.println("s:" + s + ", " + path.toString());
com(n, k, i+1);
path.removeLast();
}
}
216. 组合总和 III
https://leetcode-cn.com/problems/combination-sum-iii/
List<List<Integer>> res = new ArrayList<>();
LinkedList<Integer> path = new LinkedList<>();
public List<List<Integer>> combinationSum3(int k, int n) {
com(k, n, 1, 0);
return res;
}
public void com(int k, int n, int start, int sum) {
if(sum > n) return;
if(path.size() == k) {
if( sum == n ) res.add(new ArrayList<>(path));
return;
}
for( int i=start; i<=9; i++) {
path.add(i);
sum+=i;
com(k, n, i+1, sum);
path.removeLast();
sum-=i;
}
}
17. 电话号码的字母组合
https://leetcode-cn.com/problems/letter-combinations-of-a-phone-number/
List<String> list = new ArrayList<>();
public List<String> letterCombinations(String digits) {
if (digits == null || digits.length() == 0) return list;
backTracking(digits, numString, 0);
return list;
}
String[] numString = {"", "", "abc",
"def", "ghi", "jkl",
"mno", "pqrs", "tuv", "wxyz"};
StringBuilder temp = new StringBuilder();
public void backTracking(String digits, String[] numString, int num) {
if (num == digits.length()) {
list.add(temp.toString());
return;
}
String str = numString[digits.charAt(num) - '0'];
for (int i = 0; i < str.length(); i++) {
temp.append(str.charAt(i));
backTracking(digits, numString, num + 1);
temp.deleteCharAt(temp.length() - 1);
}
}
39. 组合总和
https://leetcode-cn.com/problems/combination-sum/
List<List<Integer>> res = new ArrayList<>();
LinkedList<Integer> path = new LinkedList<>();
public List<List<Integer>> combinationSum(int[] candidates, int target) {
Arrays.sort(candidates);
com(candidates, target, 0, 0);
return res;
}
public void com(int[] candidates, int target, int s, int sum) {
if( sum == target ) {
res.add(new ArrayList<>(path));
return;
}
for(int i=s; i<candidates.length; i++) {
if( sum + candidates[i] > target) break;
path.add(candidates[i]);
sum += candidates[i];
com(candidates, target, i, sum);
sum -= candidates[i];
path.removeLast();
}
}
40. 组合总和 II
跟上面不一样,同一层不能重复,同一枝可以。额外布尔数组存储是否使用过。
List<List<Integer>> res = new ArrayList<>();
LinkedList<Integer> path = new LinkedList<>();
public List<List<Integer>> combinationSum2(int[] candidates, int target) {
Arrays.sort(candidates);
boolean[] flag = new boolean[candidates.length];
com(candidates, target, 0, 0, flag);
return res;
}
public void com(int[] candidates, int target, int s, int sum, boolean[] flag) {
if( sum == target ) {
System.out.println("加入res的为:" + path.toString());
res.add(new ArrayList<>(path));
return;
}
for(int i=s; i<candidates.length; i++) {
show(flag);
if (i > 0 && candidates[i] == candidates[i - 1] && !flag[i - 1]) {
flag[i] = false;
System.out.println("被跳过的值为" + candidates[i]);
continue;
}
flag[i] = true;
if( sum + candidates[i] > target) break;
path.add(candidates[i]);
System.out.println( path.toString());
sum += candidates[i];
com(candidates, target, i+1, sum, flag);
flag[i] = false;
sum -= candidates[i];
path.removeLast();
}
}
public void show(boolean[] flag) {
System.out.println("\n");
for(boolean f : flag) System.out.print(f + ", ");
System.out.println("\n");
}
2. 切割问题
131. 分割回文串
https://leetcode-cn.com/problems/palindrome-partitioning/
List<List<String>> res = new ArrayList<>();
LinkedList<String> path = new LinkedList<>();
public List<List<String>> partition(String s) {
huisu(s, 0);
return res;
}
public void huisu(String s, int start) {
System.out.println("start:" + start);
if(start >= s.length()) {
System.out.println("加");
res.add(new LinkedList<String>(path));
return;
}
for(int i=start; i<s.length(); i++) {
if( hui(s, start, i)) {
String str = s.substring(start, i + 1);
System.out.println(str);
path.add(str);
}else continue;
huisu(s, i + 1);
path.removeLast();
}
}
public boolean hui(String s, int start, int end) {
int l = start;
int r = end;
while(l < r) {
if(s.charAt(l) != s.charAt(r)) return false;
l++;
r
}
return true;
}
93. 复原 IP 地址
这题后面得再做一下 https://leetcode-cn.com/problems/restore-ip-addresses/
List<String> res = new ArrayList<>();
Deque<String> path = new ArrayDeque<>(4);
String s;
public List<String> restoreIpAddresses(String s) {
this.s = s;
dfs(0, 4);
return res;
}
public void dfs(int begin, int reside){
if(begin == s.length()){
if(reside==0){
res.add(String.join(".", path));
}
return;
}
for(int i=begin; i<begin+3; i++){
if(i >= s.length())
break;
if(s.length()-i > reside*3)
continue;
if(judgeNumber(s, begin, i)){
String curS = s.substring(begin, i+1);
path.addLast(curS);
dfs(i+1, reside-1);
path.removeLast();
}
}
}
public boolean judgeNumber(String s, int left, int right){
int len = right - left + 1;
if(len>1 && s.charAt(left)=='0')
return false;
int res = len<=0 ? 0 : Integer.parseInt(s.substring(left, right+1));
return res>=0 && res<=255;
}
3. 子集问题
78. 子集
https://leetcode-cn.com/problems/subsets/
List<List<Integer>> res = new ArrayList<>();
LinkedList<Integer> path = new LinkedList<>();
public List<List<Integer>> subsets(int[] nums) {
if( nums.length == 0 ) {
res.add(new ArrayList<>());
return res;
}
dfs(nums, 0);
return res;
}
public void dfs(int[] nums, int s) {
res.add(new ArrayList<>(path));
for(int i=s; i<nums.length; i++) {
path.add(nums[i]);
dfs(nums, i+1);
path.removeLast();
}
}
90. 子集 II
和前面一样维护一个used数组 但是为什么这个不多写一行主动置false就对了呢? https://leetcode-cn.com/problems/subsets-ii/
List<List<Integer>> res = new ArrayList<>();
LinkedList<Integer> path = new LinkedList<>();
boolean[] flag;
public List<List<Integer>> subsetsWithDup(int[] nums) {
if( nums.length == 0 ) {
res.add(new ArrayList<>());
return res;
}
Arrays.sort(nums);
flag = new boolean[nums.length];
dfs(nums, 0);
return res;
}
public void dfs(int[] nums, int s) {
res.add(new ArrayList<>(path));
for(int i=s; i<nums.length; i++) {
if (i > 0 && nums[i] == nums[i - 1] && !flag[i - 1]){
continue;
}
flag[i] = true;
path.add(nums[i]);
dfs(nums, i+1);
path.removeLast();
flag[i] = false;
}
}
491. 递增子序列
https://leetcode-cn.com/problems/increasing-subsequences/
- 不要跟之前一样直接return
- 数据范围有限(200个),利用数组去重
List<List<Integer>> res = new ArrayList<>();
LinkedList<Integer> path = new LinkedList<>();
public List<List<Integer>> findSubsequences(int[] nums) {
dfs(nums, 0);
return res;
}
public void dfs(int[] nums, int s) {
if( path.size() > 1) {
res.add(new ArrayList<>(path));
}
int[] used = new int[201];
for(int i=s; i<nums.length; i++) {
if(!path.isEmpty() && nums[i] < path.get(path.size() - 1)) {
continue;
}
if(used[nums[i] + 100] == 1) continue;
used[nums[i] + 100] = 1;
path.add(nums[i]);
dfs(nums, i+1);
path.removeLast();
}
}
4. 排列问题
46. 全排列
https://leetcode-cn.com/problems/permutations/
List<List<Integer>> res = new ArrayList<>();
LinkedList<Integer> path = new LinkedList<>();
boolean[] used;
public List<List<Integer>> permute(int[] nums) {
used = new boolean[nums.length];
dfs(nums);
return res;
}
public void dfs(int[] nums) {
if(path.size() == nums.length) {
res.add(new ArrayList<>(path));
return;
}
for(int i=0; i<nums.length; i++) {
if(used[i]) continue;
used[i] = true;
path.add(nums[i]);
dfs(nums);
path.removeLast();
used[i] = false;
}
}
47. 全排列 II
https://leetcode-cn.com/problems/permutations-ii/
List<List<Integer>> res = new ArrayList<>();
LinkedList<Integer> path = new LinkedList<>();
boolean[] used;
public List<List<Integer>> permuteUnique(int[] nums) {
used = new boolean[nums.length];
Arrays.sort(nums);
dfs(nums);
return res;
}
public void dfs(int[] nums) {
if(path.size() == nums.length) {
res.add(new ArrayList<>(path));
return;
}
for(int i=0; i<nums.length; i++) {
if(used[i] || (i>0 && nums[i-1]==nums[i] && !used[i-1])) {
continue;
}
used[i] = true;
path.add(nums[i]);
dfs(nums);
path.removeLast();
used[i] = false;
}
}
|