英雄哥《零基础算法》13/100之 “最大公约数”

文章目录

  • 一、设问
  • 二、题目
    • 找出数组的最大公约数
    • 序列中不同最大公约数的数目
  • 三、题解报告
    • 找出数组的最大公约数
    • 序列中不同最大公约数的数目
  • 四、知识点笔记
  • 《算法零基础100讲》介绍
  • 参考资料

本学习笔记是根据《算法零基础100讲》进行的每讲总结,目标是采用刻意练习的方法对个人的学习和思考进行总结和归纳,方便复习和进一步深入理解和掌握内化。
每一讲的笔记内容大致分为:

  1. 设问,通过这一讲的学习应该理解什么内容?
  2. 题目,在学习完每讲内容后对题目先进行独立的思考和分析,记录下来;
  3. 题解报告,通过个人思考和学习其他优秀解题方案,记录个人认为较为优秀的解答并进行画图理解和内化吸收,并分析如何优化自己的思考;
  4. 知识点笔记,将本讲内容的知识点进行汇总和扩展,方便日后查阅复习;
  5. 解题模板,尽量将所学代码进行通用化处理。
    另外
    笔记中会尽量用图示的方式将所学内容进行可视化,方便记忆和内化,以及帮助读者进行理解。
    笔记至少会参考5篇以上的参考资料,并在文尾列出。

第十三讲:最大公约数

一、设问

  1. 最大公约数是什么?
  2. 计算最大公约数的方法有哪些?
  3. 如何计算一组数的最大公约数?
  4. 如何计算一组数的子序列的最大公约数数目?

二、题目

找出数组的最大公约数

英雄哥《零基础算法》13/100之 “最大公约数”_第1张图片

step1: 找出最大数和最小数
step2: 计算最大公约数

序列中不同最大公约数的数目

英雄哥《零基础算法》13/100之 “最大公约数”_第2张图片

这道题一开始真的一点思路都没有。
只感觉,首先数组内去重就是第一批最大公约数,另外如何枚举所有的子序列以及如何计算一组数的最大公约数没有想法。

三、题解报告

找出数组的最大公约数

就如上面所说,第一步是找出最大数和最小数,第二步是计算两个数的最大公约数。
第一步需要遍历数组,一一比较确定;
第二步的

int gcd(int a, int b) {
    return !b ? a : gcd (b, a%b);
}

int findGCD(int* nums, int numsSize){
    int max = nums[0];
    int min = nums[0];
    int res = 1;

    for (int i = 1; i < numsSize; i++) {
        max = max > nums[i] ? max : nums[i];
        min = min < nums[i] ? min : nums[i];
    }

    return gcd (max, min);
}

英雄哥《零基础算法》13/100之 “最大公约数”_第3张图片

序列中不同最大公约数的数目

由于从枚举子序列的角度看,复杂度较高,因此转换思路,枚举可能的最大公约数:

  1. 试图遍历子序列可能的所有最大公约数:很明显数据是从1~序列中的最大值;
  2. 判断数据是否为最大公约数:看其中是否有该数据的倍数,并计算序列中所有数的最大公约数,其中:
    1)gcd(0, a) = a;
    2)在进行运算之前先将序列中的所有值使用hash表进行了保存,可以在这一步进行快速判断其倍数是否存在;
    3)仅当计算出的最大公约数=枚举的值时才认为找到了一个最大公约数(防止多次计算);

更多代码的解释可以查看第13讲详细内容。

#define maxn 200001
int has[maxn];

int Max(int a, int b) {
    return a > b ? a : b;                          // (1)
}

int gcd(int a, int b) {
    return !b ? a : gcd(b, a%b);                   // (2)
}

int countDifferentSubsequenceGCDs(int* nums, int numsSize){
    int i, j, t, m = 0, ans = 0;

    memset(has, 0, sizeof(has));                   // (3)
    for(i = 0; i < numsSize; ++i) {
        has[ nums[i] ] = 1;                        // (4)
        m = Max(m, nums[i]);                       // (5)
    }

    for(i = 1; i <= m; ++i) {                      // (6)
        t = 0;
        for(j = i; j <= m; j += i) {               // (7)
            if(has[j])
                t = gcd(t, j);                    
        }
            
        if(t == i)                                 // (8)
            ++ans;
    }
    return ans;
}

四、知识点笔记

  1. 最大公因数Greatest Common Divisor(GCD),也称最大公约数、最大公因子,指两个或多个整数共有约数中最大的一个。与最大公约数相对应的概念是最小公倍数。
    英雄哥《零基础算法》13/100之 “最大公约数”_第4张图片
  2. 求最大公约数有多种方法,常见的有质因数分解法、短除法、辗转相除法、更相减损法。
  3. 模运算满足结合律、交换律和分配律
    英雄哥《零基础算法》13/100之 “最大公约数”_第5张图片
  4. 辗转相除法计算公约数的代码模板
    int gcd(int a, int b) {
    	return !b ? a : gcd(b, a % b);
    }
    
  5. 在解有关最大公约数、最小公倍数的问题时,常用到以下结论:
    (1)如果两个自然数是互质数,那么它们的最大公约数是1,最小公倍数是这两个数的乘积。
    (2)如果两个自然数中,较大数是较小数的倍数,那么较小数就是这两个数的最大公约数,较大数就是这两个数的最小公倍数。
    (3)两个整数分别除以它们的最大公约数,所得的商是互质数。
    (4)两个自然数的最大公约数与它们的最小公倍数的乘积等于这两个数的乘积。
    (5)GCD(a,b) is the smallest positive linear combination of a and b. a与b的最大公约数是最小的a与b的正线性组合,即对于方程xa+yb=c来说,若x,a,y,b都为整数,那么c的最小正根为gcd(a,b).

《算法零基础100讲》介绍

该栏目是CSDN@英雄哪里出来大佬的万人千题计划第一阶段,其目标是让想要学会算法的人抱团成长,能通过这个项目稳步成长,扎扎实实掌握算法,最终用算法改变世界!

img

大佬将算法学习的路线总结如下,并分别根据五步路线总结写出了相应的教学内容,关于目前的第一阶段算法入门的详细的介绍可以看博文《万人千题:第一阶段,算法零基础抱团打卡》学习路线指引

img

100讲的学习大纲如下:

img

参考资料

此处列出除文中链接之外的参考资料

  1. 最大公约数-百度百科
  2. 最大公约数(Gcd)两种算法(Euclid && Stein) [整理]
  3. 浅析求两个数的最大公约数的三种算法
  4. C语言求最大公约数(详解版)
  5. 最大公约数-OI Wiki
  6. Stein算法
  7. 最大公约数-Lucifer

你可能感兴趣的:(万人千题学习报告,#,算法)