算法练习day24

68 阅读1分钟

一、复原IP地址

此题关键在于分割字符串的同时要加上分割点,注意起始位置startIndex 为i + 2

终止条件为当点数等于3的时候只需要判断后面的子串是否合法即可

/**
 * @param {string} s
 * @return {string[]}
 */
var restoreIpAddresses = function(s) {
    let result = []
    function isValid(s, start, end) {
        if(start > end) {
            return false
        }
        if(s[start] === '0' && start !== end) {
            return false
        }
        let num = 0
        for(let i = start; i <= end; i++) {
            if(s[i] > '9' || s[i] < 0) {
                return false
            }
            num = num * 10 + Number(s[i])
            if(num > 255) {
                return false
            }
        }
        return true
    }

    function backtracking(s, startIndex, pointNum) {
        if(pointNum === 3) {
            if(isValid(s, startIndex, s.length - 1)) {
                result.push(s)
            }
            return 
        }
        for(let i = startIndex; i < s.length; i++) {
            if(isValid(s, startIndex, i)) {
                backtracking(s.substring(0, i + 1) + '.' + s.substring(i + 1), i + 2, pointNum + 1)
            } else {
                break
            }
        }
    }
    if(s.length > 12) {
        return []
    }
    backtracking(s, 0, 0)
    return result
};

二、子集

和之前的组合问题不同,子集相当于把所有子节点记录下来,需要遍历整颗树,所以不需要剪枝

/**
 * @param {number[]} nums
 * @return {number[][]}
 */
var subsets = function(nums) {
    let path = []
    let result = []
    function backtracking(startIndex) {
        if(startIndex > nums.length) {
            return
        }
        result.push([...path])
        for(let i = startIndex; i < nums.length; i++) {
            path.push(nums[i])
            backtracking(i + 1)
            path.pop()
        }
    }
    backtracking(0)
    return result
};

三、子集2

此题和子集的区别在于集合是可以有重复的,需要去重,所以需要排序,还有就是树层去重和树枝去重的理解,和之前组合问题的去重一样

/**
 * @param {number[]} nums
 * @return {number[][]}
 */
var subsetsWithDup = function (nums) {
    let path = []
    let result = []
    nums.sort((x, y) => x - y)
    function backtracking(startIndex) {
        if (startIndex > nums.length) {
            return
        }
        result.push([...path])
        for (let i = startIndex; i < nums.length; i++) {
            if(i > startIndex && nums[i] === nums[i - 1]) {
                continue
            }
            path.push(nums[i])
            backtracking(i + 1)
            path.pop()
        }
    }
    backtracking(0)
    return result
};