C.滑动窗口-求子数组个数-越短越合法——3134. 找出唯一性数组的中位数

题目链接:3134. 找出唯一性数组的中位数(困难)

算法原理:

解法:二分查找+滑动窗口

击败7.55%

时间复杂度O(Nlogn)

二分查找模板👇

优选算法-二分:18.在排序数组中查找元素的第一个和最后一个位置

①确定中位数位置:

nums 的唯一性数组的数量就是 nums 的非空连续子数组的个数

一共有m=1+2+⋯+n=2n(n+1)​ 个非空连续子数组

当 m=4 时,中位数是第 2 小元素,m=5 时,中位数是第 3 小元素

所以中位数是这 m 个数中的第k=(m+1)/2小

②二分查找调节mid找k(求最左端点模板)

以 "子数组的不同元素个数" 为二分对象(左边界 0、右边界 n),每次取中间值mid,判断 "不同元素数≤mid 的子数组数量" 是否≥k:

while(left<right)

1.分二段,发现左无= 右有 --->左无=就求左端点->check确定等号在右边,所以是求左端点

2.注意mid靠左:mid=left+(right-left)/2->确定mid咋写

3.if(mid在最左端点的左边)让左端点的左边往里靠,还要超过:left=mid+1->mid在最左端点的左边就是!check

4.else 另一边靠过来就行:right=mid

5.返回left或者right都行(因为最终会重合)

③用封装的check方法来判断是否覆盖第k小(ret>=k返回true)

维护窗口[left, right],保证窗口内不同元素数≤mid,累加合法子数组数(right-left+1),数量≥k 则提前返回 true

答疑

Q1:m既然是总的非空连续子数组的个数,那里面还有可能存在重复的元素呢

唯一性数组是:[1,1,1,1,2,2](长度 m=6,和子数组总数一致)------这里的元素可以重复,但数组长度固定为 m,中位数的位置只由长度 m 决定,和元素值是否重复无关

Java代码:

java 复制代码
class Solution {
    public int medianOfUniquenessArray(int[] nums) {
        int n=nums.length;
        long k=((long)n*(n+1)/2+1)/2;//中位数的位置,第k小的数
        //求左端点模板↓
        int left=0,right=n;
        while(left<right){
            int mid=left+(right-left)/2;//取靠左的位置
            //mid是不断调节的,目标位置在k
            //检查不同元素个数<=mid时的子数组数量是否>=k
            if(!check(nums,mid,k)) left=mid+1;//比k小,left往右调整
            else right=mid;//比k大,right往左调整
        }
        return right;
    }
    //检查是否覆盖第k小,ret>=k算覆盖到k
    private boolean check(int[] nums,int upper,long k){
        long ret=0;
        int n=nums.length,kinds=0;
        //<元素,个数>
        Map<Integer,Integer> hash=new HashMap<>();
        for(int left=0,right=0;right<n;right++){
            //进窗口
            int in=nums[right];
            if(hash.getOrDefault(in,0)==0) kinds++;
            hash.put(in,hash.getOrDefault(in,0)+1);
            //出窗口
            while(kinds>upper){
                int out=nums[left];
                hash.put(out,hash.get(out)-1);
                if(hash.get(out)==0){
                    hash.remove(out);
                    kinds--;
                }
                left++;
            }
            //更新
            ret+=right-left+1;
            //判断是否提前返回(无需遍历完所有子数组)
            if(ret>=k) return true;
        }
        return false;
    }
}
相关推荐
毕设源码-钟学长13 分钟前
【开题答辩全过程】以 基于Springboot的扶贫众筹平台为例,包含答辩的问题和答案
java·spring boot·后端
lsx20240616 分钟前
C++ 基本的输入输出
开发语言
CodeSheep程序羊28 分钟前
拼多多春节加班工资曝光,没几个敢给这个数的。
java·c语言·开发语言·c++·python·程序人生·职场和发展
独好紫罗兰28 分钟前
对python的再认识-基于数据结构进行-a002-列表-列表推导式
开发语言·数据结构·python
2401_8414956433 分钟前
【LeetCode刷题】二叉树的直径
数据结构·python·算法·leetcode·二叉树··递归
budingxiaomoli33 分钟前
优选算法-字符串
算法
I'mChloe36 分钟前
PTO-ISA 深度解析:PyPTO 范式生成的底层指令集与 NPU 算子执行的硬件映射
c语言·开发语言
编程小白20261 小时前
从 C++ 基础到效率翻倍:Qt 开发环境搭建与Windows 神级快捷键指南
开发语言·c++·windows·qt·学习
我是咸鱼不闲呀1 小时前
力扣Hot100系列19(Java)——[动态规划]总结(上)(爬楼梯,杨辉三角,打家劫舍,完全平方数,零钱兑换)
java·leetcode·动态规划
qq7422349841 小时前
APS系统与OR-Tools完全指南:智能排产与优化算法实战解析
人工智能·算法·工业·aps·排程