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]
。其中数字1
和9
存在重复 -
输出复复的数字以及重复的次数。
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
,则将整数A
和B
称为亲密数。求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, "是完美数")
以上题目都会有多种解决方案。
请同学们自行思考。