刷题13 数组


989. 数组形式的整数加法

整数的 数组形式  num 是按照从左到右的顺序表示其数字的数组。例如,对于 num = 1321 ,数组形式是 [1,3,2,1] 。

给定 num ,整数的 数组形式 ,和整数 k ,返回 整数 num + k 的 数组形式 。

输入:num = [1,2,0,0], k = 34        输出:[1,2,3,4]
解释:1200 + 34 = 1234
int* addToArrayForm(int* num, int numSize, int k, int* returnSize) {
    int* res=malloc(sizeof(int)*100000);
    *returnSize=0;
    //从后向前进行加
    for(int i=numSize-1;i>=0||k>0;--i){
        if(i>=0){
            k+=num[i];
        }
        res[(*returnSize)++]=k%10;
        k/=10;
    }
    //翻转
    for(int i=0;i<(*returnSize)/2;++i){
        int tmp=res[i];
        res[i]=res[(*returnSize)-i-1];
        res[(*returnSize)-i-1]=tmp;
    }
    return res;
}


941. 有效的山脉数组

 给定一个整数数组 arr,如果它是有效的山脉数组就返回 true,否则返回 false。让我们回顾一下,如果 arr 满足下述条件,那么它是一个山脉数组:arr.length >=3

  • 在 0 < i < arr.length - 1 条件下,存在 i 使得:
    • arr[0] < arr[1] < ... arr[i-1] < arr[i]
    • arr[i] > arr[i+1] > ... > arr[arr.length - 1]

        线性扫描,进行模拟。 

bool validMountainArray(int* arr, int arrSize){
    int i=0;
    while(i+1<arrSize&&arr[i]<arr[i+1]){
        i++;
    }
    if(i==0||i==arrSize-1){
        return false;
    }
    while(i+1<arrSize&&arr[i]>arr[i+1]){
        i++;
    }
    return i==arrSize-1;
}


1207. 独一无二的出现次数

 给你一个整数数组 arr,请你帮忙统计数组中每个数的出现次数。如果每个数的出现次数都是独一无二的,就返回 true;否则返回 false

输入:arr = [1,2,2,1,1,3]
输出:true
解释:在该数组中,1 出现了 3 次,2 出现了 2 次,3 只出现了 1 次。没有两个数的出现次数相同。
int cmp(int* a,int* b){
    return *a-*b;
}
bool uniqueOccurrences(int* arr, int arrSize) {
    int flag[2002]={0};
    for(int i=0;i<arrSize;++i){
        if(arr[i]<0){
            //-1就放到下标为1001的位置
            flag[arr[i]+1002]++;
        }else{
            flag[arr[i]]++;
        }
    }
    qsort(flag,2002,sizeof(int),cmp);
    for(int i=0;i<2001;++i){
        if(flag[i]!=0){
            if(flag[i]==flag[i+1]){
                return false;
            }
        }
    }
    return true;
}


1437. 是否所有 1 都至少相隔 k 个元素

 给你一个由若干 0 和 1 组成的数组 nums 以及整数 k。如果所有 1 都至少相隔 k 个元素,则返回 True ;否则,返回 False 。

输入:nums = [1,0,0,0,1,0,0,1], k = 2
输出:true
解释:每个 1 都至少相隔 2 个元素。

        记录 上一个1出现的下标,除了第一个1之外,每次遇到一个1就判断与前一个1的距离。

bool kLengthApart(int* nums, int numsSize, int k) {
    int pre=-1;
    for(int i=0;i<numsSize;++i){
        if(nums[i]==1){
            if(pre!=-1&&i-pre-1<k){
                return false;
            }
            pre=i;
        }
    }
    return true;
}


2553. 分割数组中数字的数位

 给你一个正整数数组 nums ,请你返回一个数组 answer ,你需要将 nums 中每个整数进行数位分割后,按照 nums 中出现的 相同顺序 放入答案数组中。对一个整数进行数位分割,指的是将整数各个数位按原本出现的顺序排列成数组。

比方说,整数 10921 ,分割它的各个数位得到 [1,0,9,2,1] 。

输入:nums = [13,25,83,77]
输出:[1,3,2,5,8,3,7,7]
void reverse(int* res,int l,int r){
    while(l<r){
        int tmp=res[l];
        res[l]=res[r];
        res[r]=tmp;
        l++;r--;
    }
    return;
}
int* separateDigits(int* nums, int numsSize, int* returnSize) {
    int* res=malloc(sizeof(int)*100000);
    int l=0;
    for(int i=0;i<numsSize;++i){
        if(nums[i]<10){
            res[l++]=nums[i];
        }else{
            int start=l;
            int num=nums[i];
            while(num){
                int cur=num%10;
                res[l++]=cur;
                num/=10;
            }
            reverse(res,start,l-1);
        }
    }
    *returnSize=l;
    return res;
}


2855. 使数组成为递增数组的最少右移次数

 给你一个长度为 n 下标从 0 开始的数组 nums ,数组中的元素为 互不相同 的正整数。请你返回让 nums 成为递增数组的 最少右移 次数,如果无法得到递增数组,返回 -1 。

一次 右移 指的是同时对所有下标进行操作,将下标为 i 的元素移动到下标 (i + 1) % n 处。

输入:nums = [3,4,5,1,2]        输出:2
解释:第一次右移后,nums = [2,3,4,5,1] 。第二次右移后,nums = [1,2,3,4,5] 。现在 nums 是递增数组了,所以答案为 2 。

        将数组分成两段,每一段都单调递增,并且前一段严格大于后一段。 

int minimumRightShifts(int* nums, int numsSize){
    int i=1;
    while(i<numsSize&&nums[i-1]<nums[i]){
        //找到第一个开始下降的点
        i++;
    }
    if(i==numsSize) return 0; //数列递增
    if(nums[0]<nums[numsSize-1]) return -1;//最后一个元素值大于第一个元素值
    int mid=i;
    i++;
    //判断mid之后的元素是否递增
    while(i<numsSize&&nums[i-1]<nums[i]) i++;
    if(i<numsSize) return -1;
    return numsSize-mid;
}


2869. 收集元素的最少操作次数

 给你一个正整数数组 nums 和一个整数 k 。一次操作中,你可以将数组的最后一个元素删除,将该元素添加到一个集合中。请你返回收集元素 1, 2, ..., k 需要的 最少操作次数 。

输入:nums = [3,1,5,4,2], k = 2        输出:4
解释:4 次操作后,集合中的元素依次添加了 2 ,4 ,5 和 1 。此时集合中包含元素 1 和 2 ,所以答案为 4 。
int minOperations(int* nums, int numsSize, int k){
    int* ans=malloc(sizeof(int)*(k+1));
    for(int i=0;i<=k;++i) ans[i]=0;
    for(int i=0;i<numsSize;++i){
        //记录每个数字的下标位置
        if(nums[i]<=k){
            ans[nums[i]]=i;
        }
    }
    int mmin=INT_MAX;
    //找到符合要求的最小下标位置
    for(int i=1;i<=k;++i){
        if(ans[i]<mmin){
            mmin=ans[i];
        }
    }
    return numsSize-mmin;
}


2970. 统计移除递增子数组的数目 I

 给你一个下标从 0 开始的  整数数组 nums 。

如果 nums 的一个子数组满足:移除这个子数组后剩余元素 严格递增 ,那么我们称这个子数组为 移除递增 子数组。比方说,[5, 3, 4, 6, 7] 中的 [3, 4] 是一个移除递增子数组,因为移除该子数组后,[5, 3, 4, 6, 7] 变为 [5, 6, 7] ,是严格递增的。

请你返回 nums 中 移除递增 子数组的总数目。注意 ,剩余元素为空的数组也视为是递增的。子数组 指的是一个数组中一段连续的元素序列。

输入:nums = [1,2,3,4]
输出:10
解释:10 个移除递增子数组分别为:[1], [2], [3], [4], [1,2], [2,3], [3,4], [1,2,3], [2,3,4] 和 [1,2,3,4]。移除任意一个子数组后,剩余元素都是递增的。注意,空数组不是移除递增子数组。
int incremovableSubarrayCount(int* nums, int numsSize) {
    int i=0;
    int n=numsSize;
    while(i<n-1&&nums[i]<nums[i+1]){
        i++;
    }
    if(i==n-1){
        //每个非空子数组都可以移除
        return n*(n+1)/2;
    }
    int ans=i+2;
    for(int j=n-1;j==n-1||nums[j]<nums[j+1];j--){
        while(i>=0&&nums[i]>=nums[j]){
            i--;
        }
        ans+=i+2;
    }
    return ans;
}


453. 最小操作次数使数组元素相等

给你一个长度为 n 的整数数组,每次操作将会使 n - 1 个元素增加 1 。返回让数组所有元素相等的最小操作次数。

输入:nums = [1,2,3]
输出:3
解释:只需要3次操作(注意每次操作会增加两个元素的值):
[1,2,3]  =>  [2,3,3]  =>  [3,4,3]  =>  [4,4,4]
int minMoves(int* nums, int numsSize){
    int mmin=INT_MAX;
    for(int i=0;i<numsSize;++i){
        if(nums[i]<mmin){
            mmin=nums[i];
        }
    }
    int ans=0;
    for(int i=0;i<numsSize;++i){
        ans+=nums[i]-mmin;
    }
    return ans;
}


462. 最小操作次数使数组元素相等 II

 给你一个长度为 n 的整数数组 nums ,返回使所有数组元素相等需要的最小操作数。

在一次操作中,你可以使数组中的一个元素加 1 或者减 1 。

输入:nums = [1,2,3]
输出:2
解释:只需要两次操作(每次操作指南使一个元素加 1 或减 1):
[1,2,3]  =>  [2,2,3]  =>  [2,2,2]
int cmp(int* a,int* b){
    return *a-*b;
}
int minMoves2(int* nums, int numsSize) {
    qsort(nums,numsSize,sizeof(int),cmp);
    int ans=0;
    int x=nums[numsSize/2];
    for(int i=0;i<numsSize;++i){
        ans+=abs(nums[i]-x);
    }
    return ans;
}
int* nextGreaterElements(int* nums, int numsSize, int* returnSize) {
    int *res=malloc(sizeof(int)*numsSize);
    *returnSize=numsSize;
    memset(res,-1,sizeof(int)*numsSize);
    for(int i=0;i<numsSize;++i){
        for(int j=i+1;j<i+1+numsSize;++j){
            if(nums[j%numsSize]>nums[i]){
                res[i]=nums[j%numsSize];
                break;
            }
        }
    }
    return res;
}


532. 数组中的 k-diff 数对

 给你一个整数数组 nums 和一个整数 k,请你在数组中找出 不同的 k-diff 数对,并返回不同的 k-diff 数对 的数目。

k-diff 数对定义为一个整数对 (nums[i], nums[j]) ,并满足下述全部条件:

  • 0 <= i, j < nums.length
  • i != j
  • |nums[i] - nums[j]| == k
输入:nums = [3, 1, 4, 1, 5], k = 2
输出:2
解释:数组中有两个 2-diff 数对, (1, 3) 和 (3, 5)。尽管数组中有两个 1 ,但我们只应返回不同的数对的数量。
int cmp(int* a,int* b){
    return *a-*b;
}
int findPairs(int* nums, int numsSize, int k) {
    int ans=0;
    qsort(nums,numsSize,sizeof(int),cmp);
    for(int i=0;i<numsSize-1;++i){
        //去重
        if(i!=0&&nums[i]==nums[i-1]) continue;
        int l=i+1,r=numsSize-1;
        //二分查找
        while(l<r){
            int mid=(r-l)/2+l;
            if(nums[mid]>=nums[i]+k){
                r=mid;
            }else{
                l=mid+1;
            }
        }
        if(nums[l]==nums[i]+k) ans++;
    }
    return ans;
}


560. 和为 K 的子数组

 给你一个整数数组 nums 和一个整数 k ,请你统计并返回 该数组中和为 k 的子数组的个数 

子数组是数组中元素的连续非空序列。

输入:nums = [1,1,1], k = 2
输出:2

         暴力法: 简单枚举

int subarraySum(int* nums, int numsSize, int k) {
    int count=0;
    int ans=0;
    for(int i=0;i<numsSize;++i){
        count=nums[i];
        if(count==k){
            ans++;
        }
        for(int j=i+1;j<numsSize;++j){
            count+=nums[j];
            if(count==k){
                ans++;
            }
        }
    }
    return ans;
}

          前缀和,两重循环枚举子数组之和:超时 

int subarraySum(int* nums, int numsSize, int k) {
    int ans=0;
    int* presum=malloc(sizeof(int)*numsSize);
    presum[0]=nums[0];
    for(int i=1;i<numsSize;++i){
        presum[i]=presum[i-1]+nums[i];
    }
    for(int i=0;i<numsSize;++i){
        for(int j=i;j<numsSize;++j){
            if(presum[j]-presum[i]+nums[i]==k){
                ans++;
            }
        }
    }
    return ans;
}

 
611. 有效三角形的个数

 给定一个包含非负整数的数组 nums ,返回其中可以组成三角形三条边的三元组个数。

输入: nums = [2,2,3,4]
输出: 3
解释:有效的组合是: 
2,3,4 (使用第一个 2)
2,3,4 (使用第二个 2)
2,2,3

        三重循环:超时 

int cmp(int* a,int* b){
    return *a-*b;
}
int triangleNumber(int* nums, int numsSize) {
    qsort(nums,numsSize,sizeof(int),cmp);
    int ans=0;
    for(int i=0;i<numsSize;++i){
        for(int j=i+1;j<numsSize;++j){
            for(int k=j+1;k<numsSize;++k){
                if(nums[k]<nums[i]+nums[j]){
                    ans++;
                }else{
                    break;
                }
            }
        }
    }
    return ans;
}

 
673. 最长递增子序列的个数

 给定一个未排序的整数数组 nums , 返回最长递增子序列的个数 。注意 这个数列必须是 严格 递增的。

输入: [1,3,5,4,7]
输出: 2
解释: 有两个最长递增子序列,分别是 [1, 3, 4, 7] 和[1, 3, 5, 7]。
int findNumberOfLIS(int* nums, int numsSize) {
    int dp[numsSize];//表示以i结尾的最长递增子序列的长度
    int cnt[numsSize];//表示以i结尾的最长递增子序列的个数
    int mmax=0,ans=0;
    for(int i=0;i<numsSize;++i){
        dp[i]=1;
        cnt[i]=1;
        for(int j=0;j<i;++j){
            if(nums[j]<nums[i]){
                if(dp[j]+1>dp[i]){
                    dp[i]=dp[j]+1;//最长的长度发生变化
                    cnt[i]=cnt[j];//重置计数
                }else if(dp[j]+1==dp[i]){
                    cnt[i]+=cnt[j];//最长子序列个数增加
                }
            }
        }
        if(dp[i]>mmax){
            //最大长度改变,更新mmax与ans
            mmax=dp[i];
            ans=cnt[i];
        }else if(dp[i]==mmax){
            //如果最大长度没变
            ans+=cnt[i];
        }
    }
    return ans;
}

179. 最大数

给定一组非负整数 nums,重新排列每个数的顺序(每个数不可拆分)使之组成一个最大的整数。

注意:输出结果可能非常大,所以你需要返回一个字符串而不是整数。

输入:nums = [10,2]

输出:"210"
int cmp(int* x,int* y){
    char s1[101];
    char s2[101];
    sprintf(s1,"%d%d",*x,*y);
    sprintf(s2,"%d%d",*y,*x);
    return strcmp(s2,s1);
}
char* largestNumber(int* nums, int numsSize) {
    qsort(nums,numsSize,sizeof(int),cmp);
    if(nums[0]==0){
        return "0";
    }
    char *res=malloc(sizeof(char)*10000);
    memset(res, '\0', 10000);//初始化为结束符
    for(int i=0;i<numsSize;++i){
        char tmp[101];
        sprintf(tmp,"%d",nums[i]);
        strcat(res,tmp);
    }
    return res;
}

229. 多数元素 II

 给定一个大小为 的整数数组,找出其中所有出现超过 ⌊ n/3 ⌋ 次的元素。

输入:nums = [3,2,3]
输出:[3]

        排序后用双指针查找 

int cmp(int* a,int* b){
    return *a-*b;
}
int* majorityElement(int* nums, int numsSize, int* returnSize) {
    qsort(nums,numsSize,sizeof(int),cmp);
    int* res=(int*)malloc(sizeof(int)*numsSize);
    int sum=0;
    int idx=0;
    int l=0,r=0;
    while(l<numsSize){
        sum = 1;
        for(r=l+1; r<numsSize; r++) {
            if(nums[l] == nums[r]) {
                sum++;
            } else {
                break;
            }
        }
        if(sum>(numsSize/3)) {
            res[idx++] = nums[l];
        }
        l=r;
    }
    *returnSize=idx;
    return res;
}

357. 统计各位数字都不同的数字个数

 给你一个整数 n ,统计并返回各位数字都不同的数字 x 的个数,其中 0 <= x < 10n 。

输入:n = 2
输出:91
解释:答案应为除去 11、22、33、44、55、66、77、88、99 外,在 0 ≤ x < 100 范围内的所有数字。 输入:n = 0
输出:1
int countNumbersWithUniqueDigits(int n) {
    if(n==0) return 1;
    if(n==1) return 10;
    int ans=10,cur=9;
    //第一位有9种可能,第二位有9种可能,第三位有8种可能,第四位有7种可能
    for(int i=0;i<n-1;++i){
        cur*=9-i;
        ans+=cur;
    }
    return ans;
}

 368. 最大整除子集

 给你一个由 无重复 正整数组成的集合 nums ,请你找出并返回其中最大的整除子集 answer ,子集中每一元素对 (answer[i], answer[j]) 都应当满足:

  • answer[i] % answer[j] == 0 ,或
  • answer[j] % answer[i] == 0

如果存在多个有效解子集,返回其中任何一个均可。

输入:nums = [1,2,3]
输出:[1,2]
解释:[1,3] 也会被视为正确答案。
int cmp(int* a,int* b){
    return *a-*b;
}
int* largestDivisibleSubset(int* nums, int numsSize, int* returnSize) {
    qsort(nums,numsSize,sizeof(int),cmp);
    int n=numsSize;
    int dp[n];
    memset(dp,1,sizeof(int)*n);
    int mmax=dp[0],mmaxl=1;
    //找出最大子集的个数、以及子集中的最大整数
    for(int i=1;i<n;++i){
        for(int j=0;j<i;++j){
            if(nums[i]%nums[j]==0){
                dp[i]=fmax(dp[i],dp[j]+1);
            }
        }
        if(dp[i]>mmaxl){
            mmaxl=dp[i];
            mmax=nums[i];
        }
    }
    //倒推得最大子集
    int *res=malloc(sizeof(int)*n);
    int pos=0;
    if(mmaxl==1){
        res[pos++]=nums[0];
        *returnSize=1;
        return res;
    }
    for(int i=n-1;i>=0&&mmaxl>0;--i){
        if(dp[i]==mmaxl&&mmax%nums[i]==0){
            res[pos++]=nums[i];
            mmax=nums[i];
            mmaxl--;
        }
    }
    *returnSize=pos;
    return res;
}

372. 超级次方

 你的任务是计算 ab 对 1337 取模,a 是一个正整数,b 是一个非常大的正整数且会以数组形式给出。

输入:a = 2, b = [3]
输出:8
输入:a = 2, b = [1,0]
输出:1024
int mypow(int a,int b){
    a=a%1337;
    int ans=1;
    for(int i=0;i<b;++i){
        ans*=a;
        ans%=1337;
    }
    return ans;
}
int superPow(int a, int* b, int bSize) {
    if(a==1) return 1;
    int sum=1;
    for(int i=0;i<bSize;++i){
        sum=mypow(sum,10);
        sum*=mypow(a,b[i]);
        sum=sum%1337;
    }
    return sum;
}

395. 至少有 K 个重复字符的最长子串

给你一个字符串 s 和一个整数 k ,请你找出 s 中的最长子串, 要求该子串中的每一字符出现次数都不少于 k 。返回这一子串的长度。

如果不存在这样的子字符串,则返回 0。

输入:s = "aaabb", k = 3
输出:3
解释:最长子串为 "aaa" ,其中 'a' 重复了 3 次。

        滑动窗口 

int longestSubstring(char* s, int k) {
    int ans=0;
    int n=strlen(s);
    for(int t=1;t<=26;++t){
        int l=0,r=0;
        int cnt[26]={0};
        int type=0;//当前区间内字符种类数量
        int less=0;//当前出现次数小于k的字符的数量
        while(r<n){
            cnt[s[r]-'a']++;
            if(cnt[s[r]-'a']==1){
                type++;
                less++;
            }
            if(cnt[s[r]-'a']==k){
                less--;
            }
            while(type>t){
                cnt[s[l]-'a']--;
                if (cnt[s[l]-'a']==k-1) {
                    less++;
                }
                if (cnt[s[l]-'a']==0) {
                    type--;
                    less--;
                }
                l++;
            }
            if(less==0){
                ans=fmax(ans,r-l+1);
            }
            r++;
        }
    }
    return ans;
}

754. 到达终点数字

 在一根无限长的数轴上,你站在0的位置。终点在target的位置。

你可以做一些数量的移动 numMoves :

  • 每次你可以选择向左或向右移动。
  • 第 i 次移动(从  i == 1 开始,到 i == numMoves ),在选择的方向上走 i 步。

给定整数 target ,返回 到达目标所需的 最小 移动次数(即最小 numMoves ) 

输入: target = 2                输入: target = 3
输出: 3                        ​​​​​​​ 输出: 2
解释:0+1-2+3=2         ​​​​​​​         解释:0+1+2=3
int reachNumber(int target) {
    int sum=0;
    int idx=0;
    target=abs(target);
    while(sum<target){
        idx++;
        sum+=idx;
    }
    if(sum==target){
        return idx;
    }
    //当sum-target为偶数时,可以将一个数值的符号改为符号使得等式成立
    //当sum-target为奇数,那么就需要继续相加来凑出偶数
    while((sum-target)%2!=0){
        idx++;
        sum+=idx;
    }
    return idx;
}

762. 二进制表示中质数个计算置位

 给你两个整数 left 和 right ,在闭区间 [left, right] 范围内,统计并返回 计算置位位数为质数 的整数个数。计算置位位数 就是二进制表示中 1 的个数。

例如, 21 的二进制表示 10101 有 3 个计算置位。

输入:left = 6, right = 10
输出:4
解释:
6 -> 110 (2 个计算置位,2 是质数)
7 -> 111 (3 个计算置位,3 是质数)
9 -> 1001 (2 个计算置位,2 是质数)
10-> 1010 (2 个计算置位,2 是质数)
共计 4 个计算置位为质数的数字。
//判断质数
bool fun(int x){
    if(x<2){
        return false;
    }
    for(int i=2;i*i<=x;++i){
        if(x%i==0){
            return false;
        }
    }
    return true;
}
//统计二进制1的个数
int count(int x){
    int ans=0;
    while(x){
        if(x%2==1){
            ans++;
        }
        x/=2;
    }
    return ans;
}
int countPrimeSetBits(int left, int right) {
    int ans=0;
    for(int i=left;i<=right;++i){
        if(fun(count(i))){
            ans++;
        }
    }
    return ans;
}

845. 数组中的最长山脉

 把符合下列属性的数组 arr 称为 山脉数组 :

  • arr.length >= 3
  • 存在下标 i0 < i < arr.length - 1),满足
    • arr[0] < arr[1] < ... < arr[i - 1] < arr[i]
    • arr[i] > arr[i + 1] > ... > arr[arr.length - 1]

给出一个整数数组 arr,返回最长山脉子数组的长度。如果不存在山脉子数组,返回 0 。

输入:arr = [2,1,4,7,3,2,5]
输出:5

        暴力枚举

int longestMountain(int* arr, int arrSize) {
    if(arrSize<3) return 0;
    int i=0,j=1,k=2;
    int ans=0;
    while(k<arrSize){
        int i1=i,j1=j,k1=k;
        if(arr[i1]<arr[j1]&&arr[j1]<arr[k1]){
            while(i1>0&&arr[i1-1]<arr[i1]){
                i1--;
            }
            while(k1<arrSize-1&&arr[k1]>arr[k1+1]){
                k1++;
            }
            ans=fmax(ans,k1-i1+1);
        }
        i++;j++;k++;
    }
    return ans;
}

 424. 替换后的最长重复字符

给你一个字符串 s 和一个整数 k 。你可以选择字符串中的任一字符,并将其更改为任何其他大写英文字符。该操作最多可执行 k 次。

在执行上述操作后,返回 包含相同字母的最长子字符串的长度。

输入:s = "ABAB", k = 2
输出:4
解释:用两个'A'替换为两个'B',反之亦然。
int characterReplacement(char * s, int k){
    int flag[26]={0};
    int n=strlen(s);
    int mmax=0;
    int l=0,r=0;
    while(r<n){
        flag[s[r]-'A']++;
        mmax=fmax(mmax,flag[s[r]-'A']);//记录最大字符的数量
        //当前长度大于最大字符长度+k
        if(r-l+1>mmax+k){
            flag[s[l]-'A']--;
            l++;
        }
        r++;
    }
    return r-l;
}

520. 检测大写字母

 我们定义,在以下情况时,单词的大写用法是正确的:

  • 全部字母都是大写,比如 "USA" 。
  • 单词中所有字母都不是大写,比如 "leetcode" 。
  • 如果单词不只含有一个字母,只有首字母大写, 比如 "Google" 。

给你一个字符串 word 。如果大写用法正确,返回 true ;否则,返回 false 。

输入:word = "USA"        ​​​​​​​        ​​​​​​​输入:word = "FlaG"
输出:true        ​​​​​​​        ​​​​​​​        输出:false

        只有三种情况:

        1、全是大写字母

        2、 没有大写字母

        3、只有一个大写字母,并且只存在在第一个位置

bool detectCapitalUse(char* word) {
    int len=strlen(word);
    int res=0;
    int idx=-1;
    if(len==1) return true;
    for(int i=0;i<len;++i){
        if(word[i]>='A'&&word[i]<='Z'){
            res++;//记录大写字母的个数
            idx=i;//记录最后一个大写字母的下标
        }
    }
    return res==len||res==0||(res==1&&idx==0);
}

438. 找到字符串中所有字母异位词

给定两个字符串 s 和 p,找到 s 中所有 p 的 异位词 的子串,返回这些子串的起始索引。不考虑答案输出的顺序。

异位词 指由相同字母重排列形成的字符串(包括相同的字符串)

输入: s = "cbaebabacd", p = "abc"
输出: [0,6]
解释:
起始索引等于 0 的子串是 "cba", 它是 "abc" 的异位词。
起始索引等于 6 的子串是 "bac", 它是 "abc" 的异位词。
bool check(int *cnt1,int *cnt2){
    for(int i=0;i<26;++i){
        if(cnt1[i]!=cnt2[i]){
            return false;
        }
    }
    return true;
}
int* findAnagrams(char * s, char * p, int* returnSize){
    int cnt1[26]={0},cnt2[26]={0};
    int n=strlen(s),m=strlen(p);
    for(int i=0;i<m;++i){
        cnt2[p[i]-'a']++;
    }
    int pos=0;
    int* ans=malloc(sizeof(int)*n);
    for(int l=0,r=0;r<n;++r){
        cnt1[s[r]-'a']++;
        //窗口长度超过m
        if(r-l+1>m){
            cnt1[s[l]-'a']--;
            l++;
        }
        //如果窗口内的字母与p一样,就将下标记录
        if(check(cnt1,cnt2)){
            ans[pos++]=l;
        }
        *returnSize=pos;
    }
    return ans;
}

1838. 最高频元素的频数

元素的 频数 是该元素在一个数组中出现的次数。

给你一个整数数组 nums 和一个整数 k 。在一步操作中,你可以选择 nums 的一个下标,并将该下标对应元素的值增加 1 。

执行最多 k 次操作后,返回数组中最高频元素的 最大可能频数 

输入:nums = [1,2,4], k = 5
输出:3
解释:对第一个元素执行 3 次递增操作,对第二个元素执 2 次递增操作,此时 nums = [4,4,4] 。
4 是数组中最高频元素,频数是 3 。

        滑动窗口

int cmp(int* a,int* b){
    return *a-*b;
}
int maxFrequency(int* nums, int numsSize, int k) {
    qsort(nums,numsSize,sizeof(int),cmp);
    long long total=0;
    int l=0,ans=1;
    for(int r=1;r<numsSize;++r){
        //r之前的数都是一样的
        total+=(long long)(nums[r]-nums[r-1])*(r-l);
        while(total>k){
            total-=nums[r]-nums[l];//减去添加l所需要增加的步数
            l++;
        }
        ans=fmax(ans,r-l+1);
    }
    return ans;
}

下一个更大系列: 

31. 下一个排列 

整数数组的一个 排列  就是将其所有成员以序列或线性顺序排列。

  • 例如,arr = [1,2,3] ,以下这些都可以视作 arr 的排列:[1,2,3][1,3,2][3,1,2][2,3,1] 。

整数数组的 下一个排列 是指其整数的下一个字典序更大的排列。更正式地,如果数组的所有排列根据其字典顺序从小到大排列在一个容器中,那么数组的 下一个排列 就是在这个有序容器中排在它后面的那个排列。如果不存在下一个更大的排列,那么这个数组必须重排为字典序最小的排列(即,其元素按升序排列)。

  • 例如,arr = [1,2,3] 的下一个排列是 [1,3,2] 。
  • 类似地,arr = [2,3,1] 的下一个排列是 [3,1,2] 。
  • 而 arr = [3,2,1] 的下一个排列是 [1,2,3] ,因为 [3,2,1] 不存在一个字典序更大的排列。
输入:nums = [1,2,3]
输出:[1,3,2]
void swap(int *a,int *b){
    int tmp=*a;
    *a=*b;
    *b=tmp;
}
void reverse(int* nums,int i,int j){
    int l=i,r=j;
    while(l<r){
        swap(&nums[l],&nums[r]);
        l++;r--;
    }
}
void nextPermutation(int* nums, int numsSize) {
    int i=numsSize-2;
    //找第一个(小,大)的排序
    while(i>=0&&nums[i]>=nums[i+1]){
        i--;
    }
    //已经是从大到小排列了
    if(i==-1){
        reverse(nums,0,numsSize-1);
        return;
    }
    int j=numsSize-1;
    //从后往前,找第一个比nums[i]大的数字
    while(j>=0&&nums[j]<=nums[i]){
        j--;
    }
    //交换
    swap(&nums[i],&nums[j]);
    //将i以后的数字进行逆置
    reverse(nums,i+1,numsSize-1);
}

 

496. 下一个更大元素 I 

nums1 中数字 x 的 下一个更大元素 是指 x 在 nums2 中对应位置 右侧 的 第一个 比 x 大的元素。

给你两个 没有重复元素 的数组 nums1 和 nums2 ,下标从 0 开始计数,其中nums1 是 nums2 的子集。

对于每个 0 <= i < nums1.length ,找出满足 nums1[i] == nums2[j] 的下标 j ,并且在 nums2 确定 nums2[j] 的 下一个更大元素 。如果不存在下一个更大元素,那么本次查询的答案是 -1 。

返回一个长度为 nums1.length 的数组 ans 作为答案,满足 ans[i] 是如上所述的 下一个更大元素 。

输入:nums1 = [4,1,2], nums2 = [1,3,4,2].
输出:[-1,3,-1]
解释:nums1 中每个值的下一个更大元素如下所述:
- 4 ,用加粗斜体标识,nums2 = [1,3,4,2]。不存在下一个更大元素,所以答案是 -1 。
- 1 ,用加粗斜体标识,nums2 = [1,3,4,2]。下一个更大元素是 3 。
- 2 ,用加粗斜体标识,nums2 = [1,3,4,2]。不存在下一个更大元素,所以答案是 -1 。
int* nextGreaterElement(int* nums1, int nums1Size, int* nums2, int nums2Size, int* returnSize) {
    int* ans=malloc(sizeof(int)*nums1Size);
    for(int i=0;i<nums1Size;++i){
        int j=0;
        while(j<nums2Size&&nums1[i]!=nums2[j]){
            j++;
        }
        int k=j+1;
        while(k<nums2Size&&nums1[i]>nums2[k]){
            k++;
        }
        ans[i]=k<nums2Size?nums2[k]:-1;
    }
    *returnSize=nums1Size;
    return ans;
}

503. 下一个更大元素 II 

给定一个循环数组 nums ( nums[nums.length - 1] 的下一个元素是 nums[0] ),返回 nums 中每个元素的 下一个更大元素 。

数字 x 的 下一个更大的元素 是按数组遍历顺序,这个数字之后的第一个比它更大的数,这意味着你应该循环地搜索它的下一个更大的数。如果不存在,则输出 -1 。

输入: nums = [1,2,1]
输出: [2,-1,2]
解释: 第一个 1 的下一个更大的数是 2;
数字 2 找不到下一个更大的数; 
第二个 1 的下一个最大的数需要循环搜索,结果也是 2。
int* nextGreaterElements(int* nums, int numsSize, int* returnSize) {
    int* ans=malloc(sizeof(int)*numsSize);
    memset(ans,-1,sizeof(int)*numsSize);
    *returnSize=numsSize;
    for(int i=0;i<numsSize;++i){
        for(int j=i+1;j<i+1+numsSize;++j){
            if(nums[i]<nums[j%numsSize]){
                ans[i]=nums[j%numsSize];
                break;
            }
        }
    }
    return ans;
}

556. 下一个更大元素 III 

 给你一个正整数 n ,请你找出符合条件的最小整数,其由重新排列 n 中存在的每位数字组成,并且其值大于 n 。如果不存在这样的正整数,则返回 -1 。

注意 ,返回的整数应当是一个 32 位整数 ,如果存在满足题意的答案,但不是 32 位整数 ,同样返回 -1 。

输入:n = 12
输出:21

        第一步:先找到第一个非递减的排列,如51432中,要找到1,4

        第二步:再找到第一个大于1的数字2,并与其交换,52431

        第三步:逆转后面的位数,得到52134

void swap(char* a,char* b){
    char tmp=*a;
    *a=*b;
    *b=tmp;
}
int nextGreaterElement(int n) {
    char nums[32];
    sprintf(nums,"%d",n);
    int i=strlen(nums)-2;
    //找第一个非递减的i
    while(i>=0&&nums[i]>=nums[i+1]){
        i--;
    }
    //从大到小的排列
    if(i<0) return -1;
    int j=strlen(nums)-1;
    //找到第一个大于nums[i]的j
    while(j>=0&&nums[i]>=nums[j]){
        j--;
    }
    //交换
    swap(&nums[i],&nums[j]);
    //将i后面的数字反转
    int l=i+1,r=strlen(nums)-1;
    while(l<r){
        swap(&nums[l],&nums[r]);
        l++;r--;
    }
    long long ans=atol(nums);
    if(ans>INT_MAX||ans<INT_MIN) return -1;
    return ans;
}

 面试题 05.04. 下一个数

 下一个数。给定一个正整数,找出与其二进制表达式中1的个数相同且大小最接近的那两个数(一个略大,一个略小)。

 输入:num = 2(或者0b10)
 输出:[4, 1] 或者([0b100, 0b1])

        暴力解:距离最近的两个数,加减之后判断即可,但是会溢出 

int count(long long n){
    int ans=0;
    while(n){
        if(n%2==1){
            ans++;
        }
        n/=2;
    }
    return ans;
}
int* findClosedNumbers(int num, int* returnSize){
    int *ans=malloc(sizeof(int)*2);
    *returnSize=2;
    long long n=num;
    ans[0]=-1;ans[1]=-1;
    while(n){
        n++;
        if(count(n)==count(num)){
            ans[0]=n;
            break;
        }
    } 
    n=num;
    while(n){
        n--;
        if(count(n)==count(num)){
            ans[1]=n;
            break;
        }
    }
    return ans;
}

2048. 下一个更大的数值平衡数 

 如果整数  x 满足:对于每个数位 d ,这个数位 恰好 在 x 中出现 d 次。那么整数 x 就是一个 数值平衡数 。

给你一个整数 n ,请你返回 严格大于 n 的 最小数值平衡数 

输入:n = 1000
输出:1333
解释:
1333 是一个数值平衡数,因为:
- 数字 1 出现 1 次。
- 数字 3 出现 3 次。 
bool check(int n){
    int count[10]={0};
    while(n){
        count[n%10]++;
        n/=10;
    }
    for(int i=0;i<10;++i){
        if(count[i]>0&&count[i]!=i){
            return false;
        }
    }
    return true;
}
int nextBeautifulNumber(int n){
    for(int i=n+1;i<INT_MAX;++i){
        if(check(i)){
            return i;
        }
    }
    return -1;
}

1432. 改变一个整数能得到的最大差值 

给你一个整数 num 。你可以对它进行如下步骤恰好 两次 :

  • 选择一个数字 x (0 <= x <= 9).
  • 选择另一个数字 y (0 <= y <= 9) 。数字 y 可以等于 x 。
  • 将 num 中所有出现 x 的数位都用 y 替换。
  • 得到的新的整数 不能 有前导 0 ,得到的新整数也 不能 是 0 。

请你返回 a 和 b 的 最大差值 。

输入:num = 555
输出:888
解释:第一次选择 x = 5 且 y = 9 ,并把得到的新数字保存在 a 中。
第二次选择 x = 5 且 y = 1 ,并把得到的新数字保存在 b 中。
现在,我们有 a = 999 和 b = 111 ,最大差值为 888

        枚举x与y,模拟,记录最大值与最小值,然后返回差值

int maxDiff(int num) {
    int mmin=num;
    int mmax=num;
    //枚举xy
    for(int x=0;x<10;++x){
        for(int y=0;y<10;++y){
            //用y替换x
            char s[100];
            sprintf(s,"%d",num);
            for(int i=0;i<strlen(s);++i){
                if(s[i]-'0'==x){
                    s[i]='0'+y;
                }
            }
            //判断是否有前导0
            if(s[0]!='0'){
                int res=atoi(s);
                mmin=fmin(mmin,res);
                mmax=fmax(mmax,res);
            }
        }
    }
    return mmax-mmin;
}

1493. 删掉一个元素以后全为 1 的最长子数组 

 给你一个二进制数组 nums ,你需要从中删掉一个元素。

请你在删掉元素的结果数组中,返回最长的且只包含 1 的非空子数组的长度。

如果不存在这样的子数组,请返回 0 。

输入:nums = [1,1,0,1]
输出:3
解释:删掉位置 2 的数后,[1,1,1] 包含 3 个 1 。
int longestSubarray(int* nums, int numsSize) {
    int ans=0;
    int zero=0;
    int l=0;
    for(int r=0;r<numsSize;++r){
        if(nums[r]==0){
            zero++;
        }
        while(zero>1){
            if(nums[l]==0) zero--;
            l++;
        }
        ans=fmax(ans,r-l);//要减去一个位置,因为必须删除一个元素
    }
    return ans;
}

2962. 统计最大元素出现至少 K 次的子数组 

给你一个整数数组 nums 和一个 正整数 k 。

请你统计有多少满足 「 nums 中的 最大 元素」至少出现 k 次的子数组,并返回满足这一条件的子数组的数目。

子数组是数组中的一个连续元素序列。

输入:nums = [1,3,2,3,3], k = 2
输出:6
long long countSubarrays(int* nums, int numsSize, int k) {
    long long ans=0;
    int mmax=0;
    //找出最大值
    for(int i=0;i<numsSize;++i){
        if(nums[i]>mmax){
            mmax=nums[i];
        }
    }
    int cnt=0,l=0;
    for(int r=0;r<numsSize;++r){
        if(nums[r]==mmax){
            cnt++;
        }
        //当满足条件,让l后移计数
        while(cnt==k){
            if(nums[l]==mmax){
                cnt--;
            }
            l++;
        }
        ans+=l;
    }
    return ans;
}

3011. 判断一个数组是否可以变为有序 

 给你一个下标从 0 开始且全是  整数的数组 nums 。

一次 操作 中,如果两个 相邻 元素在二进制下数位为 1 的数目 相同 ,那么你可以将这两个元素交换。你可以执行这个操作 任意次 (也可以 0 次)。

如果你可以使数组变有序,请你返回 true ,否则返回 false 。

输入:nums = [8,4,2,30,15]
输出:true
解释:我们先观察每个元素的二进制表示。 2 ,4 和 8 分别都只有一个数位为 1 ,分别为 "10" ,"100" 和 "1000" 。15 和 30 分别有 4 个数位为 1 :"1111" 和 "11110" 。

        正难则反:找到一对不满足条件(i,j)找一个数比另一个数小,但位数不同,返回false,若找不到就返回true。 

int count(int n){
    int ans=0;
    while(n){
        if(n%2==1){
            ans++;
        }
        n/=2;
    }
    return ans;
}
bool canSortArray(int* nums, int numsSize) {
    //正难则反:找一个数比另一个数小,但位数不同
    for(int i=0;i<numsSize;++i){
        for(int j=i+1;j<numsSize;++j){
            if(nums[i]>nums[j]&&count(nums[i])!=count(nums[j])){
                return false;
            }
        }
    }
    return true;
}

        直接法:分组循环

int count(int n){
    int ans=0;
    while(n){
        ans+=n%2;
        n/=2;
    }
    return ans;
}
bool canSortArray(int* nums, int numsSize) {
    //对于每一段,如果这一段的每个数,都大于等于上一段的最大值
    //那么就能把数组排成递增的,否则不行
    int i=0,pre_max=0;
    while(i<numsSize){
        int mmax=nums[i];
        int one=count(mmax);
        //二进制下数位为1的数目相同且临近的为一组,每次记录最大值
        while(i<numsSize&&count(nums[i])==one){
            if(nums[i]<pre_max){
                return false;
            }
            mmax=fmax(mmax,nums[i]);
            i++;
        }
        pre_max=mmax;
    }
    return true;
}

1144. 递减元素使数组呈锯齿状 

 给你一个整数数组 nums,每次 操作 会从中选择一个元素并 将该元素的值减少 1

如果符合下列情况之一,则数组 A 就是 锯齿数组

  • 每个偶数索引对应的元素都大于相邻的元素,即 A[0] > A[1] < A[2] > A[3] < A[4] > ...
  • 或者,每个奇数索引对应的元素都大于相邻的元素,即 A[0] < A[1] > A[2] < A[3] > A[4] < ...

返回将数组 nums 转换为锯齿数组所需的最小操作次数。

输入:nums = [1,2,3]
输出:2
解释:我们可以把 2 递减到 0,或把 3 递减到 1。

         分奇偶下标进行计算,返回两者中的较小值

int movesToMakeZigzag(int* nums, int numsSize) {
    int res1=0,res2=0;
    //偶数下标
    for(int i=0;i<numsSize;i+=2){
        int a=0;
        if(i-1>=0){
            a=fmax(a,nums[i]-nums[i-1]+1);
        }
        if(i+1<numsSize){
            a=fmax(a,nums[i]-nums[i+1]+1);
        }
        res1+=a;
    }
    //奇数下标
    for(int i=1;i<numsSize;i+=2){
        int a=0;
        if(i-1>=0){
            a=fmax(a,nums[i]-nums[i-1]+1);
        }
        if(i+1<numsSize){
            a=fmax(a,nums[i]-nums[i+1]+1);
        }
        res2+=a;
    }
    return fmin(res1,res2);
}

2294. 划分数组使最大差为 K 

 给你一个整数数组 nums 和一个整数 k 。你可以将 nums 划分成一个或多个 子序列 ,使 nums 中的每个元素都 恰好 出现在一个子序列中。

在满足每个子序列中最大值和最小值之间的差值最多为 k 的前提下,返回需要划分的 最少 子序列数目。

子序列 本质是一个序列,可以通过删除另一个序列中的某些元素(或者不删除)但不改变剩下元素的顺序得到。

输入:nums = [3,6,1,2,5], k = 2
输出:2
解释:
可以将 nums 划分为两个子序列 [3,1,2] 和 [6,5] 。
第一个子序列中最大值和最小值的差值是 3 - 1 = 2 。
第二个子序列中最大值和最小值的差值是 6 - 5 = 1 。
由于创建了两个子序列,返回 2 。可以证明需要划分的最少子序列数目就是 2 。

        由于此题求的是分组的个数,虽然要求的是子序列,但是依旧可以先排序然后进行统计 

int cmp(int* a,int* b){
    return *a-*b;
}
int partitionArray(int* nums, int numsSize, int k) {
    qsort(nums,numsSize,sizeof(int),cmp);
    int ans=0;
    int l=0,r=0;
    while(r<numsSize){
        while(r<numsSize&&(nums[r]-nums[l]<=k)) r++;//注意每次r会多移一位
        ans++;
        l=r;
    }
    return ans;
}

 2348. 全 0 子数组的数目

 给你一个整数数组 nums ,返回全部为 0 的 子数组 数目。

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

输入:nums = [1,3,0,0,2,0,0,4]
输出:6
解释:
子数组 [0] 出现了 4 次。
子数组 [0,0] 出现了 2 次。
不存在长度大于 2 的全 0 子数组,所以我们返回 6 。

        要统计全为0的子数组,就是要统计连续0的个数,累加到答案中。

long long zeroFilledSubarray(int* nums, int numsSize) {
    int l=0,r=0;
    long long ans=0;
    long long zero=0;
    while(r<numsSize){
        if(nums[r]==0){
            zero++;
            ans+=zero;
        }else{
            zero=0;
        }
        r++;  
    }
    return ans;
}

2384. 最大回文数字 

 给你一个仅由数字(0 - 9)组成的字符串 num 。请你找出能够使用 num 中数字形成的 最大回文 整数,并以字符串形式返回。该整数不含 前导零 。

输入:num = "444947137"
输出:"7449447"
解释:
从 "444947137" 中选用数字 "4449477",可以形成回文整数 "7449447" 。
可以证明 "7449447" 是能够形成的最大回文整数。
char* largestPalindromic(char* num) {
    int n=strlen(num);
    int flag[10]={0};
    //统计数字个数
    for(int i=0;i<n;++i){
        flag[num[i]-'0']++;
    }
    int j=0;
    //大于2的数字进行统计
    for(int i=9;i>0;--i){
        while(flag[i]>1){
            num[j]=i+'0';
            j++;
            flag[i]-=2;
        }
    }
    //对0单独处理
    if(flag[0]>1&&j>0){
        while(flag[0]>=2){
            num[j]='0';
            j++;
            flag[0]-=2;
        }
    }
    //对奇数个进行处理
    int x=0;
    for(int i=9;i>=0;--i){
        if(flag[i]!=0){
            num[j++]=i+'0';
            x=1;
            break;
        }
    }
    int i=j;
    //对后半段进行处理
    for(i=j;i<n;++i){
        if(j-1>=0&&x==0){
            //偶数个
            num[i]=num[j-1];
        }else if(j-2>=0&&x==1){
            //奇数个
            num[i]=num[j-2];
        }else{
            break;
        }
        j--;
    }
    num[i]='\0';
    return num;
}

2396. 严格回文的数字 

如果一个整数 n 在 b 进制下(b 为 2 到 n - 2 之间的所有整数)对应的字符串 全部 都是 回文的 ,那么我们称这个数 n 是 严格回文 的。

给你一个整数 n ,如果 n 是 严格回文 的,请返回 true ,否则返回 false 。

如果一个字符串从前往后读和从后往前读完全相同,那么这个字符串是 回文的 。

输入:n = 9
输出:false
解释:在 2 进制下:9 = 1001 ,是回文的。
在 3 进制下:9 = 100 ,不是回文的。
所以,9 不是严格回文数字,我们返回 false 。
注意在 4, 5, 6 和 7 进制下,n = 9 都不是回文的。
bool check(int n,int x){
    int ans[100]={0};
    int cnt=0;
    while(n){
        ans[cnt++]=n%x;
        n/=x;
    }
    for(int i=0;i<cnt;++i){
        if(ans[i]!=ans[cnt-i-1]){
            return false;
        }
    }
    return true;
}
bool isStrictlyPalindromic(int n) {
    for(int i=2;i<=n-2;++i){
        if(check(n,i)==false){
            return false;
        }
    }
    return true;
}

2443. 反转之后的数字和 

 给你一个 非负 整数 num 。如果存在某个 非负 整数 k 满足 k + reverse(k) = num  ,则返回 true ;否则,返回 false 。

reverse(k) 表示 k 反转每个数位后得到的数字。

输入:num = 443
输出:true
解释:172 + 271 = 443 ,所以返回 true 。
int reverse(int n){
    int ans=0;
    while(n){
        ans=ans*10+n%10;
        n/=10;
    }
    return ans;
}
bool sumOfNumberAndReverse(int num) {
    if(num==0) return true;
    for(int i=0;i<num;++i){
        if(i+reverse(i)==num){
            return true;
        }
    }
    return false;
}

2442. 反转之后不同整数的数目 

 给你一个由  整数组成的数组 nums 。你必须取出数组中的每个整数,反转其中每个数位,并将反转后得到的数字添加到数组的末尾。这一操作只针对 nums 中原有的整数执行。返回结果数组中 不同 整数的数目。

输入:nums = [1,13,10,12,31]
输出:6
解释:反转每个数字后,结果数组是 [1,13,10,12,31,1,31,1,21,13] 。
反转后得到的数字添加到数组的末尾并按斜体加粗表示。注意对于整数 10 ,反转之后会变成 01 ,即 1 
数组中不同整数的数目为 6(数字 1、10、12、13、21 和 31)。
int cmp(int* a,int* b){
    return *a-*b;
}
int reverse(int n){
    int ans=0;
    while(n){
        ans=ans*10+n%10;
        n/=10;
    }
    return ans;
}
int countDistinctIntegers(int* nums, int numsSize) {
    int* ans=malloc(sizeof(int)*(2*numsSize));
    int pos=0;
    for(int i=0;i<numsSize;++i){
        ans[pos++]=nums[i];
        ans[pos++]=reverse(nums[i]);
    }
    qsort(ans,2*numsSize,sizeof(int),cmp);
    int cnt=1;
    for(int i=1;i<2*numsSize;++i){
        if(ans[i-1]!=ans[i]){
            cnt++;
        }
    }
    return cnt;
}

1509. 三次操作后最大值与最小值的最小差 

 给你一个数组 nums 。

每次操作你可以选择 nums 中的任意一个元素并将它改成 任意值 。

在 执行最多三次移动后 ,返回 nums 中最大值与最小值的最小差值。

输入:nums = [1,5,0,10,14]
输出:1
解释:我们最多可以走 3 步。
第一步,将 5 改为 0 。 nums变成 [1,0,0,10,14] 。
第二步,将 10 改为 0 。 nums变成 [1,0,0,0,14] 。
第三步,将 14 改为 1 。 nums变成 [1,0,0,0,1] 。
执行 3 步后,最小值和最大值之间的差值为 1 - 0 = 1 。
可以看出,没有办法可以在 3 步内使差值变为0。
int cmp(int* a,int* b){
    return *a-*b;
}
int minDifference(int* nums, int numsSize) {
    if(numsSize<=3) return 0;
    qsort(nums,numsSize,sizeof(int),cmp);
    int ans=INT_MAX;
    //删去最小的k个数,还需要删去3−k个最大值
    for(int i=0;i<4;++i){
        ans=fmin(ans,nums[numsSize-4+i]-nums[i]);
    }
    return ans;
}

 

  • 18
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值