第一次打leetcode的比赛,打的virtual,简单说下每题的思路。
反转两次的数字
大意:判断一个数字翻转两次后是否还是原来的数字,翻转后要去掉前导零。
只要末位不是零翻转两次肯定没变化,要特判一下0
代码:
class Solution {
public:
bool isSameAfterReversals(int num) {
if(num == 0) return true;
return num % 10;
}
};
执行所有后缀指令
大意:给一个长度为n的URDL操作序列和一个起点,问从0~n-1开始按照操作序列顺序移动,在不越界的情况下能移动多少次。
没想到简单的办法,暴力模拟一下也不超时,复杂度O(n2)。
代码:
class Solution {
public:
vector<int> executeInstructions(int n, vector<int>& startPos, string s) {
vector<int> ans;
for(int i = 0;i < s.size();++i){
int r = startPos[0];
int c = startPos[1];
for(int j = i; j < s.size();++j){
if(s[j] == 'L'){
c -= 1;
}else if(s[j] == 'R'){
c += 1;
}else if(s[j] == 'U'){
r -= 1;
}else{
r += 1;
}
if(r >= n || c >= n || r < 0 || c < 0){
ans.push_back(j-i);
break;
}
if(j == s.size()-1){
ans.push_back(j-i+1);
}
}
}
return ans;
}
};
相同元素的间隔之和
大意:给一个数组,问每个数字与相同数字下标的距离和。
没太多时间思考,写了个空间复杂度很爆炸的方法。把每个元素分两类统计,一个是在该元素前面的,一个是在该元素后面的,比如该元素下标是i,sum[i]表示该元素下标集合的前缀和,j表示该元素是相同元素中的第几个。m表示该类元素的个数,那么第一类就是 j×i - sum[j-1],第二类就是(sum[m-1] - sum[j]) - 1LL×(m-j-1)×i。具体实现看代码。时间复杂度O(N),空间复杂度O(N),但常数极度爆炸。pos数组改成哈希表可能会好一点。
代码:
class Solution {
public:
vector<long long> getDistances(vector<int>& a) {
int n = a.size();
vector<long long> ans = vector<long long>(n,0);
vector<vector<int>> pos = vector<vector<int>>(1e5+1,vector<int>());
vector<long long> sum = vector<long long>(1e5+1,0);
for(int i = 0 ; i < n; ++ i)
pos[a[i]].push_back(i);
for(int i = 0 ;i < 1e5+1;++i){
int m = pos[i].size();
sum[0] = m?pos[i][0]:0;
for(int j = 1;j < m; j++) sum[j] = 1LL*pos[i][j]+sum[j-1];
for(int j = m-1;j >= 0;-- j){
long long pre = 0,aft = 0;
if(j > 0) pre = 1LL*j*pos[i][j] - sum[j-1];
if(j < m-1) aft = (sum[m-1] - sum[j]) - 1LL*(m-j-1) * pos[i][j];
ans[pos[i][j]] = pre + aft;
}
}
return ans;
}
};
还原原数组
大意:原来有一个数组a和一个k,生成两个数组:b[i] = a[i] + k,c[i] = c[i] - k。现在只有混起来的b,c数组d。求a和k。
继续暴力,考虑一下b和c的关系,显然b[i] = c[i] + 2×k,那么就先对数组排个序,假设k确定了,那么只需要从0开始,为每个数找到d[i] + 2*k,如果找不到或者已经被前面的数用完了,那么这个k就是非法的。这个k其实也很好枚举,排序后的d[0],其他n-1个数和他只有n-1种组合,k也只有n-1个,时间复杂度O(n2)。
代码:
class Solution {
public:
vector<int> recoverArray(vector<int>& nums) {
int n = nums.size();
sort(nums.begin(),nums.end());
unordered_map<int,int> mp;
vector<int> ans;
int kk = 0;
for(int i = 0 ; i< n; ++ i) mp[nums[i]]++;
for(int i = 1; i <= n/2; ++ i){
int k = (nums[i] - nums[0])/2;
if(!k || (nums[i]-nums[0])%2) continue;
bool flag = 1;
mp[nums[i]]--;
mp[nums[0]]--;
vector<int> temp;
for(int j = 0;j < n; ++ j){
if(!mp[nums[j]]) continue;
int next = nums[j] + 2*k;
if(!mp[next]){
flag = false;
break;
}
mp[next]--;
mp[nums[j]]--;
temp.push_back(next);
temp.push_back(nums[j]);
}
for(auto x:temp) mp[x]++;
mp[nums[i]]++;
mp[nums[0]]++;
if(flag){
kk = k;
break;
}
}
for(int i = 0;i < n; ++ i){
if(mp[nums[i]] && mp[nums[i]+2*kk]){
ans.push_back(nums[i]+kk);
mp[nums[i]]--;
mp[nums[i]+2*kk]--;
}
}
return ans;
}
};