数据结构与算法练习(1)_为什么最小的盈、数是12,2024年最新万字总结

先自我介绍一下,小编浙江大学毕业,去过华为、字节跳动等大厂,目前阿里P7

深知大多数程序员,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年最新Linux运维全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上运维知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以添加V获取:vip1024b (备注运维)
img

正文

解题思路:
本题有2种实现方式:

  1. 找出这个数的所有质因数,再找出其中最大的那一个;
  2. 不断递归调用,判断每次得到的数是否为质数,如果不是,则继续查找。

代码如下:

def max\_prime1(num):
    '''普通方法'''
    prime = 1
    temp = num   
    while temp > 1:
        num_root = int(pow(num, 0.5))
        for i in range(2, num_root+1):
            if temp % i == 0:
                temp /= i
                if i > prime:
                    prime = i
                break
    return prime

def max\_prime2(num):
    '''递归方法'''
    if num == 1:
        return 1
    for i in range(2, int(pow(num, 0.5))+1):
        if num % i == 0:
            return max_prime2(num // i)
    return num

print(max_prime1(600851475143))
print(max_prime2(600851475143))

输出:

6857
6857

性能分析:
第2种方法的性能更高,因为第2种方法相对于第1种,遍历的次数更少。

2.最大回文乘积

回文数就是从前往后和从后往前读都一样的数。由两个2位数相乘得到的最大回文乘积是 9009 = 91 × 99。找出由两个3位数相乘得到的最大回文乘积。

解答思路:
本题也有2种解答方式,两种方式均需要判断一个数是否是回文数,区别在于处理三位数因数的方式:

  • 单层循环,从999*999开始,一直往下找,找到第一个为两个三位数乘积并且为回文数的数即为所找的数;
  • 双层循环,内外循环都从999开始,找到内层与外层的乘积为回文数的数,再找出其中最大的数,即为结果。

代码如下:

def is\_three\_multi(num):
    '''判断一个数是否是两个三位数的乘积'''
    is_multi = False
    for j in range(100, int(pow(num, 0.5)+1)):
        if num % j == 0 and num // j < 1000 and num // j >= 100:
            is_multi = True
            break
    return is_multi

def is\_palindrome(num):
    '''判断一个数是否是回文数'''
    is_palin = False
    num_str = str(num)
    str_len = len(num_str)
    half_len = str_len // 2
    for k in range(half_len):
        if num_str[k] != num_str[str_len-1-k]:
            break
    else:
        is_palin = True
    return is_palin

def max\_palindrome\_multiply1():
    '''单层循环方法'''
    for i in range(999\*999, 100\*100-1, -1):
        if is_three_multi(i):
            if is_palindrome(i):
                return i
    return None

print(max_palindrome_multiply1())


def is\_palindrome(num):
    '''判断一个数是否是回文数'''
    is_palin = False
    nums = []
    while num > 0:
        nums.append(num % 10)
        num //= 10
    num_len = len(nums)
    for i in range(num_len//2):
        if nums[i] != nums[num_len - 1 - i]:
            break
    else:
        is_palin = True
    return is_palin

def max\_palindrome\_multiply2():
    '''双层循环方法'''
    max_pro = 1
    for i in range(999, 99, -1):
        for j in range(999, 99, -1):
            pro = i \* j
            if pro > max_pro and is_palindrome(pro):
                max_pro = pro
                break
    return max_pro

print(max_palindrome_multiply2())

输出:

906609
906609

性能分析:
经过测试,两种方法的效率相近。

3.最小倍数

2520是最小的能够被1到10整除的数。
最小的能够被1到20整除的正数是多少?

解题思路:
本题有3种实现方式:

  1. 本题求最小的能够被1到20整除的正数,其实就是求1到20的最小公倍数,1到n的最小公倍数也是n*(n-1)的倍数,通过不断判断n*(n-1)的倍数是否都能被1到n整除,如果能整除则这个数就是寻找的答案。
  2. 从1开始累乘,如果当前的数与乘积互质、则乘这个数,否则乘这个数与这个数乘积的最大公因数的商。
  3. 先找出2-20所有的质数,并得到它们的乘积作为初始值S,剩下的全是非质数,对于每一个非质数找出组成这个非质数的最小质数z,如果这个非质数能整除S,则S不变,否则S乘z,详细思路可查看https://blog.csdn.net/weixin_30471561/article/details/99387184

代码如下:

import sys

def min\_cumulative\_number1(n):
    max_int = sys.maxsize
    base = n \* (n - 1)
    min_cumul = 1
    for i in range(1, max_int):
        min_cumul = base \* i
        for j in range(1, n + 1):
            if min_cumul % j != 0:
                break
            if j == n:
                return min_cumul
    return min_cumul

print(min_cumulative_number1(20))

def max\_common\_divider(m, n):
    '''寻找两个数的最大公因数'''
    if m < n:
        m, n = n, m
    while n != 0:
        m, n = n, m % n
    return m
        

def min\_cumulative\_number2(n):
    res = 1
    for i in range(1, n + 1):
        common_divider = max_common_divider(res, i)
        if common_divider == 1:
            res \*= i
        else:
            res \*= (i // common_divider)
    return res

print(min_cumulative_number2(20))


def is\_prime(n):
    '''判断一个数是否是质数'''
    is_prime = True
    for i in range(2, int(pow(n, 0.5)) + 1):
        if n % i == 0:
            is_prime = False
            break
    return is_prime

def min\_prime(n):
    '''寻找一个数的最小质数'''
    res = 1
    for i in range(2, int(pow(n, 0.5)) + 1):
        if n % i == 0:
            res = i
            break
    return res

def get\_primes(n):
    '''获取前n个数中的素数列表'''
    primes = []
    for i in range(2, n + 1):
        if is_prime(i):
            primes.append(i)
    return primes


def min\_cumulative\_number3(n):
    nums = [i for i in range(2, n + 1)]
    res = 1
    prime_list = get_primes(n)
    for num in prime_list:
        res \*= num
        nums.remove(num)
    for num in nums:
        res = res if res % num == 0 else res \* min_prime(num)
    return res

print(min_cumulative_number3(20))

输出:

232792560
232792560
232792560

性能分析:
其中第一种方式的性能较低,因为要循环的次数太多(sys.maxsize表示Python中最大的整数);
第二种和第三种的性能相近。

4.并非盈数之和

完全数是指真因数之和等于自身的那些数。例如,28的真因数之和为1 + 2 + 4 + 7 + 14 = 28,因此28是一个完全数。
一个数n被称为亏数,如果它的真因数之和小于n;反之则被称为盈数。
由于12是最小的盈数,它的真因数之和为1 + 2 + 3 + 4 + 6 = 16,所以最小的能够表示成两个盈数之和的数是24。
通过数学分析可以得出,所有大于28123的数都可以被写成两个盈数的和;
尽管我们知道最大的不能被写成两个盈数的和的数要小于这个值,但这是通过分析所能得到的最好上界。
找出所有不能被写成两个盈数之和的正整数,并求它们的和。

解题思路:

  1. 寻找所有的盈数,再找出不能写成两个数的和的数,判断和的方式为嵌套循环,时间复杂度较高;
  2. 判断一个数是否是盈数、形成盈数的列表,在找不能由两个盈数的和组成的数时,用到的是二分法,复杂度降低。

代码如下:

def find\_num\_fac\_sum(n):
    '''寻找一个数的真因数之和'''


### 最后的话

最近很多小伙伴找我要Linux学习资料,于是我翻箱倒柜,整理了一些优质资源,涵盖视频、电子书、PPT等共享给大家!

### 资料预览

给大家整理的视频资料:

![](https://img-blog.csdnimg.cn/img_convert/a26a9def8f2b959e3aa3a87f0cd70518.png)

给大家整理的电子书资料:

  

![](https://img-blog.csdnimg.cn/img_convert/a07dcb6b2a2ac7a4c2468775734660d8.png)



**如果本文对你有帮助,欢迎点赞、收藏、转发给朋友,让我有持续创作的动力!**


**网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**

**需要这份系统化的资料的朋友,可以添加V获取:vip1024b (备注运维)**
![img](https://img-blog.csdnimg.cn/img_convert/4e358327cebf479f821a1cfb98f45453.jpeg)

**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**
子书资料:

  

[外链图片转存中...(img-T0YrCPlm-1713250171800)]



**如果本文对你有帮助,欢迎点赞、收藏、转发给朋友,让我有持续创作的动力!**


**网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**

**需要这份系统化的资料的朋友,可以添加V获取:vip1024b (备注运维)**
[外链图片转存中...(img-zfByOeLk-1713250171801)]

**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**
  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值