• [LeetCode] 九坤-03. 数字默契考验


    一、题目

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

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

    示例 1:
    输入:numbers = [50, 75, 100]
    输出:5
    解释:
    numbers[0] * 2 * 3 = 300 操作两次;
    numbers[1] * 2 * 2 = 300 操作两次;
    numbers[2] * 3 = 300 操作一次。共计操作五次。
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    示例 2:
    输入:numbers = [10, 14]
    输出:-1
    解释:无法通过操作得到相同数字。
    
    • 1
    • 2
    • 3
    提示:
    • 1 <= numbers.length <= 10^5
    • 1 <= numbers[i] <= 10^9

    二、题解

    1. 任何一个数字都可以分解成 x ∗ 2 m ∗ 3 n x*2^{m}*3^{n} x2m3n
    2. 假如 n u m b e r [ i ] number[i] number[i] n u m b e r [ j ] number[j] number[j]可以通过乘以2或者乘以3变成相等的数字 n u m [ k ] num[k] num[k],根据1.有:
      n u m b e r [ i ] = n u m [ i ] ∗ 2 m i ∗ 3 n i number[i] = num[i]*2^{mi}*3^{ni} number[i]=num[i]2mi3ni n u m b e r [ j ] = n u m [ j ] ∗ 2 m j ∗ 3 n j number[j] = num[j]*2^{mj}*3^{nj} number[j]=num[j]2mj3nj
      那么有: n u m [ k ] = n u m [ i ] ∗ 2 m i ∗ 3 n i ∗ 2 x i ∗ 3 x j = n u m [ j ] ∗ 2 m j ∗ 3 n j ∗ 2 x j ∗ 3 x j num[k]=num[i]*2^{mi}*3^{ni}*2^{xi}*3^{xj}=num[j]*2^{mj}*3^{nj}*2^{xj}*3^{xj} num[k]=num[i]2mi3ni2xi3xj=num[j]2mj3nj2xj3xj
      由于 n u m [ i ] num[i] num[i] n u m [ j ] num[j] num[j]都与2、3互质,因此为了满足上式,需要保证 n u m [ i ] = n u m [ j ] num[i]=num[j] num[i]=num[j]
    3. 因此,我们可以将numbers中的所有数字分解为 n u m [ i ] ∗ 2 m i ∗ 3 n i num[i]*2^{mi}*3^{ni} num[i]2mi3ni的形式,然后判断 n u m [ 0 ] , n u m [ 1 ] . . . n u m [ n − 1 ] num[0],num[1]...num[n-1] num[0],num[1]...num[n1]是否相等,如果不相等返回 − 1 -1 1。如果相等,再统计 2 m ∗ 3 n 2^{m}*3^{n} 2m3n中2的幂次最大值 m a x m max_m maxm和3的幂次最大值 m a x n max_n maxn,需要乘以2或者乘以3的总次数就是各个数字的2的幂次变成 m a x m max_m maxm和3的幂次变成 m a x n max_n maxn的次数之和。
      具体请看下方代码

    三、代码

    class Solution {
    public:
        // 把一个数字 分成 x *2*2*2*...*3*3*3, 返回{num[i], 2的幂次, 3的幂次}
        tuple<int, int, int> getAns(int num){
            int x = num;
            int cnt_2 = 0;
            int cnt_3 = 0;
            while(x%2==0){
                x/=2;
                cnt_2 ++;
            }
            while(x%3==0){
                x/=3;
                cnt_3 ++;
            }
            return {x, cnt_2, cnt_3};
        }
        
        int minOperations(vector<int>& numbers) {
            int ans = 0;
            int n = numbers.size();
            int a,b,c;
            vector<array<int, 3>> nums(n);
            for(int i=0; i<n; i++){
                tie(nums[i][0],nums[i][1],nums[i][2]) = getAns(numbers[i]);
            }
            for(int i=0; i<n-1; i++){
                if(nums[i][0]!=nums[i+1][0]){
                    return -1;
                }
            }
            int max_cnt_2 = 0;
            int max_cnt_3 = 0;
            for(int i=0; i<n; i++){
                max_cnt_2 = max(max_cnt_2, nums[i][1]);
                max_cnt_3 = max(max_cnt_3, nums[i][2]);
            }
            for(int i=0; i<n; i++){
                ans += max_cnt_2 - nums[i][1];
                ans += max_cnt_3 - nums[i][2];
            }
            return ans;
        }
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 时间复杂度:O(n*log(n));
    • 空间复杂度:O(n*log(n));
  • 相关阅读:
    题目:2667.创建 Hello World 函数
    Java进阶 之 再论面向对象(3)——构造方法Constructors 以及 调用的分析 & JavaBean的概念 & 构造函数中this关键字
    Idea远程debug
    软件质量保护与测试(第2版)学习总结第十三章 集成测试
    【附源码】计算机毕业设计SSM社区留守儿童帮扶系统
    怎样恢复误删和损坏磁盘上的文件
    软件测试——Postman Script脚本功能
    Jackson方法是一种典型的面向数据结构的结构化程序设计方法,其设计目标是从分析系统的数据结构出发,最后得出用Jackson伪代码表示的程序处理过程。
    不只有 Spring,这四款 Java 基础开发框架同样值得关注!
    Linux知识点总结(思维导图,建议收藏)
  • 原文地址:https://blog.csdn.net/Strengthennn/article/details/126473338