day24|93复原IP地址78子集90子集II|01笔记

81 阅读1分钟
  • 93复原IP地址

  • 代码随想录 (programmercarl.com)
  • 第一印象

  • 这是一道切割的题目,切割点就在.上,在判断是否是有效数字时需要仔细讨论
  • 讲解观后感

  • 本题除了要有idx记录分割位置,还要有pointnum记录逗点的数量,终止条件也是达到3个逗点时判断。或者用path记录分段数,到达4段后终止。
  • 解题代码

  •     var (
            path []string
            res  []string
        )
        func restoreIpAddresses(s string) []string {
            path, res = make([]string, 0, len(s)), make([]string, 0)
            dfs(s, 0)
            return res
        }
        func dfs(s string, start int) {  
            if len(path) == 4 {    // 够四段后就不再继续往下递归
                if start == len(s) {      //start在len(s)表示已经遍历到最后
                    str := strings.Join(path, ".")
                    res = append(res, str)
                }
                return 
            }
            for i := start; i < len(s); i++ {
                if i != start && s[start] == '0' { // 含有前导 0,无效
                    break
                }
                str := s[start : i+1]
                num, _ := strconv.Atoi(str)
                if num >= 0 && num <= 255 {
                    path = append(path, str)  // 符合条件的就进入下一层
                    dfs(s, i+1)
                    path = path[:len(path) - 1]
                } else {   // 如果不满足条件,再往后也不可能满足条件,直接退出
                    break
                }
            }
        }
    
  • 78子集

  • 代码随想录 (programmercarl.com)
  • 第一印象

  • 这题和组合十分相似,不限制组合数量并且不能重复的就是子集。用path记录子集,因为元素不会重复,所以直接idx+1向下添加即可。
  • 不要忘了添加空集。
  • 解题代码

  •     func subsets(nums []int) [][]int {
            ans :=  [][]int{}
            path := []int{}
            kong := []int{}
            ans = append(ans, kong)
            if len(nums) == 0 {
                return ans
            }
        
            var backtrac func(nums []int, idx int)
            backtrac = func(nums []int, idx int) {
                
                for i:=idx;i<len(nums);i++ {
                    path = append(path, nums[i])
                    tmp := make([]int, len(path))
                    copy(tmp, path)
                    ans = append(ans, tmp)
                    backtrac(nums, i+1)
                    path = path[:len(path)-1]           
                }
                return
            }
            backtrac(nums, 0)
            return ans
        }
    
  • 90子集II

  • 代码随想录 (programmercarl.com)
  • 第一印象

  • 78子集题的升级版,当集合内有重复元素的时候,如何进行去重就是需要着重处理的对象。第一想法是使用排序后类似used数组的标记方式。
  • 讲解观后感

  • 也可以直接使用i!=idx&&nums[i]==nums[i-1]的方式来去重
  • 解题代码

  • 不使用used
  •     func subsetsWithDup(nums []int) [][]int {
            ans := [][]int{}
            path := []int{}
            kong := []int{}
            ans = append(ans, kong)
            if len(nums) == 0 {
                return ans
            }
            sort.Ints(nums)
            var backtrac func(nums []int, idx int)
            backtrac = func(nums []int, idx int) {
                for i:=idx;i<len(nums);i++ {
                    if i!=idx&&nums[i]==nums[i-1] {
                        continue
                    }
                    path = append(path, nums[i])
                    tmp := make([]int, len(path))
                    copy(tmp, path)
                    ans = append(ans, tmp)
                    backtrac(nums, i+1)
                    path = path[:len(path)-1]
                }     
                return   
            }
            backtrac(nums, 0)
        
            return ans
        }
    
  • 使用used(C++)
  •     class Solution {
        private:
            vector<vector<int>> result;
            vector<int> path;
            void backtracking(vector<int>& nums, int startIndex, vector<bool>& used) {
                result.push_back(path);
                for (int i = startIndex; i < nums.size(); i++) {
                    // used[i - 1] == true,说明同一树枝candidates[i - 1]使用过
                    // used[i - 1] == false,说明同一树层candidates[i - 1]使用过
                    // 而我们要对同一树层使用过的元素进行跳过
                    if (i > 0 && nums[i] == nums[i - 1] && used[i - 1] == false) {
                        continue;
                    }
                    path.push_back(nums[i]);
                    used[i] = true;
                    backtracking(nums, i + 1, used);
                    used[i] = false;
                    path.pop_back();
                }
            }
        
        public:
            vector<vector<int>> subsetsWithDup(vector<int>& nums) {
                result.clear();
                path.clear();
                vector<bool> used(nums.size(), false);
                sort(nums.begin(), nums.end()); // 去重需要排序
                backtracking(nums, 0, used);
                return result;
            }
        };