【算法】Sum of Imbalance Numbers of All Subarrays 所有子数组中不平衡数字之和-进阶篇

这篇具有很好参考价值的文章主要介绍了【算法】Sum of Imbalance Numbers of All Subarrays 所有子数组中不平衡数字之和-进阶篇。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

Sum of Imbalance Numbers of All Subarrays 所有子数组中不平衡数字之和

问题描述:

一个长度为 n 下标从 0 开始的整数数组 arr 的 不平衡数字 定义为,在 sarr = sorted(arr) 数组中,满足以下条件的下标数目:

0 < = i < n − 1 ,和 s a r r [ i + 1 ] − s a r r [ i ] > 1 0 <= i < n - 1 ,和 sarr[i+1] - sarr[i] > 1 0<=i<n1,和sarr[i+1]sarr[i]>1
这里,sorted(arr) 表示将数组 arr 排序后得到的数组。

给你一个下标从 0 开始的整数数组 nums ,请你返回它所有 子数组 的 不平衡数字 之和。

子数组指的是一个数组中连续一段 非空 的元素序列。

1 < = n u m s . l e n g t h < = 1000   1 < = n u m s [ i ] < = n u m s . l e n g t h 1 <= nums.length <= 1000\\\ 1 <= nums[i] <= nums.length 1<=nums.length<=1000 1<=nums[i]<=nums.length

分析

上周contest的Q4。

进阶的时间复杂度为 O ( N ) O(N) O(N)

再沿着基础篇的思路换个角度思考,对于下标 i i i n u m s [ i ] = x nums[i]= x nums[i]=x来说,它所处于的任何子数组,只有都不存在 x − 1 , 和 x + 1 x-1,和x+1 x1,x+1,此时 x x x才有可能会对子数组产生贡献1.

为了避免重复统计,以当子数组有1个x时,且有 x-1 出现的子数组计入统计。

按照这个规则此时进入统计的子数组会有2种类型:

  • 如果x不是子数组的最小值,那么就一定存在 y < x − 1 y<x-1 y<x1, x x x对于符合条件的子数组贡献为1.
  • 如果x是子数组的最小值,此时不存在 y < x − 1 y<x-1 y<x1,因此统计这个类别的含 x的子数组贡献为0.【后面需要减去

在这个思路下,需要知道 n u m s [ i ] nums[i] nums[i],即 i i i左侧第一个值 n u m s [ i ] − 1 nums[i]-1 nums[i]1下标位置L,还要知道 i i i右侧第一个值 n u m s [ i ] nums[i] nums[i]位置R

那么当右侧的都是以 i i i为结尾的,而且符合上述条件进入统计的子数组的数量就是 i − L i-L iL, 此时 n u m s [ i ] nums[i] nums[i]可能是最小值,也可能是不是最小值

i i i左侧就是 i i i为开始的,而且符合上述条件进入统计的子数组的数量就是 R − i R-i Ri,此时 n u m s [ i ] nums[i] nums[i]可能是最小值,也可能是不是最小值

2侧的子数组数量已知,相乘就可以得到 n u m s [ i ] nums[i] nums[i] 作为最小值,或者非最小值的子数组。

一切似乎很完美,但是还存在一个问题。

特殊的情况

如果在 下标 i i i 出现了 n u m s [ i ] = x nums[i]=x nums[i]=x,在下标 j j j出现 n u m s [ j ] = x nums[j]=x nums[j]=x.上面的逻辑就会进入重复的统计,即处于 i → j i\rightarrow j ij 的一段。
当处于 i i i时,统计了一次 [ L , j ] [L,j] [L,j],而枚举到 j j j时,再一次统计 [ L , j ] [L,j] [L,j].

调整策略

为了避免这个情况,需要对2侧的条件进行调整。
即在枚举位置 i i i 时, n u m s [ i ] 值为 x nums[i]值为x nums[i]值为x,在向右找边界的时候,要找第一个值 n u m s [ R + 1 ] = = x nums[R+1]==x nums[R+1]==x 或者 n u m s [ R + 1 ] = = x − 1 nums[R+1]==x-1 nums[R+1]==x1,或者 R = = n R==n R==n[右侧没有这2个值]。

向左找边界,依然寻找第一个 n u m s [ L − 1 ] = = x − 1 nums[L-1]==x-1 nums[L1]==x1,或者 L = − 1 L=-1 L=1[左侧没有这个值]。

到此已经完成了 99 % 99\% 99%,还有最后一部分

就是当 x x x属于子数组的最小值的情况,这个子数组也被计入统计结果,所以需要将每个值作为最小值的子数组的数量从统计结果中减去

朴素的思路一定是枚举,但是这个时间复杂度是不可能支持的

换个角度思考长度为 n n n 的数组,它的所有子数组的数量为 n ( 1 + n ) / 2 n(1+n)/2 n(1+n)/2 , 而这个数量又恰好等于,枚举过程中统计的 x x x 作为子数组的最小值的数量。

这个不是很直观,但是确实是。因为任何长度>0的子数组,都会有一个最小值 m i n min min,而且这个子数组一定会被统计。有 c n t = n ( 1 + n ) / 2 cnt=n(1+n)/2 cnt=n(1+n)/2的子数组,在统计结果中就会有相同的数量子数组产生贡献0,需要被减去。

总的来说,这个思路,非常的细腻。

代码

class Solution {
    public int sumImbalanceNumbers(int[] nums) {
        int n = nums.length;
        var right = new int[n];
        var idx = new int[n + 1];
        Arrays.fill(idx, n);
        for (int i = n - 1; i >= 0; i--) {
            int x = nums[i];
            // right[i] 表示 nums[i] 右侧的 x 和 x-1 的最近下标(不存在时为 n)
            right[i] = Math.min(idx[x], idx[x - 1]);
            idx[x] = i;
        }

        int ans = 0;
        Arrays.fill(idx, -1);
        for (int i = 0; i < n; i++) {
            int x = nums[i];
            // 统计 x 能产生多少贡献
            ans += (i - idx[x - 1]) * (right[i] - i); // 子数组左端点个数 * 子数组右端点个数
            idx[x] = i;
        }
        // 上面计算的时候,每个子数组的最小值必然可以作为贡献,而这是不合法的
        // 所以每个子数组都多算了 1 个不合法的贡献
        return ans - n * (n + 1) / 2;
    }
} 

时间复杂度 O ( N ) O(N) O(N)

空间复杂度 O ( N ) O(N) O(N)

代码思路来源灵神大佬,值得学习

Tag

Array

Hash文章来源地址https://www.toymoban.com/news/detail-541248.html

到了这里,关于【算法】Sum of Imbalance Numbers of All Subarrays 所有子数组中不平衡数字之和-进阶篇的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包赞助服务器费用

相关文章

  • 【LeetCode 算法】Minimum Operations to Halve Array Sum 将数组和减半的最少操作次数-Greedy

    给你一个正整数数组 nums 。每一次操作中,你可以从 nums 中选择 任意 一个数并将它 减小 到 恰好 一半 。(注意,在后续操作中你可以对减半过的数继续执行操作) 请你返回将 nums 数组和 至少 减少一半 的 最少 操作数。 1 = n u m s . l e n g t h = 1 0 5 1 = n u m s [ i ] = 1 0 7 1 = num

    2024年02月15日
    浏览(10)
  • found input variables with inconsistene numbers of samples:[] 报错处理

    found input variables with inconsistene numbers of samples:[] 报错处理

    在用train_text_spilt进行机器学习的训练时候,出现了以下的报错:  代码检查发现错误 : train_x,train_y,test_x,test_y=train_test_split() train_x,train_y的行数不一致 应该改为: train_x,test_x,train_y,test_y=train_test_split()  

    2024年02月15日
    浏览(11)
  • 【算法萌新闯力扣】:找到所有数组中消失对数字

    【算法萌新闯力扣】:找到所有数组中消失对数字

      这两天刚交了蓝桥杯的报名费,刷题的积极性高涨。算上打卡题,今天刷了10道算法题了,题目都比较简单,挑选了一道还不错的题目与大家分享。   把数组先排序,然后利用桶排来统计数组中存在的元素,对于数量为0的元素则存入list集合中,最后返回list集合   如果这

    2024年02月04日
    浏览(10)
  • 算法:移除数组中的val的所有元素---双指针[2]

    算法:移除数组中的val的所有元素---双指针[2]

    文章来源: https://blog.csdn.net/weixin_45630258/article/details/132689237 欢迎各位大佬指点、三连 1、题目: 给你一个数组 nums和一个值 val,你需要 原地移除 所有数值等于 val 的元素,并返回移除后数组的新长度。 不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并 原地修改 输入

    2024年02月09日
    浏览(9)
  • 【算法】Add Two Numbers 两数相加

    给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。 请你将两个数相加,并以相同形式返回一个表示和的链表。 你可以假设除了数字 0 之外,这两个数都不会以 0 开头。 每个链表中的节点数在范围

    2024年02月11日
    浏览(38)
  • 【Edibat 算法 ★★★★★★】【吸血鬼数字】Vampire Numbers

    Vampire Numbers recursion permutation brute force A Vampire Number is a positive integer greater than 99, that rearranged in all of its possible digits permutations, with every permutation being split into two parts, is equal to the product of at least one of its permutations. If the number has an even quantity of digits, left and right parts will have the s

    2024年02月07日
    浏览(9)
  • LeetCode //C - 1161. Maximum Level Sum of a Binary Tree

    LeetCode //C - 1161. Maximum Level Sum of a Binary Tree

    Given the root of a binary tree, the level of its root is 1, the level of its children is 2, and so on. Return the smallest level x such that the sum of all the values of nodes at level x is maximal.   Example 1: Input: root = [1,7,0,7,-8,null,null] Output: 2 **Explanation: ** Level 1 sum = 1. Level 2 sum = 7 + 0 = 7. Level 3 sum = 7 + -8 = -1. So we return

    2024年01月23日
    浏览(8)
  • LeetCode //C - 2130. Maximum Twin Sum of a Linked List

    LeetCode //C - 2130. Maximum Twin Sum of a Linked List

    In a linked list of size n, where n is even, the i t h i^{th} i t h node (0-indexed) of the linked list is known as the twin of the ( n − 1 − i ) t h (n-1-i)^{th} ( n − 1 − i ) t h node, if 0 = i = (n / 2) - 1. For example, if n = 4, then node 0 is the twin of node 3, and node 1 is the twin of node 2. These are the only nodes with twins for n = 4. Th

    2024年01月17日
    浏览(44)
  • 小白水平理解面试经典题目LeetCode 404 Sum of Left Leaves【Tree】

    小白水平理解面试经典题目LeetCode 404 Sum of Left Leaves【Tree】

    给定二叉树的root,返回所有左叶的总和。 叶子是没有子节点的节点。左叶是另一个节点的左子节点的叶。 在大学某个自习的下午,小白坐在教室看到这道题。想想自己曾经和白月光做题,现在大过年的,也是只有自己练题了。左边一颗树,右边一棵树。。。 这时候黑长直女

    2024年02月22日
    浏览(13)
  • Leetcode 2897. Apply Operations on Array to Maximize Sum of Squares

    Leetcode 2897. Apply Operations on Array to Maximize Sum of Squares 1. 解题思路 2. 代码实现 题目链接:2897. Apply Operations on Array to Maximize Sum of Squares 这一题事实上非常的简单,我们只需要想明白一些关键点就行了。 题中最终的目标是获得 k k k 个数,使得其平方和最大。因此,我们就只需要

    2024年02月07日
    浏览(15)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包