【LeetCode】第 317 场周赛题解

92 阅读5分钟

6220. 可被三整除的偶数的平均值

给你一个由正整数组成的整数数组 nums ,返回其中可被 3 整除的所有偶数的平均值。

注意:n 个元素的平均值等于 n 个元素 求和 再除以 n ,结果 向下取整 到最接近的整数。

 

示例 1:

输入: nums = [1,3,6,10,12,15]
输出: 9
解释: 6 和 12 是可以被 3 整除的偶数。(6 + 12) / 2 = 9

示例 2:

输入: nums = [1,2,4,7,10]
输出: 0
解释: 不存在满足题目要求的整数,所以返回 0 。

 

提示:

  • 1 <= nums.length <= 1000
  • 1 <= nums[i] <= 1000

题解: 哈希表

class Solution {
public:
    int averageValue(vector<int>& nums) {
        long long sum = 0;
        int cnt = 0;
        for(auto c : nums){
            if(c%3 == 0&& c%2 == 0){
                sum += c;
                cnt++;
            }
        }
        if(cnt == 0){
            return 0;
        }
        return sum/cnt;
    }
};

6221. 最流行的视频创作者

给你两个字符串数组 creators 和 ids ,和一个整数数组 views ,所有数组的长度都是 n 。平台上第 i 个视频者是 creator[i] ,视频分配的 id 是 ids[i] ,且播放量为 views[i] 。

视频创作者的 流行度 是该创作者的 所有 视频的播放量的 总和 。请找出流行度 最高 创作者以及该创作者播放量 最大 的视频的 id 。

  • 如果存在多个创作者流行度都最高,则需要找出所有符合条件的创作者。
  • 如果某个创作者存在多个播放量最高的视频,则只需要找出字典序最小的 id 。

返回一个二维字符串数组 **answer **,其中 **answer[i] = [creatori, idi] **表示 **creatori 的流行度 最高 且其最流行的视频 id 是 **idi **,可以按任何顺序返回该结果

 

示例 1:

输入: creators = ["alice","bob","alice","chris"], ids = ["one","two","three","four"], views = [5,10,5,4]
输出: [["alice","one"],["bob","two"]]
解释:
alice 的流行度是 5 + 5 = 10 。
bob 的流行度是 10 。
chris 的流行度是 4 。
alice 和 bob 是流行度最高的创作者。
bob 播放量最高的视频 id"two" 。
alice 播放量最高的视频 id"one""three" 。由于 "one" 的字典序比 "three" 更小,所以结果中返回的 id"one"

示例 2:

输入: creators = ["alice","alice","alice"], ids = ["a","b","c"], views = [1,2,2]
输出: [["alice","b"]]
解释:
id 为 "b""c" 的视频都满足播放量最高的条件。
由于 "b" 的字典序比 "c" 更小,所以结果中返回的 id 是 "b"

 

提示:

  • n == creators.length == ids.length == views.length
  • 1 <= n <= 105
  • 1 <= creators[i].length, ids[i].length <= 5
  • creators[i] 和 ids[i] 仅由小写英文字母组成
  • 0 <= views[i] <= 105

题解:哈希表 + 优先队列

class Solution {
public:
    struct cmp{
       bool operator()( pair<int,string> a, pair<int,string> b){
        if(a.first == b.first){
               return a.second > b.second;
         }
         return a.first < b.first;
        }  
    };
    
    vector<vector<string>> mostPopularCreator(vector<string>& c, vector<string>& ids, vector<int>& v) {
       unordered_map<string, long long> cv;
       unordered_map<string, priority_queue<pair<int, string>, vector<pair<int, string>>, cmp>> cs;
        int n = c.size();
        long long maxv = INT_MIN;
        for(int i=0; i<n; i++){
            cv[c[i]] += v[i];
            if(cv[c[i]] > maxv){
                maxv = cv[c[i]];
            }
            cs[c[i]].push(make_pair(v[i], ids[i]));
        }
        vector<string> maxC;
        for(auto[k, v] : cv){
            if(v == maxv){
                maxC.push_back(k);
            }
        }
        vector<vector<string>> res;
        for(auto cc : maxC){
            vector<string> t;
            t.push_back(cc);
            t.push_back(cs[cc].top().second);
            res.push_back(t);
        }
        return res;
    }
};

6222. 美丽整数的最小增量

给你两个正整数 n 和 target 。

如果某个整数每一位上的数字相加小于或等于 target ,则认为这个整数是一个 美丽整数 。

找出并返回满足 n + x 是 美丽整数 的最小非负整数 x 。生成的输入保证总可以使 n 变成一个美丽整数。

 

示例 1:

输入: n = 16, target = 6
输出: 4
解释: 最初,n 是 16 ,且其每一位数字的和是 1 + 6 = 7 。在加 4 之后,n 变为 20 且每一位数字的和变成 2 + 0 = 2 。可以证明无法加上一个小于 4 的非负整数使 n 变成一个美丽整数。

示例 2:

输入: n = 467, target = 6
输出: 33
解释: 最初,n 是 467 ,且其每一位数字的和是 4 + 6 + 7 = 17 。在加 33 之后,n 变为 500 且每一位数字的和变成 5 + 0 + 0 = 5 。可以证明无法加上一个小于 33 的非负整数使 n 变成一个美丽整数。

示例 3:

输入: n = 1, target = 1
输出: 0
解释: 最初,n 是 1 ,且其每一位数字的和是 1 ,已经小于等于 target 。

 

提示:

  • 1 <= n <= 1012
  • 1 <= target <= 150
  • 生成的输入保证总可以使 n 变成一个美丽整数。

题解:贪心算法,让末尾部位 部位 0 的位,变成 0, 前一位 + 1, 位数不够需要补充

/*
         * 12345 1
         * n/10*10+10                12350
         * n/100*100+100             12400
         * n/1000*1000+1000          13000
         * n/10000*10000+10000       20000
         * n/100000*100000+100000   100000
         * 1000000==n*10
         */
class Solution {
public:
    vector<int> get(long long x){
        vector<int> bits;
        while(x){
            bits.push_back(x%10);
            x/=10;
        }
        return bits;
    }
    int sumn(vector<int>& bits){
        int sum = 0;
        for(auto c : bits){
            sum += c;
        }
        return sum;
    }
    void incr(vector<int>& bits){
        int c = 1;
        int n = bits.size();
        int i = 0;
        for(i=0; i<n; i++){
            if(bits[i] != 0){
                bits[i] = 0;
                break;
            }
        }
        i++;
        for(; i<n; i++){
            bits[i] += c;
            c = bits[i]/10;
            bits[i] %=10;
        }
        if(c > 0){
            bits.push_back(c);
        }
    }
    void print(vector<int> bb){
        for(auto c : bb){
            cout<<c<<" ";
        }
        cout<<endl;
    }
    long long makeIntegerBeautiful(long long n, int target) {
        vector<int> b = get(n);
        int sum = sumn(b);
        if(sum <= target){
            return 0;
        }
        while(sumn(b) > target){
            incr(b);
           // print(b);
        }
        long long s = 0;
        for(int i=b.size()-1; i>=0; i--){
            s  =  s *10 + b[i];
        }
        return s - n;
    }
};

6223. 移除子树后的二叉树高度

给你一棵 二叉树 的根节点 root ,树中有 n 个节点。每个节点都可以被分配一个从 1 到 n 且互不相同的值。另给你一个长度为 m 的数组 queries 。

你必须在树上执行 m 个 独立 的查询,其中第 i 个查询你需要执行以下操作:

  • 从树中 移除 以 queries[i] 的值作为根节点的子树。题目所用测试用例保证 queries[i]  等于根节点的值。

返回一个长度为 m 的数组 **answer **,其中 **answer[i] **是执行第 i 个查询后树的高度。

注意:

  • 查询之间是独立的,所以在每个查询执行后,树会回到其 初始 状态。
  • 树的高度是从根到树中某个节点的 最长简单路径中的边数 。

 

示例 1:

输入: root = [1,3,4,2,null,6,5,null,null,null,null,null,7], queries = [4]
输出: [2]
解释: 上图展示了从树中移除以 4 为根节点的子树。
树的高度是 2(路径为 1 -> 3 -> 2)。

示例 2:

输入: root = [5,8,9,2,1,3,7,4,6], queries = [3,2,4,8]
输出: [3,2,3,2]
解释: 执行下述查询:
- 移除以 3 为根节点的子树。树的高度变为 3(路径为 5 -> 8 -> 2 -> 4)。
- 移除以 2 为根节点的子树。树的高度变为 2(路径为 5 -> 8 -> 1)。
- 移除以 4 为根节点的子树。树的高度变为 3(路径为 5 -> 8 -> 2 -> 6)。
- 移除以 8 为根节点的子树。树的高度变为 2(路径为 5 -> 9 -> 3)。

 

提示:

  • 树中节点的数目是 n
  • 2 <= n <= 105
  • 1 <= Node.val <= n
  • 树中的所有值 互不相同
  • m == queries.length
  • 1 <= m <= min(n, 104)
  • 1 <= queries[i] <= n
  • queries[i] != root.val

题解: 两遍 DFS ,第一遍DFS求出所有节点的高度,第二遍求出删除节点的高度。

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    vector<int> treeQueries(TreeNode* root, vector<int>& queries) {
        unordered_map<TreeNode*, int> height;
        // 统计每个节点的高度
        function<int(TreeNode*)> get_height = [&](TreeNode* node)->int{
            if (node == NULL){
                return 0;
            }
            height[node] = 1+max(get_height(node->left), get_height(node->right));
            return height[node];
        };
        get_height(root);
        int res[height.size()+1];
        // 排除节点后的高度
        // depth 从root到node遍历高度
        // rest 其余节点最大高度
        function<void(TreeNode*, int ,int)> dfs = [&](TreeNode* node, int depth, int rest){
            if(node == NULL){
                return;
            }
            depth++;
            res[node->val] = rest;
            dfs(node->left, depth, max(rest, depth+height[node->right]));
            dfs(node->right, depth, max(rest, depth+height[node->left]));
        };
        dfs(root, -1, 0);
        vector<int> ans;
        for(auto q : queries){
            ans.push_back(res[q]);
        }
        return ans;
    }
};