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;
}
};
总结:
- 这一次的算法考试难度不算大,可能第三题的动态规划不太好想。
- 第四题除了暴力的贪心算法,也可以使用线索树。