leetcode每天5题-Day51

上一篇:回溯算法的组合问题
这一篇记录回溯算法的切割问题与子集问题。

1.分割回文串

131. 分割回文串-中等
b站视频讲解
难点:

  • 切割问题如何抽象为组合问题?
  • 用什么模拟切割线?
  • 递归终止条件
function isPalindrome(s, l, r) {
    while(l <= r) {
        if(s[l] !== s[r]) {
            return false;
        }
        l++, r--;
    }
    return true;
}
var partition = function(s) {
    const ans = [], path = [];
    const backtracing = (s, index) => {
        if(index >= s.length) {
            ans.push([...path]);
            return;
        }
        for(let i = index; i < s.length; i++) {
            if(isPalindrome(s, index, i)) {
                let str = s.substring(index, i + 1);
                path.push(str);
            }else{
                continue;
            }
            backtracing(s, i + 1);
            path.pop();
        }
    }
    backtracing(s, 0);
    return ans;
};

2.复原 IP 地址

93. 复原 IP 地址-中等
b站视频讲解
思路:利用.作分割,一个合法的IP地址总共有三个.,每次都需要对.之前的子串进行判断,看是否合法。当有三个.时,需要对.之后的子串进行判断。

var restoreIpAddresses = function(s) {
    const ans = [], path = [];
    const backtracing = (index) => {
        if(path.length > 4) {
            return;
        }
        if(path.length === 4 && index === s.length) {
            ans.push(path.join('.'));
            return;
        }
        for(let i = index; i < s.length; i++) {
            let number = s.substring(index, i + 1);
            if(number.length > 3 || +number > 255) break;
            if(number.length > 1 && number[0] === '0') break;
            path.push(number);
            backtracing(i + 1);
            path.pop();          
        }
    }
    backtracing(0);
    return ans;
};

3.子集

78. 子集-中等
b站视频讲解
思路:子集问题与组合、切割问题不同之处在于,子集问题要收集每个节点,而组合、切割问题只收集叶子节点。做完了组合与切割问题的题,一下子就能写出来子集的题。

var subsets = function(nums) {
    const ans = [], path = [];
    const backtracing = (index) => {
        ans.push([...path]);
        for(let i = index; i < nums.length; i++) {
            path.push(nums[i]);
            backtracing(i + 1);
            path.pop();
        }
    }
    backtracing(0);
    return ans;
};

4.子集 II

90. 子集 II-中等
b站视频讲解
思路:该题与组合总和II很像,在上题(子集)的基础上加了去重。

var subsetsWithDup = function(nums) {
    const ans = [], path = [];
    nums.sort();
    const backtracing = (index) => {
        ans.push([...path]);
        for(let i = index; i < nums.length; i++) {
            if(i > index && nums[i] === nums[i - 1]) continue;
            path.push(nums[i]);
            backtracing(i + 1);
            path.pop();
        }
    }
    backtracing(0);
    return ans;
};

5. 递增子序列

491. 递增子序列-中等
b站视频讲解
重点:

  • 怎么使其递增
    本题不是比较nums[i]nums[i-1]的关系,而是比较nums[i]path[path.length-1]的关系。
  • 怎么去重
    与前几道题不同的是,该题中的数组不能排序,那么怎么去重呢?使用Set或者uset数组,每一层定义一个uset,进行判断。
  1. 注:for循环内的if条件判断的与/或关系很重要。
  2. if(path.length > 1) { ans.push([...path]); // return; }中不要写return,因为把path放进ans后,还要接着向下做判断,把符合条件的数组元素继续放进path里。否则path里会只有两个元素。
var findSubsequences = function(nums) {
    const ans = [], path = [];
    const backtracing = (index) => {
        if(path.length > 1) {
            ans.push([...path]);
        }
        // let set = new Set();
        let uset = [];
        for(let i = index; i < nums.length; i++) {
            if((path.length > 0 && nums[i] < path[path.length - 1]) || uset[nums[i] + 100]) {
                // set.has(nums[i])
                continue;
            }
            // set.add(nums[i]);
            uset[nums[i] + 100] = true;
            path.push(nums[i]);
            backtracing(i + 1);
            path.pop();
        }
    }
    backtracing(0);
    return ans;
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值