返回顶部

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;
    }
};
posted @ 2021-12-26 16:31  cherish-lgb  阅读(23)  评论(0编辑  收藏  举报