LeetCode第392场周赛题解(c++)

本文介绍了如何找到给定整数数组中严格递增或递减的最长子数组长度,以及如何通过最少操作改变数组元素使其中位数等于特定值k。算法涉及滑动窗口和比较操作计数。
摘要由CSDN通过智能技术生成

100264.最长的严格递增或递减子数组

给你一个整数数组 nums 。

返回数组 nums 中 严格递增 或 严格递减 的最长非空子数组的长度。

示例 1:

输入:nums = [1,4,3,3,2]

输出:2

解释:

nums 中严格递增的子数组有[1][2][3][3][4] 以及 [1,4] 。

nums 中严格递减的子数组有[1][2][3][3][4][3,2] 以及 [4,3] 。

因此,返回 2 。

示例 2:

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

输出:1

解释:

nums 中严格递增的子数组有 [3][3][3] 以及 [3] 。

nums 中严格递减的子数组有 [3][3][3] 以及 [3] 。

因此,返回 1 。

示例 3:

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

输出:3

解释:

nums 中严格递增的子数组有 [3][2] 以及 [1] 。

nums 中严格递减的子数组有 [3][2][1][3,2][2,1] 以及 [3,2,1] 。

因此,返回 3 。

提示:

  • 1 <= nums.length <= 50
  • 1 <= nums[i] <= 50

这个题目其实刚开始我是打算滑动窗口的,本地测试也是可以,但是提交力扣后就是显示不对,于是我又重新思考写了代码。

思路就是:

  • 两个数组:

     vector<int> inc(n, 1);

     vector<int> dec(n, 1);

  • 对于该数组,如果nums[i+1]>nums[i],那么记录递增数组的inc[i+1]=inc[i]+1;

#include<iostream>
#include<vector>
#include<algorithm>
#include<cstring>
using namespace std;
// int longestMonotonicSubarray(vector<int>& nums) {
//       int n=nums.size();
//       int ans=1; //最短肯定是1
//        if (n <= 1) {
//             return n; // 只有一个元素或者空数组的情况
//         }
//       //滑动窗口
//       for(int i=0;i<n-1;i++){
//         int cnt=1;
//         int cnt1=1;
//         int k=i,j=i;
//         while(nums[k]<nums[k+1]&&k<n-1){
//             cnt++;
//             //  cout<<nums[k]<<" "<<nums[k+1]<<"\n";
//             if(k+1<n){
//                 k++;
//             }
//         }
//         while(nums[j]>nums[j+1]&&j<n-1){
//             cnt1++;
//            if(j+1<n) j++;
//         //    cout<<nums[j]<<" "<<nums[j+1]<<"\n";
             
//         }
//         ans=max(ans,cnt);
//         ans=max(ans,cnt1);
        
//       }
//     return ans;
// }
int longestMonotonicSubarray(vector<int>& nums) {
        int n = nums.size();
        if (n == 0) {
            return 0;
        }

        vector<int> inc(n, 1);
        vector<int> dec(n, 1);

        for (int i = 1; i < n; i++) {
            if (nums[i] > nums[i - 1]) {
                inc[i] = inc[i - 1] + 1;
            }
            if (nums[i] < nums[i - 1]) {
                dec[i] = dec[i - 1] + 1;
            }
        }

        int maxLength = 0;
        for (int i = 0; i < n; i++) {
            maxLength = max(maxLength, max(inc[i], dec[i]));
        }

        return maxLength ;
    }
int main(){
    vector<int> nums;
    nums={1,4,3,3,2};
    cout<<longestMonotonicSubarray(nums);
    return 0;
}

100242.满足距离约束且字典序最小的字符串

给你一个字符串 s 和一个整数 k 。

定义函数 distance(s1, s2) ,用于衡量两个长度为 n 的字符串 s1 和 s2 之间的距离,即:

  • 字符 'a' 到 'z' 按 循环 顺序排列,对于区间 [0, n - 1] 中的 i ,计算所有「 s1[i] 和 s2[i] 之间 最小距离」的 和 

例如,distance("ab", "cd") == 4 ,且 distance("a", "z") == 1 。

你可以对字符串 s 执行 任意次 操作。在每次操作中,可以将 s 中的一个字母 改变  任意 其他小写英文字母。

返回一个字符串,表示在执行一些操作后你可以得到的 字典序最小 的字符串 t ,且满足 distance(s, t) <= k 。

示例 1:

输入:s = "zbbz", k = 3
输出:"aaaz"
解释:在这个例子中,可以执行以下操作:
将 s[0] 改为 'a' ,s 变为 "abbz" 。
将 s[1] 改为 'a' ,s 变为 "aabz" 。
将 s[2] 改为 'a' ,s 变为 "aaaz" 。
"zbbz" 和 "aaaz" 之间的距离等于 k = 3 。
可以证明 "aaaz" 是在任意次操作后能够得到的字典序最小的字符串。
因此,答案是 "aaaz" 。

示例 2:

输入:s = "xaxcd", k = 4
输出:"aawcd"
解释:在这个例子中,可以执行以下操作:
将 s[0] 改为 'a' ,s 变为 "aaxcd" 。
将 s[2] 改为 'w' ,s 变为 "aawcd" 。
"xaxcd" 和 "aawcd" 之间的距离等于 k = 4 。
可以证明 "aawcd" 是在任意次操作后能够得到的字典序最小的字符串。
因此,答案是 "aawcd" 。

示例 3:

输入:s = "lol", k = 0
输出:"lol"
解释:在这个例子中,k = 0,更改任何字符都会使得距离大于 0 。
因此,答案是 "lol" 。

提示:

  • 1 <= s.length <= 100
  • 0 <= k <= 2000
  • s 只包含小写英文字母。

这个题还是比较简单的。就是遍历该字符串,s[0]这些越靠近'a'越好,最小就是'a',

特殊情况就是如果在字母表末端,且因为是循环,可以到'z',再到'a',这样字典序就一定会是小的

但是当这个字母到'a'和到'z'->'a'的距离一样时,肯定是直接到'a'而不是从'z'到'a',需要考虑这样的情况。

#include<iostream>
#include<vector>
#include<cstring>
using namespace std;
// string getSmallestString(string s, int k) {
//     int n=s.length();
//     if(k==0){
//         return s;
//     }
    
//         //遍历s
//         for(int i=0; i<n; i++){
//             if(s[i]=='a'){
//                 //由于已经是最小的,不需要再改变
//                 k=k;
//             }
//             else if(s[i]=='z'){
//                 s[i]='a';
//                 k--;
//             }
//             else if('z'-s[i]+1<=k){
//                 s[i]='a';
//                 k=k-('z'-s[i])-1;
//             }
//             else{
//                 while(s[i]-'a'>=0&&k>=0){
//                     s[i]=s[i]-1;
//                     k--;
//                     if(s[i]=='a') break;
//                 }
//             }
//             if(k==0) return s;
//         }
//         return s;
    
// }
string getSmallestString(string s, int k){
    int n=s.length();
    if(k==0){
        return s;
    }
    //遍历s
        for(int i=0; i<n; i++){
            if(s[i]=='a'){
                //由于已经是最小的,不需要再改变
                continue;
            }else{
                int a=s[i]-'a';  //到a的距离
                int z='z'-s[i]+1;  //该字母到z的距离+1 => 循环到a的距离
                if(a<=k&&a<=z){  //如果该字母到a,z的距离一样,那么应该是直接考虑为a,而不是先到z再到a
                    s[i]='a';
                    k-=a;
                }else if(z<=k){
                    s[i]='a';
                    k-=z;
                }else{
                    s[i]-=k;
                    k=0;
                }

            }
            if(k==0) return s;
        }
        return s;
}
int main(){
    // :s = "zbbz", k = 3
    string s="zzpwd";
    int k=46;
    cout<<getSmallestString(s,k)<<endl;
    double ss=1995/2387;
    cout<<ss;
    return 0;
}

这些就是早上周赛时我写的题了,确实是平时练的太少了,写的太慢而且考虑边界情况也很少,幸好力扣是给看不通过的例子的,但是在我csp时就没有这样好的事情,导致很难查出自己代码哪里不对。。。

3107.使数组中位数等于K的最小操作数

给你一个整数数组 nums 和一个 非负 整数 k 。一次操作中,你可以选择任一元素 加 1 或者减 1 。

请你返回将 nums 中位数 变为 k 所需要的 最少 操作次数。

一个数组的中位数指的是数组按非递减顺序排序后最中间的元素。如果数组长度为偶数,我们选择中间两个数的较大值为中位数。

示例 1:

输入:nums = [2,5,6,8,5], k = 4

输出:2

解释:我们将 nums[1] 和 nums[4] 减 1 得到 [2, 4, 6, 8, 4] 。现在数组的中位数等于 k 。

示例 2:

输入:nums = [2,5,6,8,5], k = 7

输出:3

解释:我们将 nums[1] 增加 1 两次,并且将 nums[2] 增加 1 一次,得到 [2, 7, 7, 8, 5] 。

示例 3:

输入:nums = [1,2,3,4,5,6], k = 4

输出:0

解释:数组中位数已经等于 k 了。

提示:

  • 1 <= nums.length <= 2 * 105
  • 1 <= nums[i] <= 109
  • 1 <= k <= 109

没啥好说的,挺简单的感觉,就是写的太慢了

#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
long long minOperationsToMakeMedianK(vector<int>& nums, int k) {
    sort(nums.begin(), nums.end());
    // 255681 7
    int n=nums.size();
    int mid=0,m=0;
    long long ans=0;
    if(n%2!=0) {
        mid=nums[(n-1)/2];
        m=(n-1)/2;
    }
    else{
        //已经排序了,所以一定是nums[n/2]
        // if(nums[n/2]==nums[n/2-1]){
        //     if(nums[n/2]>k){
        //         mid=nums[n/2];
        //         m=n/2;
        //     }
        //     else{
        //         mid=nums[n/2];
        //         m=n/2;
        //     }
        // }
        mid=nums[n/2];
        m=n/2;
        
    }
    if(mid==k){
        return 0;
    }
    else if(mid<k){
        for(int i=m;i<n;i++){
            if(nums[i]<k){
                ans+=k-nums[i];
            }
            else{
                break;
            }
        }
    }
    else{
        //mid>k
        for(int i=m;i>=0;i--){
            if(nums[i]>k){
                ans+=nums[i]-k;
                // cout<<" "<<nums[i]<<endl;
            }
            else{
                break;
            }
        }
        
    }
    return ans;

}
int main(){
    vector<int> nums={1,2,3,4,5,6};
    //1 2 3 4 5 6
    // 
    int k=4;
    cout<<minOperationsToMakeMedianK(nums,k)<<endl;
    return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值