LeetCode第273场周赛
T1 5963. 反转两次的数字
题目描述:给你一个整数\(num\),反转 \(num\) 得到 \(reversed_1\) ,接着反转 \(reversed_1\) 得到 \(reversed_2\) 。如果 \(reversed_2\) 等于 \(num\) ,返回 \(true\) ;否则返回 \(false\) 。
思路:根据题意判断\(num\)是否大于等于\(10\)且末尾是否是\(0\)即可
时间复杂度:\(O(1)\)
参考代码:
class Solution {
public:
bool isSameAfterReversals(int num) {
return !(num >= 10 && num % 10 == 0);
}
};
T2 5964. 执行所有后缀指令
题目描述:点击上面的链接自行查看
思路:考虑到数据范围很小,直接暴力模拟即可
时间复杂度:\(O(n^2)\)
参考代码:
class Solution {
public:
vector<int> executeInstructions(int n, vector<int>& startPos, string s) {
int m = s.size();
vector<int> res(m , 0);
for(int j = 0 ; j < m ; ++j){
int x = startPos[1] , y = startPos[0];
int cnt = 0;
for(int i = j ; i < m ; ++i){
int dx = x , dy = y;
if(s[i] == 'U') --dy;
else if(s[i] == 'D') ++dy;
else if(s[i] == 'L') --dx;
else ++dx;
if(dx < 0 || dx >= n || dy < 0 || dy >= n) break;
++cnt;
x = dx ; y = dy;
}
res[j] = cnt;
}
return res;
}
};
T3 5965. 相同元素的间隔之和
题目描述:给你一个下标从\(0\)开始、由\(n\)个整数组成的整数\(arr\)。\(arr\)中两个元素的间隔定义为它们下标的差值的绝对值。返回一个长度为\(n\)的数组\(intervals\),其中\(intervals_i\)表示\(arr\)中与\(arr_i\)值相同的元素的间隔之和。
示例:
输入:arr = [2,1,3,1,2,3,3]
输出:[4,2,7,2,4,4,5]
解释:
- 下标 0 :另一个 2 在下标 4 ,|0 - 4| = 4
- 下标 1 :另一个 1 在下标 3 ,|1 - 3| = 2
- 下标 2 :另两个 3 在下标 5 和 6 ,|2 - 5| + |2 - 6| = 7
- 下标 3 :另一个 1 在下标 1 ,|3 - 1| = 2
- 下标 4 :另一个 2 在下标 0 ,|4 - 0| = 4
- 下标 5 :另两个 3 在下标 2 和 6 ,|5 - 2| + |5 - 6| = 4
- 下标 6 :另两个 3 在下标 2 和 5 ,|6 - 2| + |6 - 5| = 5
数据范围: \(1 \leq n \leq 1e5 , 1\leq arr_i \leq 1e5\)
思路:设\(f_i\)表示下标比\(i\)小且值与\(arr_i\)相同的数字对\(i\)的答案的贡献,假设\(i\)前面有\(x\)个数字与它相同且下标最大的一个的下标是\(j\),则\(f_i\)的转移方程为:\(f_i = f_j + x * (i - j)\) ;同理,设\(g_i\)表示下标比\(i\)大且值与\(arr_i\)相同的数字对\(i\)的答案的贡献,假设\(i\)后面有\(y\)个数字与它相同,且下标最小的一个的下标是\(j\),则\(g_i\)的转移方程为\(g_i = g_j + y * (j - i)\)。最终\(i\)的答案为\(res_i = f_i + g_i\)。注意开long long。
时间复杂度:\(O(n)\)
参考代码:
class Solution {
public:
vector<long long> getDistances(vector<int>& arr) {
int n = arr.size();
vector<vector<int>> graph(100005);
vector<long long> f(n , 0) , g(n , 0) , res(n , 0);
for(int i = 0 ; i < n ; ++i) graph[arr[i]].push_back(i);
for(int i = 1 ; i <= 100000 ; ++i){
if(graph[i].size() == 0) continue;
int m = graph[i].size();
for(int j = 1 ; j < m ; ++j){
int dx = graph[i][j] , dy = graph[i][j - 1];
f[dx] = f[dy] + 1ll * (dx - dy) * j;
}
for(int j = m - 2 ; j >= 0 ; --j){
int dx = graph[i][j] , dy = graph[i][j + 1];
g[dx] = g[dy] + 1ll * (dy - dx) * (m - j - 1);
}
}
for(int i = 0 ; i < n ; ++i) res[i] = f[i] + g[i];
return res;
}
};
T4 5966. 还原原数组
题目描述:给你一个长度为\(2n\)的数组\(nums\) , 存在一个原数组,对原数组中的每一个数都\(+k\)和\(-k\)(\(k\)为正整数),并将通过这种方式产生的\(2n\)个数放入一个数组中就构成了\(nums\)。现需要你求出原数组,保证有解。
数据范围:\(1\leq n \leq 1000\)
思路:首先将\(nums\)从小到大排序,则\(nums_{2n - 1}\)一定是原数组中的某个数\(x\) , \(+k\)得到的,所以我们可以暴力枚举\(nums\)中的元素作为\(x - k\),求出此时的\(k\)并检验,如果符合题意就返回这个解。过程中可以使用map辅助解的检验,时间复杂度是:\(O(n^2logn)\)理论上能过,但常数很大且力扣计算总时间,这个复杂度就不行了;考虑使用离散化进行优化,将\(nums\)中的元素映射成教小的数字,然后开一个桶用来辅助实现,理论复杂度还是\(O(n^2logn)\),但常数较小,可以通过此题。
参考代码:
class Solution {
private:
map<int , int>mp;
bool check(vector<int>& nums, vector<int>& cnt , int k){
for(auto num : nums) cnt[mp[num]]++;
int n = nums.size();
for(int i = n - 1 ; i >= 0 ; --i){
if(cnt[mp[nums[i]]] == 0) continue;
cnt[mp[nums[i]]]--;
int dx = nums[i] - 2 * k;
if(mp.count(dx) == 0) return false;
dx = mp[dx];
if(cnt[dx] == 0) return false;
--cnt[dx];
}
return true;
}
public:
vector<int> recoverArray(vector<int>& nums) {
sort(nums.begin() , nums.end());
int tot = 0;
for(auto num : nums) mp[num] = ++tot;
vector<int> cnt(3005 , 0);
int n = nums.size(), k = -1;
for(int i = n - 2 ; i >= 0 ; --i){
int dx = nums[n - 1] - nums[i];
if(dx & 1) continue;
k = dx / 2;
if(k == 0)continue;
if(check(nums, cnt , k)) break;
for(int i = 0 ; i <= tot ; ++i) cnt[i] = 0;
}
for(auto num : nums) cnt[mp[num]]++;
vector<int> res;
for(int i = n - 1 ; i >= 0 ; --i){
if(cnt[mp[nums[i]]] == 0) continue;
cnt[mp[nums[i]]]--;
int dx = nums[i] - 2 * k;
dx = mp[dx];
--cnt[dx];
res.push_back(nums[i] - k);
}
return res;
}
};
附超时代码:
class Solution {
private:
bool check(vector<int>& nums , int k){
unordered_map<int , int>mp;
for(auto num : nums) mp[num]++;
int n = nums.size();
for(int i = n - 1 ; i >= 0 ; --i){
if(mp[nums[i]] == 0) continue;
mp[nums[i]]--;
int dx = nums[i] - 2 * k;
if(mp[dx] == 0) return false;
--mp[dx];
}
return true;
}
public:
vector<int> recoverArray(vector<int>& nums) {
sort(nums.begin() , nums.end());
int n = nums.size(), k = -1;
for(int i = n - 2 ; i >= 0 ; --i){
int dx = nums[n - 1] - nums[i];
if(dx & 1) continue;
k = dx / 2;
if(k == 0)continue;
if(check(nums , k)) break;
}
unordered_map<int , int>mp;
for(auto num : nums) mp[num]++;
vector<int> res;
for(int i = n - 1 ; i >= 0 ; --i){
if(mp[nums[i]] == 0) continue;
mp[nums[i]]--;
int dx = nums[i] - 2 * k;
--mp[dx];
res.push_back(nums[i] - k);
}
return res;
}
};
作者:cherish.
出处:https://home.cnblogs.com/u/cherish-/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。