美文网首页图解LeetCode算法
图解LeetCode——891. 子序列宽度之和(难度:困难)

图解LeetCode——891. 子序列宽度之和(难度:困难)

作者: 爪哇缪斯 | 来源:发表于2022-11-17 09:46 被阅读0次

    一、题目

    一个序列的 宽度 定义为该序列中最大元素和最小元素的差值。

    给你一个整数数组 nums ,返回 nums 的所有非空 子序列宽度之和 。由于答案可能非常大,请返回对 10^9 + 7 取余 后的结果。

    子序列 定义为从一个数组里删除一些(或者不删除)元素,但不改变剩下元素的顺序得到的数组。例如,[3,6,2,7] 就是数组 [0,3,1,6,2,2,7] 的一个子序列。

    二、示例

    2.1> 示例 1:

    【输入】nums = [2,1,3]
    【输出】6
    【解释】子序列为 [1], [2], [3], [2,1], [2,3], [1,3], [2,1,3] 。相应的宽度是 0, 0, 0, 1, 1, 2, 2 。宽度之和是 6 。

    2.2> 示例 2:

    【输入】nums = [2]
    【输出】0

    提示:

    • 1 <= nums.length <= 10^5
    • 1 <= nums[i] <= 10^5

    三、解题思路

    根据题目描述我们可以知道,计算宽度的时候,只是需要计算序列中【最大元素】与【最小元素】的差值。那么我们只需要关心数组nums中数字的大小而不需要关心它所在的位置了,即:子序列[2,4]与子序列[4,2]差值都是2。

    那么,既然我们主要关注点是数组nums中的每个元素值大小,为了方便计算,我们首先可以对nums进行排序操作。

    排序之后,我们随便找一个下标为i的元素,可以找到以下规律:

    下面是以nums[i]其左侧所有元素拼装组合成的子序列示例:

    那么,针对于nums[i]来说,它的宽度总和就是: (2i-2nums.length-i-1) * nums[i] ,那么我们遍历所有nums数组中的元素,逐一计算每个元素的宽度总和,那么最终结果就是本题的答案。

    四、代码实现

    class Solution {
        public int sumSubseqWidths(int[] nums) {
            Arrays.sort(nums); // 排序
            int mod = (int)1e9 + 7, n = nums.length;
            long result = 0;
            long[] pow = new long[n];
            pow[0] = 1;
            for (int i = 1; i < n; i++) 
                pow[i] = (pow[i - 1] << 1) % mod; // 初始化2^n的值
    
            for (int i = 0; i < n; i++)
                result = (result + (pow[i] - pow[n-i-1]) * nums[i] % mod) % mod; // 计算总和          
            return (int)result;
        }
    }
    

    今天的文章内容就这些了:

    写作不易,笔者几个小时甚至数天完成的一篇文章,只愿换来您几秒钟的 点赞 & 分享

    更多技术干货,欢迎大家关注公众号“爪哇缪斯” ~ \(o)/ ~ 「干货分享,每天更新」

    相关文章

      网友评论

        本文标题:图解LeetCode——891. 子序列宽度之和(难度:困难)

        本文链接:https://www.haomeiwen.com/subject/jjxpxdtx.html