day24 回溯算法-ip+subsets*2

### 7.8 93. Restore IP Addresses
A valid IP address consists of exactly four integers separated by single dots. Each integer is between 0 and 255 (inclusive) and cannot have leading zeros.
For example, "0.1.2.201" and "192.168.1.1" are valid IP addresses, but "0.011.255.245", "192.168.1.312" and "192.168@1.1" are invalid IP addresses.
Given a string s containing only digits, return all possible valid IP addresses that can be formed by inserting dots into s. You are not allowed to reorder or remove any digits in s. You may return the valid IP addresses in any order.
https://programmercarl.com/0093.%E5%A4%8D%E5%8E%9FIP%E5%9C%B0%E5%9D%80.html  
这题卡住的地方:无需建立中间的path,本质上只是在原有字符串上打点。
写的过程中出错的地方:辅助函数isValid中,让0开头的非0数字不合法的语句中,charAt(int)返回的是char,所以应该是`=='0'。
```java
List<String> result = new LinkedList<>();  
public List<String> restoreIpAddresses(String s) {  
    StringBuilder sb = new StringBuilder(s);  
    backtracking(sb,0,0);  
    return result;  
}  
private void backtracking(StringBuilder sb, int startIndex, int pointSum){  
    if(pointSum == 3){  
        if(isValid(sb,startIndex,sb.length()-1)){  
            result.add(sb.toString());  
        }  
        return;  
    }  
    for (int i = startIndex; i < sb.length(); i++) {  
        if(isValid(sb,startIndex,i)){  
            sb.insert(i+1,".");  
            pointSum++;  
        }else{  
            break;//后面的不用再看了,直接退出  
        }  
        backtracking(sb,i+2,pointSum);  
        sb.deleteCharAt(i+1);  
        pointSum--;  
    }  
}  
private boolean isValid(StringBuilder sb, int start, int end){  
    if(end < start){  
        return false;  
    }  
    //这里的0是char,所以要打上''!!!不然是不会return false的!  
    if(sb.charAt(start) == '0' && start != end){  
        return false;  
    }  
    int num = 0;  
    for (int i = start; i <= end; i++) {  
        int digit = sb.charAt(i) - '0';  
        num = num * 10 + digit;  
        if(num > 255) return false;  
    }  
    return true;  
}
```
### 7.9 78. Subsets
Given an integer array nums of unique elements, return all possible subsets (the power set).
The solution set must not contain duplicate subsets. Return the solution in any order.
Example 1:
Input: nums =` [1,2,3]
Output: `[[],[1],[2],[1,2],[3],[1,3],[2,3],[1,2,3]]
Example 2:
Input: nums =` [0]
Output:` [[],[0]]
 78.子集  
子集问题,就是收集树形结构中,每一个节点的结果。 整体代码其实和 回溯模板都是差不多的。 
https://programmercarl.com/0078.%E5%AD%90%E9%9B%86.html  
终止条件:到达叶子节点。
startIndex > nums.length()
那什么时候把path放入result呢?在终止条件的上方。每次进入递归,就收获结果。
```java
public class subsets78 {  
    List<List<Integer>> result = new LinkedList<>();  
    LinkedList<Integer> path = new LinkedList<>();  
  
    public List<List<Integer>> subsets(int[] nums) {  
        backtracking(nums,0);  
        return result;  
    }  
    private void backtracking(int[] nums, int startIndex){  
        //收获结果  
        result.add(new ArrayList<>(path));  
        //终止条件  
        if(startIndex > nums.length) return;  
        for (int i = startIndex; i < nums.length; i++) {  
            path.add(nums[i]);  
            backtracking(nums,i+1);  
            path.removeLast();  
            startIndex--;  
        }  
    }  
}  
class subsets78Test {  
    public static void main(String[] args) {  
        subsets78 example = new subsets78();  
        int[] nums = {1,2,3};  
        List<List<Integer>> result = example.subsets(nums);  
        for(List<Integer> levels :result){  
            System.out.print("[");  
            for(int i : levels){  
                System.out.print(i+" ");  
            }  
            System.out.println("]");  
        }  
    }  
}
```
### 7.10 90. Subsets II
Given an integer array nums that may contain duplicates, return all possible subsets (the power set).
The solution set must not contain duplicate subsets. Return the solution in any order.
Example 1:
Input: nums = `[1,2,2]
Output: `[[],[1],[1,2],[1,2,2],[2],[2,2]]
Example 2:
Input: nums =` [0]
Output:` [[],[0]]`
90.子集II 
大家之前做了 40.组合总和II 和 78.子集 ,本题就是这两道题目的结合,建议自己独立做一做,本题涉及的知识,之前都讲过,没有新内容。 
https://programmercarl.com/0090.%E5%AD%90%E9%9B%86II.html   

这类题目要记得给数组排序!!
```java
public class subsets90 {  
    List<List<Integer>> result = new LinkedList<>();  
    LinkedList<Integer> path = new LinkedList<>();  
    public List<List<Integer>> subsetsWithDup(int[] nums) {  
        int[] used = new int[nums.length];  
        Arrays.sort(nums);  
        backtracking(nums,0,used);  
        return result;  
    }  
    private void backtracking(int[] nums, int startIndex, int[] used){  
        result.add(new ArrayList<>(path));  
  
        if(startIndex > nums.length) return;  
  
        for (int i = startIndex; i < nums.length; i++) {  
            //used[i-1] == 0意味着前一位重复元素之前没有在同一层遍历上使用过,这种情况需要做去重。直接continue,不处理后面的数据即可。  
            if(i > 0 && nums[i] == nums[i-1] && used[i-1] == 0) continue;  
            path.add(nums[i]);  
            used[i] = 1;  
            backtracking(nums,i+1,used);  
            path.removeLast();  
            startIndex--;  
            used[i] = 0;  
        }  
    }  
}  
class subsets90Test {  
    public static void main(String[] args) {  
        subsets90 example = new subsets90();  
        int[] nums = {4,4,4,1,4};  
        List<List<Integer>> result = example.subsetsWithDup(nums);  
        for(List<Integer> levels :result){  
            System.out.print("[");  
            for(int i : levels){  
                System.out.print(i+" ");  
            }  
            System.out.println("]");  
        }  
    }  
}
```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值