代码随想录第二十九天

复习

77 组合

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

class Solution {
List<List<Integer>> result = new ArrayList<>();
List<Integer> path = new ArrayList<>();
public List<List<Integer>> combine(int n, int k) {
backTracking(n, k ,1);
return result;
}

private void backTracking(int n, int k, int start){
if(path.size() == k){
result.add(new ArrayList<>(path));
return;
}

for(int i = start; i <= n - (k - path.size()) + 1; i++){
path.add(i);
backTracking(n , k, i + 1);
path.remove(path.size() - 1);
}
}
}

17 电话号码的字母组合

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class Solution {
String[] numString = new String[] {"", "", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"};

List<String> result = new ArrayList<>();
StringBuilder sb = new StringBuilder();
public List<String> letterCombinations(String digits) {
if (digits == null || digits.length() == 0) return result;
backTracking(digits, 0);
return result;
}

private void backTracking(String digits, int start){
if (sb.length() == digits.length()){
result.add(sb.toString());
return;
}
String str = numString[digits.charAt(start) - '0'];
for (int i = 0; i< str.length(); i++){
sb.append(str.charAt(i));
backTracking(digits, start + 1);
sb.deleteCharAt(sb.length() - 1);
}
}
}

216 组合总和III

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class Solution {
List<List<Integer>> result = new ArrayList<>();

List<Integer> path = new ArrayList<>();
public List<List<Integer>> combinationSum3(int k, int n) {
backTracking(k , n, 1);
return result;
}

private void backTracking(int k, int n , int start){
if (n < 0) return;
if (n == 0 && path.size() == k){
result.add(new ArrayList<>(path));
return;
}
for (int i = start; i <= 9 - (k - path.size()) + 1; i++){
path.add(i);
n -= i;
backTracking(k, n, i + 1);
n += i;
path.remove(path.size() - 1);
}
}
}

39 组合总和

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
class Solution {
List<List<Integer>> result = new ArrayList<>();
List<Integer> path = new ArrayList<>();
public List<List<Integer>> combinationSum(int[] candidates, int target) {
if (candidates == null || candidates.length == 0) return result;
Arrays.sort(candidates);
backTracking(candidates, target, 0);
return result;
}

private void backTracking(int[] candidates, int target, int start){
if (target < 0) return;
if (target == 0){
result.add(new ArrayList<>(path));
return;
}

for (int i = start; i < candidates.length; i++){
path.add(candidates[i]);
target -= candidates[i];
backTracking(candidates, target, i);
target += candidates[i];
path.remove(path.size() - 1);
}
}
}

40 组合总和II

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
class Solution {
List<Integer> path = new ArrayList<>();
List<List<Integer>> result = new ArrayList<>();

boolean[] used;
public List<List<Integer>> combinationSum2(int[] candidates, int target) {
used = new boolean[candidates.length];
Arrays.sort(candidates);
Arrays.fill(used, false);
backTracking(candidates, target, 0);
return result;
}

private void backTracking(int[] candidates, int target, int start){
if (target == 0){
result.add(new ArrayList<>(path));
return;
}

for (int i = start; i < candidates.length; i++){
if (target < 0) break;
if (i > 0 && candidates[i] == candidates[i - 1] && !used[i - 1]) continue;
path.add(candidates[i]);
used[i] = true;
target -= candidates[i];
backTracking(candidates, target, i + 1);
target += candidates[i];
used[i] = false;
path.remove(path.size() - 1);
}
}
}

131 分割回文串

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
class Solution {
List<List<String>> result = new ArrayList<>();
List<String> path = new ArrayList<>();
public List<List<String>> partition(String s) {
if (s == null || s.length() == 0) return result;

backTracking(s, 0);
return result;
}

private void backTracking(String s, int start){
if (start == s.length()){
result.add(new ArrayList<>(path));
return;
}

for (int i = start; i < s.length(); i++){
if (isPalindrome(s, start, i)){
path.add(s.substring(start, i + 1));
backTracking(s, i + 1);
path.remove(path.size() - 1);
}
}
}

private boolean isPalindrome(String s, int start, int end){
while (start <= end){
if (s.charAt(start) != s.charAt(end)) return false;
start++;
end--;
}
return true;
}
}

93 复原ip地址

注意:
判断数字问题
判断最后一段符合逻辑
注意对s的操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
class Solution {
List<String> result = new ArrayList<>();
public List<String> restoreIpAddresses(String s) {
if (s.length() == 0 || s.length() > 12) return result;
backTracking(s, 0, 0);
return result;
}

private void backTracking(String s, int start, int points){
if (points == 3){
if (isValid(s, start, s.length() - 1)){
result.add(s);
}

return;
}

for (int i = start; i < s.length(); i++){
if (isValid(s, start, i)){
s = s.substring(0, i + 1) + "." + s.substring(i + 1);
points++;
backTracking(s, i + 2, points);
points--;
s = s.substring(0, i + 1) + s.substring(i + 2);
} else break;
}
}

private boolean isValid(String s, int start, int end){
if (start > end) return false;
if (s.charAt(start) == '0' && start != end) return false;
int num = 0;
for (int i = start; i <= end; i++){
if (s.charAt(i) - '0' > 9 || s.charAt(i) - '0' < 0) return false;
num = num * 10 + s.charAt(i) - '0';
if (num > 255) return false;
}
return true;
}
}

78 子集

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Solution {
List<List<Integer>> result = new ArrayList<>();
List<Integer> path = new ArrayList<>();
public List<List<Integer>> subsets(int[] nums) {
backTracking(nums, 0);
return result;
}

private void backTracking(int[] nums, int start){
result.add(new ArrayList(path));
for (int i = start; i < nums.length; i++){
path.add(nums[i]);
backTracking(nums, i + 1);
path.remove(path.size() - 1);
}
}
}

90 子集II

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
class Solution {
List<List<Integer>> result = new ArrayList<>();

List<Integer> path = new ArrayList<>();

boolean[] used;
public List<List<Integer>> subsetsWithDup(int[] nums) {
used = new boolean[nums.length];
Arrays.fill(used, false);
Arrays.sort(nums);
backTracking(nums, 0);
return result;
}

private void backTracking(int[] nums, int start){
result.add(new ArrayList(path));
for (int i = start; i < nums.length; i++){
if (i > 0 && nums[i] == nums[i - 1] && !used[i - 1]) continue;
path.add(nums[i]);
used[i] = true;
backTracking(nums, i + 1);
used[i] = false;
path.remove(path.size() - 1);
}
}
}

491 递增子序列

利用在回溯函数里面的hashset或者int[] 记录本层通过的点
利用if语句判断是否递增,或者是否是重复的值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
class Solution {
List<List<Integer>> result = new ArrayList<>();
List<Integer> path = new ArrayList<>();

public List<List<Integer>> findSubsequences(int[] nums) {
backTracking(nums, 0);
return result;
}

private void backTracking(int[] nums, int start){
if (path.size() >= 2){
result.add(new ArrayList<>(path));
}
int[] used = new int[201];
for (int i = start; i < nums.length; i++){
if (!path.isEmpty() && path.get(path.size() - 1) > nums[i] || used[nums[i] + 100] == 1 ) continue;
path.add(nums[i]);
used[nums[i] + 100] = 1;
backTracking(nums, i + 1);
path.remove(path.size() - 1);
}
}

private boolean isNonDecreasing(List<Integer> nums){
for (int i = 1; i < nums.size(); i++){
if (nums.get(i) < nums.get(i - 1)){
return false;
}
}

return true;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

class Solution {
List<List<Integer>> result = new ArrayList<>();
List<Integer> path = new ArrayList<>();
public List<List<Integer>> findSubsequences(int[] nums) {
backTracking(nums, 0);
return result;
}
private void backTracking(int[] nums, int start){
if (path.size() >= 2){
result.add(new ArrayList<>(path));
}
Set<Integer> set = new HashSet<>();
for (int i = start; i < nums.length; i++){
if (!path.isEmpty() && path.get(path.size() - 1) > nums[i] || set.contains(nums[i])) continue;
set.add(nums[i]);
path.add(nums[i]);
backTracking(nums, i + 1);
path.remove(path.size() - 1);
}
}
}

46 全排列

第一种 利用used记录path里面有没有nums[i]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

class Solution {
List<List<Integer>> result = new ArrayList<>();
List<Integer> path = new ArrayList<>();
boolean[] used;
public List<List<Integer>> permute(int[] nums) {
used = new boolean[nums.length];
backTracking(nums);
return result;
}

private void backTracking(int[] nums){
if (path.size() == nums.length){
result.add(new ArrayList<>(path));
return;
}

for (int i = 0; i < nums.length; i++){
if (used[i]) continue;
used[i] = true;
path.add(nums[i]);
backTracking(nums);
used[i] = false;
path.removeLast();
}
}
}

第二种直接通过检查path里面有没有nums[i] 元素判断
List 有个 removeLast 方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class Solution {
List<List<Integer>> result = new ArrayList<>();
List<Integer> path = new ArrayList<>();
public List<List<Integer>> permute(int[] nums) {
backTracking(nums);
return result;
}

private void backTracking(int[] nums){
if (path.size() == nums.length){
result.add(new ArrayList<>(path));
return;
}

for (int i = 0; i < nums.length; i++){
if (path.contains(nums[i])) continue;
path.add(nums[i]);
backTracking(nums);
path.removeLast();
}
}
}

47 全排列II

去重代码中
!used[i - 1] 是树层去重
used[i - 1] 是树枝去重
要确定used[i] 是否为false, 因为i一直是从0开始的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
class Solution {
List<List<Integer>> result = new ArrayList<>();
List<Integer> path = new ArrayList<>();

boolean[] used;
public List<List<Integer>> permuteUnique(int[] nums) {
used = new boolean[nums.length];
Arrays.sort(nums);
backTracking(nums);
return result;
}

private void backTracking(int[] nums){
if (path.size() == nums.length){
result.add(new ArrayList<>(path));
return;
}
for (int i = 0; i < nums.length; i++){
if (i > 0 && nums[i] == nums[i - 1] && !used[i - 1]) continue;

if (used[i] == false){
used[i] = true;
path.add(nums[i]);
backTracking(nums);
path.removeLast();
used[i] = false;
}
}
}
}