首页 > 其他分享 >数组问题技巧学习指南

数组问题技巧学习指南

时间:2023-10-17 20:23:50浏览次数:31  
标签:学习指南 arr 技巧 int 元素 数组 长度 乘积

前置芝士

求解两个有序数组的第 K 小乘积

先统计分负数乘积个数neg、正数乘积个数pos以及乘积为0的个数 zero,

然后分三种情况讨论:

k≤negk,我们可以二分负数答案,统计不超过二分值的乘积个数;
neg<k≤neg+zero,此时返回0;
k>neg+zero,我们可以二分正数答案,统计不超过二分值的乘积个数。

字段和问题

不限制长度——在一个数列里找两个不相交区间使得他们权值和最大

找 m个长度为 k 的不相交区间使得他们的权值和最大 (1≤n≤5000)

f[i][j]=max(f[i−k][j−1]+sum[i]−sum[i−k],f[i−1][j])

区间数目变多且不限制长度——找 m 个不相交长度不限的区间使得他们权值和最大(1≤n≤5000)

选2个不重叠的长度为k的区间

使子数组和最大

因为区间大小是固定为k的,所以显然需要前缀和处理一下处理之后我们去维护前缀中长度为k的最大值ma,枚举第二个长度为k的起点,那么答案就是max(ma+当前长度为k的序列和)复杂度为O(n).

int T,n,k;
ll a[2000100];
void solve(){
    cin>>T;
    while(T--){
        cin>>n>>k;
        for(int i=1;i<=n;i++) {cin>>a[i];a[i]+=a[i-1];}
        ll ma=-1e18,ans=-1e18;
        for(int i=k;i+k<=n;i++){
            ma=max(ma,a[i]-a[i-k]);
            ans=max(ans,ma+a[i+k]-a[i]);
        }
        cout<<ans<<endl;
    }

使子数组元素和相等(循环数组)

给你一个下标从 0 开始的整数数组 arr 和一个整数 k ,数组 arr 是一个循环数组,数组中的最后一个元素的下一个元素是数组中的第一个元素,数组中第一个元素的前一个元素是数组中的最后一个元素。

选中 arr 中任意一个元素,并使其值加上 1 或减去 1。

执行运算使每个长度为 k 的 子数组 的元素总和都相等,返回所需要的最少运算次数。

  • 1 <= k <= arr.length <= 105
  • 1 <= arr[i] <= 10^9

【解题思路分析】

1)解决 a不是循环数组的情况

考虑从 i 和 i+1开始的两个长为 k的子数组的和,如果要求这两个和相等,则有

\(a[i]+a[i+1]+⋯+a[i+k−1]=a[i+1]+a[i+2]+⋯+a[i+k]\)

及\(a[i]=a[k+i]=a[2k+i]....\)

2)分组处理

按照 i mod k的结果将 a 分组,对每一组(记作 b)

我们需要解决:

让数组 b的所有元素相等的最少运算次数。

根据中位数贪心,将 b的所有元素变为 b 的中位数是最优的。

3)翡翠定理

比如 n=6,k=4,那么 a[2]循环后是 a[8],和 a[0]在同一组,而 a[1]无论怎么循环都无法和 a[0] 在同一组。((1+6n) mod 4≠0

一个循环数组如果既有周期 n,又有周期 k,则必然有周期 gcd⁡(n,k)。证明:根据 裴蜀定理,有:

a[i]=a[i+nx+ky]=a[i+gcd⁡(n,k)]
这样就转换成了不是循环数组的情况。

【java】

public long makeSubKSumEqual(int[] arr, int k) {
        int n=arr.length;
       k=gcd(n,k);
       System.out.println(k);
        long res=0;
        for(int i=0;i<k;i++){
            ArrayList<Integer> list=new ArrayList<>();
            for(int j=i;j<n;j+=k){
                     list.add(arr[j]);
            }
            Collections.sort(list);
            int mid=list.get((list.size())/2);
            for(int x:list){
                res+=Math.abs(x-mid);
            }                         
        }
        return res;
    }
    int gcd(int a,int b){
        while(b!=0){
            int tmp=b;
           b=a%b;
            a=tmp;
        }
        return a;
    }

标签:学习指南,arr,技巧,int,元素,数组,长度,乘积
From: https://www.cnblogs.com/taotao123456/p/17770571.html

相关文章

  • Day2 数组训练
    Day2数组的一些基本练习前一阵子生病了,把这几天落下来的内容慢慢补第一题有序数组的平方Lc977给你一个按非递减顺序排序的整数数组nums,返回每个数字的平方组成的新数组,要求也按非递减顺序排序。//使用双指针的思想完成此题,一开始我想的是直接暴力解,这有什么难的......
  • c++数组的二进制文件读写
    #include<fstream>//forifstream、ofstreamtemplate<typenameOB>inlinevoidsaveObject(constchar*filename,OB&object,intlength)//传入要保存的对象引用{std::ofstreamosm(filename,std::ios::out|std::ios::binary);osm.write((constcha......
  • Java程序优化访问数据库的技巧集锦
    大多数应用程序都需要访问数据库。据统计,在一个应用中,通过JDBC访问数据库的代码会占到30%左右。访问数据库的效率是决定程序的运行性能的关键因素之一。提高程序访问数据库的效率的总的原则是:减少建立数据库连接的次数,减少向数据库提交的SQL语句的数目,及时释放无用的Connection、St......
  • Spring Boot中的过滤器、拦截器、监听器技巧汇总:让你快速成为大神
    ......
  • 小技巧 | 渐变消失遮罩的多种实现方式
    我的小册 《CSS技术揭秘与实战通关》上线了,想了解更多有趣、进阶、系统化的CSS内容,可以猛击- LINK。在知乎看到一题比较有意思的题目。题目大致是如何实现下述图片的效果,如果使用div前置遮挡的话,会影响div后面的按钮,使其无法被点击。本文将简单介绍几种这个效果的......
  • Vue性能优化--在Vue中,千万别用属性数组作为循环的对象
    在Vue中,千万别用属性数组作为循环的对象methods:{test(){...上面省略业务逻辑1万字 //16位像素数组letdcmbuffer=newUint16Array(dcmInfo._dictionary.dict["7FE00010"].Value[0]asArrayBuffer);this.currentImageInfo={......
  • VSCode 小技巧 配置代码模版 vscode snippets
    第一步mac输入shift+command+p(windows输入ctrl+shift+p),输入snippets,点击如下图选项。第二步,选中新建全局代码片段文件。第三步,输入一个全局配置文件名,例如snippet.config第四步,进行配置{//Placeyour全局snippetshere.Eachsnippetisdefinedu......
  • 代码随想训练营第五天(Python)| 242.有效的字母异位词、349. 两个数组的交集、第202题.
    242.有效的字母异位词1、数组法这个思路贼6,在这个题的效率也高classSolution:defisAnagram(self,s:str,t:str)->bool:#全部转为asii码如果是互为异为词,则最后的-+后的结果为0record=[0]*26#范围是26。一维foriins......
  • 代码随想录第六天 | 哈希表、242.有效的字母异位词 、349. 两个数组的交集 、202. 快
    哈希表什么是哈希表哈希表是根据关键码的值而直接进行访问的数据结构。简单的例子:数组什么时候想到用哈希法当我们遇到了要快速判断一个元素是否出现集合里的时候,就要考虑哈希法。哈希碰撞元素通过哈希函数被映射到同一个索引下标位置解决方法:拉链法从发生冲......
  • modelsim仿真使用小技巧
    1.在sim界面可以看到仿真的模块如果想将这些模块添加到仿真界面(wave),可以选中模块再ctrl+w即可,在wave仿真界面,全选波形(ctrl+a),再ctrl+g即可将波形自动分组,再双击各个组名即可重新命名......