第一次参加力扣的比赛,结果给忘记了,想起来的时候快结束了,只做了两个题,可惜可惜。
题目A 判断能否形成等差数列
给你一个数字数组 arr 。
如果一个数列中,任意相邻两项的差总等于同一个常数,那么这个数列就称为 等差数列 。
如果可以重新排列数组形成等差数列,请返回 true ;否则,返回 false 。
题解
排序:
对数组sort一下,求出公差,for一边判断一下。
不排序:
遍历一遍,记录MAX和MIN,并hash一下记录出现的元素,然后通过MAX,MIN,size求出公差,然后判断等差数列所以元素是否存在。
代码
class Solution {
public:
bool canMakeArithmeticProgression(vector<int>& arr) {
if(arr.size() <= 2) return true;
sort(arr.begin(),arr.end());
int d = arr[1] - arr[0];
for(int i = 2;i < arr.size();i++){
if(arr[i]-arr[i-1] != d)
return false;
}
return true;
}
};
题目B 所有蚂蚁掉下来前的最后一刻
有一块木板,长度为 n 个 单位 。一些蚂蚁在木板上移动,每只蚂蚁都以 每秒一个单位 的速度移动。其中,一部分蚂蚁向 左 移动,其他蚂蚁向 右 移动。
当两只向 不同 方向移动的蚂蚁在某个点相遇时,它们会同时改变移动方向并继续移动。假设更改方向不会花费任何额外时间。
而当蚂蚁在某一时刻 t 到达木板的一端时,它立即从木板上掉下来。
给你一个整数 n 和两个整数数组 left 以及 right 。两个数组分别标识向左或者向右移动的蚂蚁在 t = 0 时的位置。请你返回最后一只蚂蚁从木板上掉下来的时刻。
题解
思维题,只需要把改变方向的两个蚂蚁想成交换一下,就相当于蚂蚁一直向前走,距离所在方向端点最远的蚂蚁就是答案。
代码
class Solution {
public:
int getLastMoment(int n, vector<int>& left, vector<int>& right) {
int ans = 0;
for(int i = 0;i < left.size();i++){
ans = max(ans,left[i]);
}
for(int i = 0;i < right.size();i++){
ans = max(ans,n-right[i]);
}
return ans;
}
};
题目B 统计全 1 子矩形
给你一个只包含 0 和 1 的 rows * columns 矩阵 mat ,请你返回有多少个 子矩形 的元素全部都是 1 。
题解
暴力:
只需要预处理一下每个点向左连续为1的个数,枚举每个点做矩阵右下点时,高度为k的矩阵个数(k行内最短的连续1的个数)
时间复杂度O(nnm)
代码
//暴力
class Solution {
public:
int numSubmat(vector<vector<int>>& mat) {
int n = mat.size();
int m = mat[0].size();
vector<vector<int> > count(n,vector<int>(m));
for(int i = 0;i < n;i++){
if(mat[i][0] == 1) count[i][0] = 1;
else count[i][0] = 0;
for(int j = 1;j < m;j++){
if(mat[i][j]) count[i][j] = count[i][j-1]+1;
else count[i][j] = 0;
}
}
int ans = 0;
for(int i = 0;i < n;i++){
for(int j = 0;j < m;j++){
int sum = INT_MAX;
for(int k = i;k >= 0;k--){
sum = min(sum,count[k][j]);
ans += sum;
}
}
}
return ans;
}
};
题目D 5455. 最多 K 次交换相邻数位后得到的最小整数
给你一个字符串 num 和一个整数 k 。其中,num 表示一个很大的整数,字符串中的每个字符依次对应整数上的各个 数位 。
你可以交换这个整数相邻数位的数字 最多 k 次。
请你返回你能得到的最小整数,并以字符串形式返回。
题解
首先,整数大小依据是最高位的数字大小,所以,最优解一定是尽量把最高位变小, 我们从最高位的数字,首先从最小数0开始枚举是否可以通过交换置换到当前位置(最近的0的位置 - 空位 < 交换次数),不可以一次枚举12.9。
我们要计算当前位置交换到目标位置需要的次数,需要记录这段范围内空闲的位置,明显线段树(只有单点修改,区间查询,我就只写了树状数组)
代码
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 3e4 + 50;
vector<int> pos[10];
int sum[MAXN], cur[10], n;
int lowbit(int x){
return x & -x;
}
void add(int x, int v){
for (int i = x; i <= n; i += lowbit(i))
sum[i] += v;
}
int get(int x){
int ret = 0;
for (int i = x; i; i -= lowbit(i))
ret += sum[i];
return ret;
}
class Solution {
public:
string minInteger(string num, int K) {
n = num.length();
for (int i = 0; i <= n; i++)
sum[i] = 0;
for (int i = 0; i < 10; i++)
pos[i].clear(), cur[i] = 0;
for (int i = 0; i < n; i++)
pos[num[i] - '0'].push_back(i + 1);
string ans = "";
for (int i = 1; i <= n; i++){
for (int k = 0; k < 10; k++){
if (cur[k] >= pos[k].size()) continue;
int op = pos[k][cur[k]];
int p = op + get(op) - 1;
if (p <= K){
K -= p;
ans += (char)('0' + k);
add(op, -1);
cur[k]++;
break;
}
}
}
return ans;
}
};