代码随想录第二十八天

复习

77 组合

注意剪枝操作,以及for loop的判断条件

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>> combine(int n, int k) {
getPath(n , k, 1);
return result;
}

private void getPath(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);
getPath(n, k, i + 1);
path.remove(path.size() - 1);
}
}
}

17 电话号码的字母组合

注意for loop之前的值

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
class Solution {
String[] numString = {"", "", "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);
}
}
}

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
27
28
class Solution {
List<List<Integer>> result = new ArrayList<>();
List<Integer> path = new ArrayList<>();

public List<List<Integer>> combinationSum(int[] candidates, int target) {
if (candidates.length == 0) return result;
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++){
target -= candidates[i];
path.add(candidates[i]);
backTracking(candidates, target, i);
path.remove(path.size() - 1);
target += candidates[i];
}
}
}

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
33
class Solution {
List<List<Integer>> result = new ArrayList<>();
List<Integer> path = new ArrayList<>();
boolean[] used;

public List<List<Integer>> combinationSum2(int[] candidates, int target) {
used = new boolean[candidates.length];
Arrays.fill(used, false);
Arrays.sort(candidates);
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;

target -= candidates[i];
path.add(candidates[i]);
used[i] = true;
backTracking(candidates, target, i + 1);
path.remove(path.size() - 1);
target += candidates[i];
used[i] = false;
}
}
}

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++){
n -= i;
path.add(i);
backTracking(k, n, i + 1);
path.remove(path.size() - 1);
n += i;
}
}
}

131 分割回文串

分割过程的for loop
先是切割出一个字符判断,如果是,就切割第二个,是切割第三个,完成后
第二个循环开始,直接切割两个,是移动,不是就继续第三个循环

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<List<String>> result = new ArrayList<>();
List<String> path = new ArrayList<>();
public List<List<String>> partition(String s) {
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 left, int right){
while (left <= right){
if (s.charAt(left) != s.charAt(right)) return false;
left++;
right--;
}

return true;
}
}

93 复原IP 地址

分割问题和分割回文串类似
几个重点,

  1. 代码随想录利用了一个pointnum记录逗号数量,判断
    我没有用pointnum
    我用Integer.parseInt()转化了string
  2. 在实际问题中,判断数字是否valid也很重要
    1. 数字起始不能有0
    2. 数字要在0 到 255中间
      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
      41
      42
      43
      44
      45
      46
      47
      48
      49
      50
      51
      52
      53
      54
      class Solution {
      List<String> result = new ArrayList<>();
      List<Integer> path = new ArrayList<>();
      public List<String> restoreIpAddresses(String s) {
      backTracking(s, 0);
      return result;
      }

      private void backTracking(String s, int start){
      if (path.size() == 4){
      StringBuilder sb = new StringBuilder();
      for (int i = 0; i < path.size() - 1; i++){
      sb.append(path.get(i)).append(".");
      }
      sb.append(path.get(path.size() - 1));
      if (sb.length() == s.length() + 3){
      result.add(sb.toString());
      }
      return;
      }

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

      }
      }

      private boolean isValid(String s, int start, int end){
      if (start > end){
      return false;
      }
      if (s.charAt(start) == '0' && end != start) return false;

      int num = 0;
      for (int i = start; i <= end; i++){
      if (s.charAt(i) > '9' || s.charAt(i) < '0'){
      return false;
      }

      num = num * 10 + (s.charAt(i) - '0');
      if (num > 255){
      return false;
      }
      }

      return true;
      }
      }

78 子集

与组合和分割都不一样,
如果把子集问题抽象成树,就要把所有结点都记录下来

终止条件,就是start到了nums length的时候

result一直添加path

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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));
if (start >= nums.length) return;

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
28
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.sort(nums);
Arrays.fill(used, false);
backTracking(nums, 0);
return result;
}

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

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

拓展 645 setmismatch

思路
利用loop循环查找,不等于同位置的结点,将该节点放到对应的位置上,进行排序,然后再利用for loop查找不等于该位置上的值输出result

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
class Solution {
public int[] findErrorNums(int[] nums) {
int[] result = new int[2];
int i = 0;
while (i < nums.length){
if (nums[nums[i] - 1] != nums[i]){
swap(nums, nums[i] - 1, i);
} else {
i++;
}
}

for (i = 0; i < nums.length; i++){
if (nums[i] != i + 1){
result[0] = nums[i];
result[1] = i + 1;
}
}

return result;
}

private void swap(int[] nums, int index1, int index2){
nums[index1] ^= nums[index2];
nums[index2] ^= nums[index1];
nums[index1] ^= nums[index2];
}
}