leetcode 周赛第196场

leetcode周赛第196场(字节研发岗)

leetcode周赛第196场链接
第一题
在这里插入图片描述
题目非常简单,我有两种想法,一种是排序后比较每三项的差,另一种是比较数组的和,第二种方法比第一种会减少一个排序的过程,时间复杂度为O(n).

方法一:

class Solution{
public:
    bool canMakeArithmeticProgression(vector<int>& arr) {
        if(arr.size()<=2) return true;
        sort(arr.begin(),arr.end());
        for(int i=1;i<arr.size()-1;i++){
            if(arr[i]-arr[i-1]!=arr[i+1]-arr[i]) return false;
        }
        return true;
    }
};

方法二:使用方法二的时候注意字符类型的转换,使用int的话会出现消除小数部分导致结果出错

class Solution {
public:
    bool canMakeArithmeticProgression(vector<int>& arr) {
        int min_arr=INT_MAX;
        int max_arr=INT_MIN;
        int n=arr.size();
        if(n<=2) return true;
        double sum=0;
        for(int i=0;i<n;i++){
            min_arr=min(min_arr,arr[i]);
            max_arr=max(max_arr,arr[i]);
            sum+=arr[i];
        }
        return sum==(double)(min_arr+max_arr)*n/2.0;
    }
};

第二题是一个有意思的脑经急转弯,应该来说是一个小学的智力题吧
在这里插入图片描述
在这里插入图片描述在这里插入图片描述
这个题当初拿到手上的第一感觉就是一道小学题,和当初的小明小红在马路两端相对而行,有一条狗在他们两边来回跑,直到小明与小红相遇为止。这个题其实就是小学题的变形,想出来就很简单,直接上代码。

class Solution {
public:
    int getLastMoment(int k, vector<int>& left, vector<int>& right) {
        sort(left.begin(),left.end());
        sort(right.begin(),right.end());
        int m=left.size();
        int n=right.size();
        if(m==0) return k-right[0];
        if(n==0) return left[m-1];
        int max_len=max(k-left[m-1],right[0]);
        return max_len+(left[m-1]-right[0]);
    }
};

第三题:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
考察的是一个动态规划,没有做出来。。。看了别人大佬的解答,这里就copy下别人的代码,附上代码思路链接。

class Solution {
public:
    int numSubmat(vector<vector<int>>& mat) {
        int n = mat.size();
        int m = mat[0].size();
        vector<vector<int> > left(n,vector<int>(m));
        int now = 0;
        for(int i=0;i<n;i++){
            now = 0;
            for(int j=0;j<m;j++){
                if(mat[i][j] == 1) now ++;
                else now = 0;
                left[i][j] = now;
            }
        }
        int ans = 0,minx;
        for(int i=0;i<n;i++){
            for(int j=0;j<m;j++){
                minx = 0x3f3f3f3f;
                for(int k=i;k>=0;k--){
                    minx = min(left[k][j],minx);
                    ans += minx;
                }
            }
        }
        return ans;
    }
};

第四题:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
刚拿到这个题确实第一思路就是贪心算法,开始想的是只要后面的数字比前面的小就交换,后来发现不对,以示例1为例,只要遇到后面的数字比前面小就交换的结果是
在这里插入图片描述
显然2314是大于1342的,这时候应该考虑的是尽量把后面的最小的数往前移动,以字符串54321,k=4为例
在这里插入图片描述
我们的做法是把字符串后面的最小的1往前面移动,最终最小的结果就是15432,当字符串的长度n大于k时,我们只需要考虑字符串的前k项,因为只能移动k步,当k大于n*(n-1)/2时,这个就是一个冒泡排序的最糟糕的一种情况,只需要对该字符串进行排序输出就可以了。如果继续以该字符串为例,当k=7时,我们所做的就是把字符串后面的2移到前面来,如下图:
在这里插入图片描述
对此我们需要三个变量来确定该字符串的下标:
在这里插入图片描述
i来确定排头,当最小的数字到达排头时,i往后移一位,j来确定字符串可移动最大距离中的最小数,具体代码如下:

class Solution {
public:
    string minInteger(string num, int k) {
        int n=num.size();
        if(k>n*(n-1)/2){
            sort(num.begin(),num.end());
            return num;
        }
        if(k<0) return num;
        char min_char;
        //用a来记录最小字符的下标
        int a;
        //k较小时,最大移动距离为k,k较大时,最大移动距离是字符串的长度
        for(int i=0;i<n&&i<k;i++){
            min_char=num[i];
            a=i;
            for(int j=i;j<n&&j<i+k+1;j++){
                if(min_char>num[j]){
                //在排头确定的情况下确定可移动最大距离中的最小字符
                    min_char=num[j];
                    a=j;
                }
            }
            for(int d=a;d>i;d--){
            //将最小的字符移到排头,k<0时直接输出
                if(k>0){
                    swap(num[d-1],num[d]);
                    k--;
                }
                else return num;
            }
        }
    return num;
    }
};

总结:

  1. 这一次的算法考试难度不算大,可能第三题的动态规划不太好想。
  2. 第四题除了暴力的贪心算法,也可以使用线索树。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值