2023-03-16力扣每日一题

链接:

https://leetcode.cn/problems/count-subarrays-with-median-k/

题意:

给一个数组,找出排序后中位数为k的非空子数组的数量,数组长度为n,内含1到n不重复整数

当子数组长度为偶数时,k要在偏左一侧

解:

将大于k的视为1,小于k的视为-1,前缀sz[i+1]可以表示从[0,i]这个子数组中,k于中位的偏移值(k不一定在其中)

对于任意一段所需子数组,首先要满足k被包含在其中

可知,当k为中位数且k在该段中时,该段中大于k的数字和小于k的数字数量相等,偏移值为0;

同理,当k为中位偏左且k在该段中时,偏移值需要为1,该段中大于k的数字比小于k的数字数量多一个。

所以当该段偏移值为0或1,且k在该段中时,一定是所需子数组

遍历数组,小于k的存进map,要初始化map[0]=1,因为我的sz[i]表示包含i在内的前缀数组偏移值,sz[0]就含有nums[0]的偏移值,要考虑起点在0号元素之前的情况(错了两发),等于k的偏移值也不用存,因为子数组起点必须在k之前(错了一发)。

大于等于k的每个偏移值sz[i+1]都为答案提供map[ sz[i+1] ]+map[ sz[i+1]-1 ]的值

[L,R]偏移值为sz[R+1]-sz[L],因为sz数组是对下标+1存储的,所以代码太丑陋了

实际代码:

#include
#include
using namespace std;
const int N=1E5+3;
int sz[N],mao;
int solve(vector& nums, int k)
{
    mappd;//配对组 
    int lg=nums.size(),ans=0;
    //前缀+绝对处理 
    for(int i=0;ik) sz[i+1]=sz[i]+1;
        //cout<>n;
    vector nums;
    for(int i=1;i<=n;i++)
    {
        int temp;cin>>temp;
        nums.push_back(temp);
    }
    cin>>k;
    
    int ans=solve(nums,k);
    cout<<"ans="<

限制:

  • n == nums.length
  • 1 <= n <= 105
  • 1 <= nums[i], k <= n
  • nums 中的整数互不相同

你可能感兴趣的:(力扣每日一题,leetcode,数据结构,c++,每日一题)