算法--最短连续数列

180 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第7天,点击查看活动详情

题目

给你一个数组 nums,请你从中抽取一个子序列,满足该子序列的元素之和 严格 大于未包含在该子序列中的各元素之和。

如果存在多个解决方案,只需返回长度最小的子序列。如果仍然有多个解决方案,则返回元素之和最大的子序列。

注意,题目数据保证满足所有约束条件的解决方案是 唯一 的。同时,返回的答案应当按 非递增顺序 排列。

示例:


示例 1:

输入:nums = [4,3,10,9,8]
输出:[10,9,8] 
解释:子序列 [10,9, 8]是连续的递减是最小的、满足元素之和大于其他各元素之和的子序列。

题解

题目的意思是找出连续的递减子序列。题目的解法大多数都是在进行排序计算。突破点是 3 - 10 这个位置连续递减之后就开始递增。这时候得出一个局部解,通过递归得到所有的递减序列。最后再对这些序列进行总结即可得出答案。

var minSubsequence = function(nums) {
    const len = nums.length;

    let res = [[nums[0]]];
    for (let i = 1; i < len; i++) {
        if (nums[i] < nums[i - 1]) {
            res[res.length - 1].push(nums[i]);
        }else{
            res.push([nums[i]])
        } 
    }
    res.sort((a,b)=>{
        if (a.length === b.length) {
            const aCount = a.reduce((a,b)=> a + b);
            const bCount = b.reduce((a,b)=> a + b);
            return -aCount + bCount;
        }
       return  a.length - b.length;
    })
    return res[0]

};

代码详解

定义变量res来存储我们每次遍历得到的递减序列,初始化为nums数组里的第一项。然后从nums数组的第二项开始遍历如果是比前一项小那么就往第一个结果数组里面加入这项。否则就另外开启一个数组来保存第二项的结果。

在遍历完成之后有多个长度一样的子序列,题目的意思是找出和最大的作为答案。我们对所有结果进行排序:

    res.sort((a,b)=>{
        if (a.length === b.length) {
            const aCount = a.reduce((a,b)=> a + b);
            const bCount = b.reduce((a,b)=> a + b);
            return -aCount + bCount;
        }
       return  a.length - b.length;
    })

数组的sort方法是 传入一个回调函数,回调函数的参数为数组的当前项和下一位,通过返回值的正负来进行升序或降序排列。如果长度相等的时候就再进行一次判断他们的和是降序排列。

最后返回结果数组的第一项即可。