Leetcode周赛-244

第一题:https://leetcode-cn.com/problems/determine-whether-matrix-can-be-obtained-by-rotation/

1886. 判断矩阵经轮转后是否一致

思路:90度顺时针旋转后,(i,j)->(j,n-i-1),分别计算旋转得到的四种情况进行判断即可。
反思:判断两个二维矩阵相等可以之间用vector<vector> a,b; 直接判断 a==b;
代码:

    vector<vector<int>> sol(vector<vector<int>> ans){
        int n=ans.size();
        vector<vector<int>> atm(n,vector<int>(n));
        \\以上两行可以改为 auto atm=ans;
        for(int i=0;i<n;i++)
            for(int j=0;j<n;j++)
            atm[j][n-i-1]=ans[i][j];
            return atm;
    }
    bool findRotation(vector<vector<int>>& a, vector<vector<int>>& b) {
        for(int i=0;i<4;i++){
            if(a==b)return true;
            a=sol(a);
        }
        return false;
    }

第二题:https://leetcode-cn.com/problems/reduction-operations-to-make-the-array-elements-equal/

1887. 使数组元素相等的减少操作次数

思路:每个数字都要变到最小值,而这个过程中的cost是这个数字到最小数字的距离(两个数字间从小到大不同数值的个数)
反思:不要忘记先排序。
代码:

class Solution {
public:
    int reductionOperations(vector<int>& s) {
        int ans=0,num=0;
        sort(s.begin(),s.end());
        for(int i=1;i<s.size();i++){
            if(s[i]!=s[i-1])num++;
            ans+=num;
        }
        return ans;
    }
};

第三题:https://leetcode-cn.com/problems/minimum-number-of-flips-to-make-the-binary-string-alternating/

1888. 使二进制字符串字符交替的最少反转次数

思路:
方法一:首先根据规律:字符交替的情况只有两种情况:奇数为0或者奇数为1,计算出一种情况下需要第二种变换的次数,然后遍历字符串,计算每一位作为开头,把此位前的移动到最后的情况下需要变换的次数,然后输出最小值即可。由于每种情况都是从上一种情况中转换过来的,所以只需要计算状态转换的影响即可。
规律:字符串两种情况所需要的变换次数关系为:a次和n-a次
代码:

class Solution {
public:
    int minFlips(string s) {
        int a=0,b=0;
        for(int i=0;i<s.size();i++){
          if(i%2&&(s[i]-'0')){
              //cout<<i<<endl;
              a++;
          }
          if((i%2==0)&&(s[i]=='0')){
             //cout<<i<<endl;
              a++;
          }
        }
        int len=s.size();
        int ans=min(a,len-a);
        a=len-a;
        for(int i=0;i<s.size();i++){
            if(s[i]-'0'){
                a--;
            }
            a=len-1-a;
            //cout<<a<<endl;
            if(s[i]=='0'&&len%2==0)a++;
            if(s[i]=='1'&&len%2==1)a++;
            ans=min(ans,len-a);
            ans=min(ans,a);
            //cout<<i<<" "<<a<<endl;
        }
        return ans;
    }
};
``
方法二:
前缀+后缀:对于偶数情况,操作一并不能改变某一位的奇偶性,当奇数的情况下,操作一可以使前段的奇偶变换,所以可以前段和后端分别求前缀和后枚举操作一结束的点即可。
代码:
```C++
class Solution {
public:
    int minFlips(string s) {
        const int m=s.size();
        int l[2][m],r[2][m];
        for(int i=0;i<2;i++)
            for(int j=0,num=0,k=i;j<m;j++,k^=1)
            {
                if((s[j]-'0')==k)num++;
                l[i][j]=num;
            }
        for(int i=0;i<2;i++)
            for(int j=m-1,num=0,k=i;j>=0;j--,k^=1){
                if((s[j]-'0')==k)num++;
                r[i][j]=num;
            }
        int ans= min(r[0][0],r[1][0]);
        if(m%2==0)return ans;
        for(int i=0;i<m-1;i++){
            ans=min(ans,l[0][i]+r[1][i+1]);
            ans=min(ans,l[1][i]+r[0][i+1]);
        }
        return ans;
    }
};

第四题:https://leetcode-cn.com/problems/minimum-space-wasted-from-packaging/

1889. 装包裹的最小浪费空间

思路:排序后二分判断
包裹数据范围是1e5,箱子数目总和数据范围是1e5,所以题目时间复杂度应该在O(NlogN)即可,我们可以对每个箱子供应商的包裹进行判断,箱子数总和为M(<1e5),对于i供应商的j箱子,j箱子能够装的包裹范围为[l,r),产生的浪费空间贡献:\(a[i][j]\times(l-r)-\sum_{k=l}^{r-1}{p[k]}\),此时时间复杂度为NNM,对于\(\sum_{k=l}^{r-1}{p[k]}\)可以通过前缀和优化为O(1),对于查找[l,r),可以用upper_bound二分查找优化到O(logN)所以对箱子判断的时间复杂度为O(MlogN),二分包裹前需要对包裹先排序,同样箱子判断前也需要对箱子排序,总时间复杂度为O(NlogN+MlogM+MlogN)
反思:
1.浪费空间的数据范围应该小于1e10,两种情况比较浪费空间时很明显不应该拿取模后的数值进行比较,可以long long 存储,最后返回时取模即可;
2.无法把所有包裹放入箱子的时候返回-1,则最后的结果初始值应该大于1e10,可以用LLONG_MAX进行初始化,而不是用0x3f3f3f3f(int类型不穷大,小于1e10);
代码:

class Solution {
public:
    int minWastedSpace(vector<int>& p, vector<vector<int>>& b) {
        int n=p.size(), m=b.size();
        const int mod=(int)1e9+7;
        vector<long long>qz(n+5);
        sort(p.begin(),p.end());
        for(int i=1;i<=n;i++){
            qz[i]=qz[i-1]+p[i-1];
        }
        long long ans=LLONG_MAX;
        for(int i=0;i<m;i++){
            vector<int> & bt=b[i];
            sort(bt.begin(),bt.end());
            if(bt[bt.size()-1]<p[n-1])continue;
            int s=0,t;
            long long num=0;
            for(int j=0;j<bt.size();j++){
                t=upper_bound(p.begin(),p.end(),bt[j])-p.begin();
                //cout<<s<<" "<<t<<endl;
                num=(num+1LL*(t-s)*bt[j]-(qz[t]-qz[s]));
                s=t;
                if(t==n)break;
            }
            //cout<<num<<endl;
            ans=min(ans,num);
        }
        return ans== LLONG_MAX ? -1:ans%mod;
    }
};
上一篇:【Recorder.js+百度语音识别】全栈方案技术细节


下一篇:第244天学习打卡(知识点回顾 索引)