• LeetCode第52场双周赛


    第一题 1859. 将句子排序

    题目链接:1859. 将句子排序

    • 将单词切成只含英文字符的单词和数字的一对pair<string, int>
    • 然后根据第二关键字对pair排序
    • 排序后,把单词加到答案字符串ans里就行了
    class Solution {
    private:
        using PSI = pair<string, int>;
        vector<PSI> words;
        string ans;
        int n;
        
    public:
        string sortSentence(string s) {
            n = s.size();
            int i = 0, j = 0;
            while(j < n) {
                j = i;
                while(j < n && s[j] != ' ') {
                    ++j;
                }
                // cout << i << ' ' << j << ' ' << s.substr(i, j - i - 1) << endl;
                words.push_back({s.substr(i, j - i - 1), s[j - 1] - '0'});
                i = j + 1;
            }
            sort(words.begin(), words.end(), [&](PSI a, PSI b) {
                return a.second < b.second;
            });
            for(int i = 0; i < words.size(); ++i) {
                ans += words[i].first;
                if(i != words.size() - 1) {
                    ans += ' ';
                }
            }
            return ans;
        }
    };
    

    第二题 1860. 增长的内存泄漏

    题目链接:1860. 增长的内存泄露

    • 根据题意直接模拟就可以了
    class Solution {
    private:
        vector<int> ans;
        int crashTime;
        
    public:
        vector<int> memLeak(int memory1, int memory2) {
            for(crashTime = 1; crashTime <= memory1 || crashTime <= memory2; ++crashTime) {
                if(memory1 >= memory2) {
                    memory1 -= crashTime;
                } else {
                    memory2 -= crashTime;
                }
            }
            ans.push_back(crashTime);
            ans.push_back(memory1);
            ans.push_back(memory2);
            return ans;
        }
    };
    

    第三题 1861. 旋转盒子

    题目链接:1861. 旋转盒子

    • 先构造原矩阵的旋转矩阵ans
    • 从“下”往“上”考虑每个格子的元素(因为重力是从上往下的)
    • 如果当前格子的元素是“石头”,那么我们就往下一直找“箱子底部”、“石头”或“固定障碍物”
    • 然后修改当前格子的元素为“空”,再把这个“石头”放在那个位置上
    • 这样从下往上修改之后的ans矩阵就是答案
    class Solution {
    private:
        int n, m;             // n 和 m 分别是 box 矩阵的长和宽
        vector<vector<char>> ans;    // ans 是 box 矩阵顺时针翻转 90 度之后的矩阵
        
    public:
        vector<vector<char>> rotateTheBox(vector<vector<char>>& box) {
            n = box.size();
            m = box[0].size();
            ans.resize(m, vector<char>(n, ' '));
            for(int i = 0; i < n; ++i) {        // box 矩阵顺时针翻转 90 度,得到 ans 矩阵
                for(int j = 0; j < m; ++j) {
                    ans[j][n - i - 1] = box[i][j];
                }
            }
            for(int i = m - 1; i >= 0; --i) {   // 从下往上考虑 ans 矩阵的每个元素
                for(int j = 0; j < n; ++j) {
                    if(ans[i][j] == '#') {      // 如果当前位置是个“石头”,那么它会往下“掉”,直到碰到“箱子底部”、其他“石头”或者“固定障碍物”为止
                        for(int k = i + 1; k < m; ++k) {  
                            while(k < m && ans[k][j] == '.') {   // 如果下面一直是“空”,那么石头会一直往下“掉”
                                ++k;
                            }
                            ans[i][j] = '.';        // 修改当前位置的元素为“空”,石头往下“掉”
                            ans[k - 1][j] = '#';
                            break;
                        }
                    }
                }
            }
            return ans;
        }
    };
    

    第四题 1862. 向下取整数对和

    题目链接:1862. 向下取整数对和

    • 用数组 hash 记录某个数在 nums 数组的出现次数,即 hash[i] 表示数字 inums 数组的出现次数
    • 数组 preSum 记录前缀和,preSum[i] 表示 nums 数组中小于等于i的元素个数
    • 对于一个数 i ,所有在范围[ j * i, (j + 1) * i - 1 ]的数除以它并向下取整的数都是 j
    • 所以我们可以枚举所有的数i(i 从 1 到 1e5)
    • 对于每个 i ,枚举“倍数” j ,因为题目给了数据范围是 1e5,所以 i * j <= 1e5
    • 对于固定的数字 i 和“倍数” j,我们需要知道在范围[ j * i, (j + 1) * i - 1 ]内的数的个数,这个个数可以通过前缀和 preSum[(j + 1) * i - 1] - preSum[j * i - 1]得到
    • 因为在数组 nums中,数字 i可能出现不止一次,所以当前枚举的 ij 对答案的贡献是:(preSum[(j + 1) * i - 1] - preSum[j * i - 1]) * hash[i]
    class Solution {
    private:
        using LL = long long;
        const int MAXN = 1e5 + 10;
        const int mod = 1e9 + 7;
        int ans;
        vector<int> hash;          // hash[i] 表示 nums 数组中数字 i 的个数
        vector<int> preSum;        // preSum[i] 表示 nums 数组中小于等于 i 的元素个数
    
    public:
        int sumOfFlooredPairs(vector<int>& nums) {
            hash.resize(MAXN, 0);
            preSum.resize(MAXN, 0);
            ans = 0;
            for(int i = 0; i < (int)nums.size(); ++i) {
                ++hash[nums[i]];
            }
            for(int i = 1; i < MAXN; ++i) {
                preSum[i] = preSum[i - 1] + hash[i];       // 计算前缀和数组
            }
            for(int i = 1; i < MAXN; ++i) {                // 从 1 到 1e5,枚举所有的数字,考虑它们对答案 ans 的贡献
                for(int j = 1; j * i < MAXN; ++j) {       // j 是当前的“倍数”
                    int l = j * i;                // 在 [j * i, (j + 1) * i - 1] 范围内的数除以 i 向下取整得到的整数都是 j 
                    int r = min(MAXN - 1, (j + 1) * i - 1);     // 因为 (j + 1) * i - 1 可能超过 MAXN,所以这里要取个min
                    ans = (ans + (LL)(preSum[r] - preSum[l - 1]) * j * (LL)(hash[i])) % mod;   // 对于 hash[i] 个 数字 i, 每一个 i,都会对答案贡献 (preSum[r] - preSum[l - 1]) * j  (因为有preSum[r] - preSum[l - 1]个数除以 i 的结果都是 j) 
                }
            }
            return ans;
        }
    };
    
  • 相关阅读:
    JAVA程序员必看的面试题
    百度技术研发笔试题目
    IBM-JAVA面试题
    .net 面试题系列文章二(附答案)
    Reactive Extensions简介一
    不用恢复出厂设置删除google账户的方法
    如何通过使用64位版本 Windows 查看系统注册表
    Google Goggles的图像识别很好很强大
    实现类似IE的松散耦合(LooselyCoupled )效果——Window Tabifier
    C#的二维码生成和解析
  • 原文地址:https://www.cnblogs.com/linrj/p/14789642.html
Copyright © 2020-2023  润新知