九坤投资专场竞赛题解

1,113 阅读2分钟

1. 可以读通讯稿的组数

校运动会上,所有参赛同学身上都贴有他的参赛号码。某班参赛同学的号码记于数组 nums 中。假定反转后的号码称为原数字的「镜像号码」。如果 两位同学 满足条件:镜像号码 A + 原号码 B = 镜像号码 B + 原号码 A,则这两位同学可以到广播站兑换一次读通讯稿的机会,为同班同学加油助威。请返回所有参赛同学可以组成的可以读通讯稿的组数,并将结果对10^9+7取余。

注意:

  1. 镜像号码中如存在前置零,则忽略前置零。
  2. 同一位同学可有多次兑换机会。

示例 1:

输入:nums = [17,28,39,71]

输出:3

解释:
共有三对同学,分别为 [17,28]、[17,39]、[28,39]。其中:
第一对同学:17 + 82 = 71 + 28;
第二对同学:17 + 93 = 71 + 39;
第三对同学:28 + 93 = 82 + 39。

示例 2:

输入:nums = [71, 60]

输出:1

解释:
共有一对同学,为 [71, 60]。
因为 71 + 6 = 17 + 60,此处 60 的镜像号码为 6,前导零被忽略。

提示:

  • 0 <= nums.length <= 10^6
  • 0 <= nums[i] <= 10^9

题解: 哈希表

class Solution {
public:
    int numberOfPairs(vector<int>& nums) {
        int n = nums.size();
        vector<int> f;
        for(auto x : nums){
            int t = x, s =0;
            while(t){
                s = s*10+t%10;
                t/=10;
            }
            f.push_back(s);
        }
        unordered_map<int, int> hash;
        for(int i=0; i<n; i++){
            hash[f[i]-nums[i]]++;
        }
        long res = 0, mod = 1e9+7;
        for(auto [k, v] : hash){
            res += v%mod*(v-1)/2;
        }
        return res%mod;
    }
};

2. 池塘计数

最近的降雨,使田地中的一些地方出现了积水,field[i][j] 表示田地第 i 行 j 列的位置有:

  • 若为 W, 表示该位置为积水
  • 若为 ., 表示该位置为旱地

已知一些相邻的积水形成了若干个池塘,若以 W 为中心的八个方向相邻积水视为同一片池塘。

请返回田地中池塘的数量。

示例 1:

输入: field = [".....W",".W..W.","....W.",".W....","W.WWW.",".W...."]

输出:3

解释:如下图所示,共有 3 个池塘:
image.png

示例 2:

输入: field = ["W....W",".W..W.","..W.W.","W..W..","W.W...",".W...."]

输出:1

解释:如下图所示,共有 1 个池塘:
image.png

提示:

  • 1 <= field.length, field[i].length <= 100
  • field 中仅包含 W 和 .

题解: 搜索 BFS/DFS

class Solution {
public:
    void dfs(vector<string>&g, int x, int y, int n, int m){
        if(x < 0 || x>=n || y <0 || y>=m){
            return;
        }
        if(g[x][y] == '.'){
            return;
        }
        g[x][y] = '.';
        dfs(g, x-1, y, n, m);
        dfs(g, x, y+1, n, m);
        dfs(g, x+1, y, n, m);
        dfs(g, x, y-1, n, m);
        dfs(g, x-1, y+1, n, m);
        dfs(g, x+1, y+1, n, m);
        dfs(g, x+1, y-1, n, m);
        dfs(g, x-1, y-1, n, m);
        
    }
    int lakeCount(vector<string>& g) {
        int n = g.size(), m = g[0].size();
        int res = 0;
        for(int i=0; i<n; i++){
            for(int j=0; j<m; j++){
                if(g[i][j] == 'W'){                   
                    res++;
                    dfs(g, i, j, n, m);
                }
            }
        }
        return res;
    }
};

3. 数字默契考验

某数学兴趣小组有 N 位同学,编号为 0 ~ N-1,老师提议举行一个数字默契小测试:首先每位同学想出一个数字,按同学编号存于数组 numbers。每位同学可以选择将自己的数字进行放大操作,每次在以下操作中任选一种(放大操作不限次数,可以不操作):

  1. 将自己的数字乘以 2
  2. 将自己的数字乘以 3

若最终所有同学可以通过操作得到相等数字,则返回所有同学的最少操作次数总数;否则请返回 -1。

 

示例 1:

输入:numbers = [50, 75, 100]
输出:5
解释:
numbers[0] * 2 * 3 = 300 操作两次;
numbers[1] * 2 * 2 = 300 操作两次;
numbers[2] * 3 = 300 操作一次。共计操作五次。

示例 2:

输入:numbers = [10, 14]
输出:-1
解释:无法通过操作得到相同数字。

提示:

  • 1 <= numbers.length <= 10^5
  • 1 <= numbers[i] <= 10^9

题解: 最小公倍数

class Solution {
public:
    int minOperations(vector<int>& nums) {
        int n = nums.size();
        long long s = 1;
        for(int i=0; i<n; i++){
            s = s/__gcd(s, (long long)nums[i]) * (long long)nums[i];
        }
        int res = 0;
        for(int i=0; i<n; i++){
            long diff = s/nums[i];
            if(diff%2 == 0){
                while(diff%2 == 0) diff /=2, res++;
            }
            if(diff%3 == 0){
                while(diff%3 == 0) diff /=3, res++;
            }
            if(diff != 1) return -1;
        }
        return res;
    }
};

第四题不知道怎么做😭。。。