首页 > 其他分享 >所有子数组中不平衡数字之和

所有子数组中不平衡数字之和

时间:2023-07-08 22:34:44浏览次数:24  
标签:下标 数字 idx nums int vis 数组 平衡

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

  • 0 <= i < n - 1
  • sarr[i+1] - sarr[i] > 1

这里,sorted(arr) 表示将数组 arr 排序后得到的数组。
给你一个下标从 0 开始的整数数组 nums ,请你返回它所有子数组的不平衡数字之和。

1. 哈希

class Solution {
public:
    int sumImbalanceNumbers(vector<int> &nums) {
        int ans = 0, n = nums.size();
        bool vis[n + 2]; //注意这里数据大小小于长度,使用哈希代替排序,因为只需判断相邻
        for (int i = 0; i < n; i++) { //以i为左边界
            memset(vis, 0, sizeof(vis)); //重置
            vis[nums[i]] = true;
            int cnt = 0; //记录当前数组不平衡数
            for (int j = i + 1; j < n; j++) { //以j为右边界
                int x = nums[j];
                if (!vis[x]) { //更改当前不平衡数,重复数不记
                    cnt += 1 - vis[x - 1] - vis[x + 1];
                    vis[x] = true;
                }
                ans += cnt; //累加
            }
        }
        return ans;
    }
};

2. 贡献法

class Solution {
public:
    int sumImbalanceNumbers(vector<int> &nums) {
        int n = nums.size(), right[n], idx[n + 1];
        fill(idx, idx + n + 1, n); //初始右侧边界下标默认为n
        for (int i = n - 1; i >= 0; i--) {//从右往左遍历,记录右侧
            int x = nums[i];
            // right[i] 表示 nums[i] 右侧的 x 和 x-1 的最近下标(不存在时为 n)
            right[i] = min(idx[x], idx[x - 1]);
            idx[x] = i;
        }
        //x作为不平衡数字的贡献值的数组
        int ans = 0;
        memset(idx, -1, sizeof(idx)); //重置下标,左侧边界下标默认为-1
        for (int i = 0; i < n; i++) {//枚举以i为
            int x = nums[i];
            // 统计 x 能产生多少贡献
            ans += (i - idx[x - 1]) * (right[i] - i); // 子数组左端点个数 * 子数组右端点个数
            idx[x] = i;
        }
        // 上面计算的时候,每个子数组的最小值必然可以作为贡献,而这是不合法的
        // 所以每个子数组都多算了 1 个不合法的贡献
        return ans - n * (n + 1) / 2;
    }
};

标签:下标,数字,idx,nums,int,vis,数组,平衡
From: https://www.cnblogs.com/929code/p/17538011.html

相关文章

  • js 对文字排序和对数字排序
    1、对文字排序 <html><body><scripttype="text/javascript">vararr=newArray(6)arr[0]="George"arr[1]="John"arr[2]="Thomas"arr[3]="James"arr[4]="Adrew"arr......
  • js 如何使用 join() 方法将数组的所有元素组成一个字符串。
    <html><body><scripttype="text/javascript">vararr=newArray(3);arr[0]="George"arr[1]="John"arr[2]="Thomas"document.write(arr.join());document.write("<br/>&q......
  • 牛客练习赛113 D 小红的数组操作(hard version)
    题目要求求出最小的总代价使得平均数为整数,转换式子可得实际就是求出a,b使得(a*x-b*y+sum)%n==0且a*p+b*q要最小,平均值的为sum/n,因此对sum进行操作使其成为n的倍数即可(a*x-b*y+sum)%n==0=>((a*x+sum)%n-b*y%n)%n==0因为(a*x+sum)%n<n,b*y%n<n,因此要想二者差求余数为0一定为(......
  • 长度最小的子数组滑动窗口
    /***给定一个含有n个正整数的数组和一个正整数s,找出该数组中满足其和≥s的长度最小的连续子数组,并返回其长度。如果不存在符合条件的子数组,返回0。**长度最小的子数组*示例:**输入:s=7,nums=[2,3,1,2,4,3]输出:2解释:子数......
  • 树状数组进阶
    cnblogs。作为一个常数小且好写的数据结构,树状数组(BinaryIndexedTree,BIT)自然是求解数据结构问题的第一选择。除了众所周知的区间加区间求和,树状数组还能代替常数巨大的线段树做很多事情,例如树状数组二分和维护高维差分。1.树状数组的结构很多选手对树状数组的了解仅停留在......
  • 移除数组中的元素返回新数组的长度,双指针实现
    /***给你一个数组nums和一个值val,你需要原地移除所有数值等于val的元素,并返回移除后数组的新长度。**不要使用额外的数组空间,你必须仅使用O(1)额外空间并原地修改输入数组。**元素的顺序可以改变。你不需要考虑数组中超出新长度后面的......
  • 如何实现MySQL 字符串转换成数组的具体操作步骤
    MySQL字符串转换成数组在MySQL中,我们经常需要对字符串进行处理和转换。有时候,我们需要将一个字符串拆分成多个部分,然后进行进一步的处理。这时,将字符串转换成数组是一种常见的操作。方法一:使用SUBSTRING_INDEX函数MySQL提供了SUBSTRING_INDEX函数,可以用于将一个字符串按照指定......
  • 解决Java中的byte数组不够补空格的具体操作步骤
    Java中的byte数组不够补空格在Java编程中,我们经常需要处理二进制数据,其中byte数组是一种常见的数据类型。然而,在某些情况下,我们可能需要将byte数组的长度扩展到指定的长度,不足的部分用空格进行补齐。本文将介绍在Java中如何实现byte数组的补齐操作,并提供相关代码示例。为什么需要......
  • 167. 两数之和 II - 输入有序数组
    给你一个下标从1开始的整数数组 numbers,该数组已按非递减顺序排列 ,请你从数组中找出满足相加之和等于目标数 target的两个数。如果设这两个数分别是numbers[index1]和numbers[index2],则1<=index1<index2<=numbers.length。以长度为2的整数数组[index1,i......
  • 二分法查找目标元素在数组中的索引
    /***给定一个n个元素有序的(升序)整型数组nums和一个目标值target,写一个函数搜索nums中的target,*如果目标值存在返回下标,否则返回-1。*输入:nums=[-1,0,3,5,9,12],target=9*输出:4*解释:9出现在nums中并且下标为4......