Python 作业解答

本文介绍了在编程中解决一系列数学问题的几种常见算法,包括使用双指针法找和为目标值的数字对、哈希查询解决两数之和问题、约瑟夫环问题的求解、亲密数的判断、勾股数、素数查找、反序数、回文数验证和完全数的识别,展示了不同场景下的编程技巧。
摘要由CSDN通过智能技术生成

1. 在给定的一些数字中找出2个数,使得它们的和为N

题目要求

  • 如给定5个数字 [3,4,9,7,10] 从中选择两个数使用它们的和为11
  • 必须保证这些数据中有答案,并且只有一个答案。

1.1 解题思路一:双指针

  • 把数据放在列表中,使用双指针方法解决。注:双指针要求原始列表中的数据已经排序。
  • 先将列表中的数据从小到大排序,排序时需要保留原来数据的下标。
  • 设置两个指针,一个指向第一个数据(left),一个指向最后一个数据(right)
  • 如果两个指针所指向数据之和大于目标值,则right减少。如果小于目标值,则left增加。

编码实现:

nums = [3, 4, 9, 7, 10]
#对数列排序
sort_nums = sorted(nums)
# 左指针
left = 0
# 右指针
right = len(nums) - 1
# 目标值
target = 11

while left <= right:
    if sort_nums[left] + sort_nums[right] == target:
        break
    elif sort_nums[left] + sort_nums[right] > target:
        right -= 1
    else:
        left += 1
# 找到数据在原数列中的位置,可以使用线性查找
for i in range(len(nums)):
    if sort_nums[left] == nums[i]:
        print(sort_nums[left], i)
    if sort_nums[right] == nums[i]:
        print(sort_nums[right], i)

算法分析:

  • **时间复杂度为 O(n)。**这里没有考虑排序时间复杂度。
  • 空间复杂度:o(n) 空间复杂度一般指算法执行过程中需要借用的空间。这里需要借用一个列表保存原列表中的数据。

1.2 解题思路二:哈希查询

  • 建立字典,存放数据和下标对应关系

编码实现:

def twoSum(nums, target):
    dict_ = {}
    for i in range(len(nums)):
        # m为当前待查询的数字
        m = nums[i]
        # 判断target-m是否已经在字典中
        if target - m in dict_:
            # 存在返回这两个数的下标
            return (dict_[target - m] , i )
        # 不存在则记录键值对
        dict_[m] = i

nums = [3, 4, 9, 7, 10]
target = 11
res = twoSum(nums, target)
print(res)

算法分析:

  • 时间复杂度:O(n)。因没有排序环节,时间复杂度在优于第一种解题方案。
  • 空间复杂度:o(n)。需要字典存储数据与位置。

1.3 解题思路三:使用列表的 index 方法

  • 这个思路并不能称为思路,而是直接使用 Python 已经编好的底层实现。
nums = [3, 4, 9, 7, 10]
target = 11

for i in range(len(nums)):
    if target - nums[i] in nums:
        print(i, nums.index(target - nums[i]))
        break

2. 给出n个整数,其中有整数是重复的,要求找出这重复的整数。

题目要求

  • 如有数列[2,1,7,1,9,10,4,9]。其中数字19存在重复

  • 输出复复的数字以及重复的次数。

    1 2

    9 2

2.1 解题思路一:循环嵌套方案。

  • 第一层循环:从列表中按顺序拎出每一个数字。
  • 第二层循环:再次扫描列表,查找是否有与第一次循坏中拎出来相同的数字。

编码实现:

nums = [2, 1, 7, 1, 9, 10, 4, 9]
for i in range(len(nums)):
    for j in range(i + 1, len(nums)):
        if nums[i] == nums[j]:
            print(nums[i])

算法分析:

  • 时间复杂度:O(n2)
  • 空间复杂度:O(1)

2.2 解题思路二:字典缓存法

  • 使用字典记录每一个数字在列表中的出现的次数
nums = [2, 1, 7, 1, 9, 10, 4, 9]
dic = {}
for i in nums:
    if i not in dic:
        dic[i] = 1
    else:
        dic[i] += 1
print([(k, v) for k, v in dic.items() if v > 1])

算法分析:

  • 时间复杂度为O(n)
  • 空间复杂度为O(n)

2.3 解题思路三:使用列表的count方法

nums = [2, 1, 7, 1, 9, 10, 4, 9]
for i in nums:
    if nums.count(i)>1:
        print(i)

3、在一间房间总共有n个人(下标0~n-1),只能有最后一个人活命。

**题目需求:**假设一个房间总共有 10 个人,每一个人都有编号(0~9),现按照如下规则排除人。

  • 所有人围成一圈,然后输入一个基数如 3
  • 顺时针报数,每次报到3的人将被排除掉的人将从房间内被移走。
  • 然后从被kill掉的下一个人重新报数,继续报 3,再清除,直到剩余一人。
  • 求解最后留下来的人的编号是多少。

上述问题名为约瑟夫环问题,是一个经典的数学问题。

3.1 解题思路一

思路:每一次列表中最前面的 3 个数字移动列表的最后面,然后删除第 3 个数字。列表最后留下来的数字就是幸存数字。

nums = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
base_num = 3
right = len(nums) - 1
while right != 0:
    for i in range(3):
        if i == right:
            i = 0
        nums.append(nums.pop(0))
    nums.pop()
    right = len(nums) - 1
    print(nums, "right:" + str(right))

可以稍许修改一下:不删除,通过右指针缩小列表长度。

nums = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
base_num = 3
right = len(nums) - 1
while right != 0:
    for i in range(3):
        if i == right:
            i = 0
        nums.insert(right, nums.pop(0))
    right -= 1
    print(nums, "right:" + str(right))

4. 亲密数

题目需求:

如果整数A的全部因子(包括1,不包括A本身)之和等于B,且整数B的全部因子(包括1,不包括B本身)之和等于A,则将整数AB称为亲密数。求3000以内的全部亲密数。
提示:按照亲密数定义,要判断整数a是否有亲密数,只要计算出a的全部因子的累加和,将其存到变量b,再计算b的全部因子的累加和设为n,若n等于a,则可判定a和b是亲密数。

编码实现:

for i in range(3000):
    numa = i
    yzs = 0
    for i in range(1, numa):
        if numa % i == 0:
            yzs += i
    s1 = 0
    for i in range(1, yzs):
        if yzs % i == 0:
            s1 += i
    if s1 == numa:
        print(numa, yzs)

5. 求100以内的所有勾股数。

题目需求:
所谓勾股数,是指能够构成直角三角形三条边的三个正整数(a,b,c)。根据“勾股数”定义,所求三角形三边应满足条件a2+b2=c^2。可以在所求范围内利用穷举法找出满足条件的数。

for a in range(1, 100):
    for b in range(1, 100):
        for c in range(1, 100):
            if a ** 2 + b ** 2 == c ** 2:
                print(a, b, c)

6. 有多少个重复数字

用1、2、3、4共4个数字能组成多少个互不相同且无重复数字的三位数?都是多少?求互不相同的三位数,可以一位一位地去确定,先确定百位,再确定十位和个位,各位上的数值进行比较,若互不相同则输出。

for i in range(1, 5):
    for j in range(1, 5):
        if i == j:
            continue
        for k in range(1, 5):
            if k == j or k == i:
                continue
            print(i, j, k)

7. 求素数

请找出 10000之内的所有素数,(素数指只能被1和自身整除的数字)

for i in range(10000):
    is_zs = True
    for j in range(2, i):
        if i % j == 0:
            is_zs = False
            break
    if is_zs:
        print(i)

8.4位反序数,

假设N是一个四位数,它的9倍恰好是其反序数,求N。反序数就是将整数的数字倒过来的形成的整数。

for i in range(1000,9999):
    if str(i*9)[::-1]==str(i*9):
        print(i)

9. 回文数

请验证程序运行时输入的数字是不是一个回文数(12321就是回文数,从左向右从右向左都相同)

i=12321
if str(i)[::-1] == str(i):
    print(i,"是回文数")

10. 完全数

如果一个数恰好等于他的因子之和,则成为“完全数”。如:6的因子是1、2、3,而6=1+2+3,则6是个“完全数”。试求出1000以内的全部“完全数”。

nums = 6
s = 0
for i in range(1, nums):
    if nums % i == 0:
        s += i
if s == nums:
    print(nums, "是完美数")

以上题目都会有多种解决方案。

请同学们自行思考。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一枚大果壳

码文不易,晚上熬夜需要点咖啡钱

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值