【路飞】1288. 删除被覆盖区间、491. 递增子序列

130 阅读1分钟

1288. 删除被覆盖区间

给你一个区间列表,请你删除列表中被其他区间所覆盖的区间。

只有当 c <= a 且 b <= d 时,我们才认为区间 [a,b) 被区间 [c,d) 覆盖。

在完成所有删除操作后,请你返回列表中剩余区间的数目。

示例:

输入: intervals = [[1,4],[3,6],[2,8]]
输出: 2
解释: 区间 [3,6] 被区间 [2,8] 覆盖,所以它被删除了。

解题思路:一个区间如果要被覆盖,必须满足两个条件,比如区间a1 = [1,8],如果区间 a2要被a1覆盖的话,a2的左区间要大于等于1,右区间要小于等于8,所以我们可以将intervals数组按照左区间从小到大排序,这样的话右边的左区间始终大于等于左边的左区间,被包含在内了,现在只要判断,左边的数据右区间是否大于右边数据的右区间了,如果左边数据右区间大于左边的,那么右边的数据就被覆盖,所以当左区间相等的时候按照右区间大到小排序,可以找到左边右区间最大值,当右边右区间小于等于左边右区间最大值是,右边数据就被覆盖了,代码如下:

var removeCoveredIntervals = function(intervals) {
    //将数组按照左区间由小到大排序,当左区间相等的时候按照右区间大到小排序
    intervals.sort(function(a,b){
        if(a[0] == b[0]) return b[1] - a[1];
        else return a[0] - b[0];
    })
    //cnt记录的是有多少个区间被覆盖,记录左边最大的右区间值
    let cnt = 0,r_max = -1;
    for(let i = 0; i < intervals.length; i ++){
        //a是当前区间的左区间,因为已经按照小到大排序的,所以不用比较,b是右区间,当b小于最大右区间值,就说明被覆盖了,如果小于,就替换最大值
        let [a,b] = intervals[i]
        if(b <= r_max) cnt ++;
        else r_max = b;
    }
    //cnt是被覆盖的区间数量
    return intervals.length - cnt;
};

491. 递增子序列

给你一个整数数组 nums ,找出并返回所有该数组中不同的递增子序列,递增子序列中 至少有两个元素 。你可以按 任意顺序 返回答案。

数组中可能含有重复元素,如出现两个整数相等,也可以视作递增序列的一种特殊情况。 示例 1:

输入:nums = [4,6,7,7]
输出:[[4,6],[4,6,7],[4,6,7,7],[4,7],[4,7,7],[6,7],[6,7,7],[7,7]]

示例 2:

输入: nums = [4,4,3,2,1]
输出: [[4,4]]

解题思路:这题是利用的递归来组合数据,代码如下

var findSubsequences = function(nums) {
    //保存符合条件的数组
    let ret = [];
    //0代表的是从第0位开始遍历,[]是组合的数组
    find_subsequences(nums,0,[],ret)
    return ret;
};

let find_subsequences = function(arr,k,buff,ret){
    //因为是数组要大于两位,所以当组合的数组大于1的时候就保存到ret中,[...buff]就相当于是重新定义的一个数组,不然里面内容会被新的内容更新
    if(buff.length > 1) ret.push([...buff]);
    //默认新增加的数字是0
    buff.push(0);
    //记录当前循环已有数据,避免重复
    let set = {};
    for(let i = k; i < arr.length; i ++){
       //如果当前循环这个数字已经组合过,就不用再组合了,避免重复
        if(set[arr[i]]) continue;
        //如果buff只有一个值,那肯定就是0,所以需要替换,因为buff最后以为是0 ,所以需要与buff倒数第二位比较,替换
        if(buff.length == 1 || arr[i] >= buff[buff.length - 2]){
            buff[buff.length - 1] = arr[i];
            //记录当前循环已经组合过的数字
            set[arr[i]] = 1;
            //第一次循环是[4]继续与后面组合,循环还会继续,就是[4,6]继续与后面数组组合
            find_subsequences(arr,i + 1,[...buff],ret);
        }
    }
    return;
}

面试题 04.12. 求和路径

给定一棵二叉树,其中每个节点都含有一个整数数值(该值或正或负)。设计一个算法,打印节点数值总和等于某个给定值的所有路径的数量。注意,路径不一定非得从二叉树的根节点或叶节点开始或结束,但是其方向必须向下(只能从父节点指向子节点方向)。 示例: 给定如下二叉树,以及目标和 sum = 22

              5
             / \
            4   8
           /   / \
          11  13  4
         /  \    / \
        7    2  5   1

返回:

3
解释: 和为 22 的路径有:[5,4,11,2], [5,8,4,5], [4,11,7]

解题思路:这题就是通过递归来计算,代码如下:

var pathSum = function(root, sum) {
    if(!root) return 0;
    //从根节点开始遍历是否存在等于sum值
    let a = path_sum(root,sum);
    // 根节点,加左节点,和右节点
    return a + pathSum(root.left,sum) + pathSum(root.right,sum);
};

let path_sum = function(root,sum){
    if(!root) return 0;
    let val = sum - root.val;
    //(root.val == sum)  == 1
    return (root.val == sum) + path_sum(root.left,val) + path_sum(root.right,val);
}