算法题
.
.
.
如何查找出给定的目录路径下的所有的文件路径
import os
def get_all_files(directory):
file_list = []
for root, dirs, files in os.walk(directory):
for file in files:
file_path = os.path.join(root, file)
file_list.append(file_path)
return file_list
# 指定目录路径
directory_path = r"C:\Users\Desktop\luffy\src"
# 获取该目录下的所有文件名称
files = get_all_files(directory_path)
# 打印文件名称
for file in files:
print(file)
.
.
.
查询列表里面目标元素,并返回对应的索引
# 默认列表里的数据是升序排列的
# 用二分法实现
def search_target(nums: [], target: int) -> int:
left = 0 # 索引位置
right = len(nums) - 1
while left <= right:
middle = left + (right - left) // 2
if nums[middle] == target:
if middle == 0 or nums[middle - 1] != target:
return middle
right = middle - 1
elif nums[middle] < target:
left = middle + 1
else:
right = middle - 1
return -1
----------------------------------------------------------
# 遍历法
def search_target(nums: [], target: int) -> int:
for i in nums:
if i == target:
return nums.index(i)
----------------------------------------------------------
print(search_target([1, 1, 2, 3, 4, 5], 5))
print(search_target([5, ], 5))
print(search_target([1, 1, 2, 5, 5, 6, 8], 5))
print(search_target([1, 1, 5, 5, 5, 6, 8], 5))
.
.
.
.
.
.
.
利用列表实现队列的效果,先进先出
# 列表是一个堆栈,元素append往列表的右侧添加,pop也是从右侧弹出,后进先出的效果
# 利用collections模块的双端队列来实现
from collections import deque
class DuiL:
def __init__(self, nums):
self.q = deque(nums, maxlen=100)
def put_in(self, xxx):
self.q.appendleft(xxx)
def get_out(self):
return self.q.pop()
obj = DuiL([1, ])
obj.put_in(555)
obj.put_in(666)
obj.put_in(777)
print(obj.get_out())
print(obj.get_out())
print(obj.get_out())
print(obj.get_out())
# 左边进,右边弹出,先进先出,队列效果
------------------------------------------------
# 利用两个列表,来回导,实现对列效果
class Solution:
def __init__(self):
self.list1 = []
self.list2 = []
def push(self, sth):
self.list1.append(sth)
def pop(self):
# 先判断列表2里面还有没有值,有值,先弹列表2里面的元素
if not self.list2:
# 如果列表2里面空了,列表1里面有值,把列表最右边的值弹出后,紧接着添加到列表2里面去
# 这样当列表1里面从右到左的元素,就会在列表2里面从左到右的添加进去了
# 最后列表2里面的元素就是列表1里面的元素倒序排列了,
# 这样最先放到列表1里面的元素,就变成放在列表2的最后面了
# 这样先往列表1里面放进去的值,就会从列表2里面先弹出来,
while self.list1:
self.list2.append(self.list1.pop())
return self.list2.pop()
obj = Solution()
obj.push(1)
obj.push(2)
obj.push(3)
res1 = obj.pop()
res2 = obj.pop()
res3 = obj.pop()
print(res1, res2, res3)
.
.
.
.
.
.
.
.
.
求两个数的最大公约数
# 1 倒序遍历,找最大公约数
num1 = 100
num2 = 190
def max_num(n):
for i in range(n, 1, -1):
if num1 % i == 0 and num2 % i == 0:
return i
print(max_num(100))
-----------------------------------
# 2 欧几里得辗转相除法,
# 知道有这么一回事,大的数除小的数,得出得余数,再用小的数除以余数,一旦结果为0,
# 则该除号右边的值就是最大公约数
def fun(num1, num2): # 定义一个函数, 两个形参
if num1 < num2: # 判读两个整数的大小,目的为了将大的数作为除数,小的作为被除数
num1, num2 = num2, num1 # 如果if条件满足,则进行值的交换
gong_bei = num1 * num2 # 计算出两个整数的乘积,方便后面计算最小公倍数
yu_shu = num1 % num2 # 对2个整数进行取余数
while yu_shu != 0: # 判断余数是否为0, 如果不为0,则进入循环
num1 = num2 # 重新进行赋值,进行下次计算
num2 = yu_shu
yu_shu = num1 % num2 # 对重新赋值后的两个整数取余数
# 直到 yu_shu 等于0,得到最到公约数就退出循环
gong_bei /= num2 # 得出最小公倍数
print("最大公约数为:%d" % num2) # 输出
print("最小公倍数为:%d" % gong_bei) # 输出
fun(6, 9)
.
.
.
打印9*9乘法表
# 正序的9x9乘法表
for i in range(1, 10):
for j in range(1, i + 1):
print(f'{i} * {j} = {i * j}', end=' ')
print()
1 * 1 = 1
2 * 1 = 2 2 * 2 = 4
3 * 1 = 3 3 * 2 = 6 3 * 3 = 9
4 * 1 = 4 4 * 2 = 8 4 * 3 = 12 4 * 4 = 16
5 * 1 = 5 5 * 2 = 10 5 * 3 = 15 5 * 4 = 20 5 * 5 = 25
6 * 1 = 6 6 * 2 = 12 6 * 3 = 18 6 * 4 = 24 6 * 5 = 30 6 * 6 = 36
7 * 1 = 7 7 * 2 = 14 7 * 3 = 21 7 * 4 = 28 7 * 5 = 35 7 * 6 = 42 7 * 7 = 49
8 * 1 = 8 8 * 2 = 16 8 * 3 = 24 8 * 4 = 32 8 * 5 = 40 8 * 6 = 48 8 * 7 = 56 8 * 8 = 64
9 * 1 = 9 9 * 2 = 18 9 * 3 = 27 9 * 4 = 36 9 * 5 = 45 9 * 6 = 54 9 * 7 = 63 9 * 8 = 72 9 * 9 = 81
---------------------------------------------------
# 倒序的9x9乘法表
for i in range(9, 0, -1):
for j in range(9, i - 1, -1):
print(f'{i} * {j} = {i * j}', end=' ')
print()
9 * 9 = 81
8 * 9 = 72 8 * 8 = 64
7 * 9 = 63 7 * 8 = 56 7 * 7 = 49
6 * 9 = 54 6 * 8 = 48 6 * 7 = 42 6 * 6 = 36
5 * 9 = 45 5 * 8 = 40 5 * 7 = 35 5 * 6 = 30 5 * 5 = 25
4 * 9 = 36 4 * 8 = 32 4 * 7 = 28 4 * 6 = 24 4 * 5 = 20 4 * 4 = 16
3 * 9 = 27 3 * 8 = 24 3 * 7 = 21 3 * 6 = 18 3 * 5 = 15 3 * 4 = 12 3 * 3 = 9
2 * 9 = 18 2 * 8 = 16 2 * 7 = 14 2 * 6 = 12 2 * 5 = 10 2 * 4 = 8 2 * 3 = 6 2 * 2 = 4
1 * 9 = 9 1 * 8 = 8 1 * 7 = 7 1 * 6 = 6 1 * 5 = 5 1 * 4 = 4 1 * 3 = 3 1 * 2 = 2 1 * 1 = 1
.
.
.
.
.
.
去除列表里面的重复元素
l1 = [1, 2, 3, 2, 5, 6]
print(l1[:0]) # []
print(l1[:1]) # [1]
-------------------------------
# 方法1
l2 = []
for i in l1:
if i not in l2:
l2.append(i)
print(l2)
-------------------------------
# 方法2
l2 = list(set(l1))
print(l2)
-------------------------------
# 方法3 比较烦 先用枚举并用for循环拿出结果里的一个个元祖,通过比较元祖里的值,
# 在不在列表从0到该值的索引位置的切片里面
# 注意列表切片是左闭右开的 就是判断当前取出来的值在不在列表的从0到当前位置的切片里,
# 在说明重复了,就不要
res = [i for n, i in enumerate(l1) if i not in l1[:n]]
print(res)
-------------------------------
# 方法4 和上面的方法的思路是一样的
l2 = []
n = 0
for i in l1:
# 当i=0时,l1[:0]的结果是[] 当i=1时,l1[:1]的结果是[1]
# 也就是每取出来一个值,都判断在不在该值前面的列表索引切片里,在就说明重复了!!
if i not in l1[:n]:
print(i)
l2.append(i)
n = n + 1
print(l2)
-------------------------------
.
.
.
.
.
.
保留列表里面重复的元素,把不重复的元素去掉
# 保留列表里面重复的元素,把不重复的元素去掉
l1 = [1, 2, 3, 2, 5, 6, 5, 6]
# 方法1
def qu_chu_bu_fu(l1):
return [x for x in l1 if l1.count(x) > 1]
res = qu_chu_bu_fu(l1)
print(res)
----------------------------------------------
# 方法2
# 用字典记录每个元素出现的次数,然后再遍历字典,找出值等于1的元素,放到一个另外的列表里面,for循环拿到这些值
# 最后再把原列表里对应的这些值删掉
dict1 = {}
def qu_chu_bu_fu(l1):
for i in l1:
if i in dict1:
dict1[i] += 1
else:
dict1[i] = 1
# print(dict1)
list2 = [k for k, v in dict1.items() if v == 1]
for k in list2:
l1.remove(k)
qu_chu_bu_fu(l1)
print(l1)
----------------------------------------
.
.
.
.
.
.
.
.
Python解决五猴分桃问题
有5只猴子上山去摘桃,一直摘到天黑。5只猴子把所有的桃子放在一起,然后约定第二天一早来分桃。
第二天早晨,来了一只猴子。他等了一会后心想:不如干脆我把桃子分了吧。于是他把桃子分成了五等份,分完后发现多了一只桃子。他想:我这么辛苦把桃子分了,这多出的一只桃子理应归我!于是他吃了这只桃子,然后带上一等份桃子,走了!
过了一会,第二只猴子来了。他也等了一会。不耐烦之后也把桃子分成了五等份,也发现多一只桃子。他同样吃了那桃子之后也带走了一等份桃子。
后来,第三、第四、第五只猴子都是先五等分桃子,然后吃掉多出来的一个桃,最后再带走一等份桃子。
问最初一共有多少只桃子?
--------------------------------------
# 代码如下
def zhen_chu_5(p):
# 5个猴子要分5次 所以起了一个for循环 要循环5次
# 目的就是要找出一个数字满足-1 除以5 可以整除,然后拿5份中的4份作为一个整体比如叫xxx
# xxx-1 再除以5 还能整除 然后 再从5份中拿出4份出来作为一个整体
# 以此类推 连续分5次 假如5次都能整除 那么这个数就是我们要找的 必须连续5次都能整除才行,
# 一旦出现一次不能被整除 直接返回False 让monkey_peach函数的while继续
for i in range(5):
p = p - 1
if p % 5 == 0:
# print(p)
p = p / 5 * 4 # /就是直接除 // 就是除法运算后拿整数部分 比如 6//5 等于1
else:
return False
return True
def monkey_peach():
p = 1
# 只要p-1不能被5整除返回False上面函数循环就结束了 就给p+1 在调用zhen_chu_5函数
while not zhen_chu_5(p):
p = p + 1
print(p)
# 穷举法 先认为桃子数为1 然后往整除函数里面放 不符合条件就数字加1,继续往整除函数里面放,
# 一直试到满足五次整除条件的数字出现 while循环就结束了!!!
monkey_peach()
-----------------------------
# 还有一种方法
借给猴子4个桃,这样第一次就可以均分成5堆了。
第一个猴子分一份拿的桃子数,就和原来分一份吃一个拿的桃子数是一样的,
所以剩下的桃子数还可以被分成5份,因为第一个猴子拿的桃子和原来一样多,
所以相当于还是借的桃子没被第一个猴子分了
假设开始桃子总数为X 最后一个猴子分过后剩的桃子数为Y
那么关系就为
然后找出x与y都为整数的时候,又满足方程式的x的最小值

.
.
.
.
.
.
.
杨辉三角
def triangles():
L = [1]
while True:
yield L
L = [sum(i) for i in zip([0] + L, L + [0])]
# 列表相加就是列表数据合并 用zip就是把两个列表的相同位置的值分别放元组里面去
# i 就是每个for循环出的元组 sum对元组里面的所有值求和
res =triangles()
# res.__next__()
# res.__next__()
# res.__next__()
# res.__next__()
# res.__next__()
# res.__next__()
xxx = res.__next__()
print(xxx)
# 也可以用for循环来迭代取值
count = 0
for i in res:
if count < 5:
count += 1
print(i)
else:
break
----------------------
.
.
.
.
.
.
递归函数
def get_age(n):
if n == 1:
return 18
return get_age(n-1) + 2
res = get_age(5) # res=( ( (get_age(1) + 2) + 2) + 2 )+ 2
print(res)
# 直接或者间接调用自己
# 每次调用都必须比上一次简单,离目标结果越近, 并且需要有一个明确的结束条件
"""
get_age(5) = get_age(4) + 2
get_age(4) = get_age(3) + 2
get_age(3) = get_age(2) + 2
get_age(2) = get_age(1) + 2
get_age(1) = 18
"""
.
.
.
.
.
.
将列表里面所有数据按顺序打印出来
items = [[1, 2, [5, 6]], 3, 6, [4, [5, [6, 7, 9]]]]
def shun_xu(items):
for i in items:
if isinstance(i, list):
shun_xu(i)
else:
print(i)
xxx(items)
.
.
.
.
.
给定一个列表nums和一个值val 你需要原地移除所有数组等于val的元素,并返回移除后数组的新长度
# 要求:不要使用额外的列表,必须仅使用O(1)空间复杂度,并原地修改输入数组,元素的顺序可以改变
nums = [1, 1, 2, 1, 3, 4, 5]
val = 1
def remove(nums, val):
if len(nums) == 0:
return 0
slow = 0
fast = 0
while fast < len(nums):
if nums[fast] != val:
nums[slow] = nums[fast]
slow += 1
fast += 1
# 这两行代码就是删除多余数据的
# for i in range(fast - slow):
# nums.pop(slow)
return slow
res = remove(nums, val)
print(res)
print(nums)
-------------------------------------------
# 解题思路用快慢指针,慢指针的目的是,每一次发现遍历出来的值不等于1,
# 就让当前慢指针索引对应的值,等于当前快指针的索引对应的值, 就是用快指针对应的不等于1的值,
# 覆盖掉当前慢指针对应的值
# 然后再让慢指针加1,只有遍历出的值不等于1 ,慢指针才会自增,快指针每一次遍历都会自增1
# 所以这样,每一个便利出的不等一的值,都会顺着慢指针对应的索引逐渐的从0开始慢慢往后放,
# 最后还有一点小问题就是按理说我们要的结果应该是 [2, 3, 4, 5] 实际的结果是[2, 3, 4, 5,3, 4, 5]
# 当快指针等于2的时候,遍历到列表里2的时候,将2赋值给当前慢指针指的索引0的位置
# 快指针等于4的时候,遍历到列表里3的时候,将3赋值给当前慢指针指的索引1的位置
# 快指针等于6的时候,遍历到列表里5的时候,将5赋值给当前慢指针指的索引3的位置
# 这个时候实际上就要考虑把多余的345从列表里删掉,为什么会有多余的345,
# 因为3个1所在的位置被不是1的值填充了
# 所以最后会多3个值出来,我们可以就用while循环结束后的快指针减去慢指针,
# 等于3 然后用for循环连续删3次,列表索引4的位置 就可以把多余的3 4 5 删除掉了
------------------------------------------------------
------------------------------------------------------
# 利用递归的思想,每for循环出来对应的目标值,pop掉后,直接把新列表再传到函数里面,再次调用函数
list1 = [1, 1, 1, 1, 2, 1, 3, 5, 7, 8, 41, 1, 2, 1]
target = 1
def new(list1, target):
if target not in list1:
return len(list1)
for i in range(len(list1)):
if target == list1[i]:
print([i])
list1.pop(i)
return new(list1, target)
print(new(list1, target))
print(list1)
.
.
.
.
.
.
.
编写一个函数 查找列表中 所有中字符串的最长公共前缀
------------------------------------------------
# 如果不存在公共前缀,返回空字符串
# 方法1
l1 = ['abc', 'abcuuu', 'abckl', 'abcsd']
def common_prefix(l1):
prefix = ''
res = zip(*l1)
print(res)
for i in res:
if len(set(i)) == 1:
prefix += i[0]
else:
break
return prefix
print(common_prefix(l1))
------------------------------------------------
# 方法2
l1 = ['abc', 'abcuuu', 'abkl', 'asd']
def long_common_prefix(l1):
if not l1:
return ''
prefix = l1[0] # 默认第一个字符串与其他所有的字符串去比较,并先把'abc'当成公共前缀
for i in l1[1:]:
while prefix not in i: # 当发现公共前缀不在后面的字符串里面,就把公共前缀削掉一位
prefix = prefix[:-1]
# 直到公共前缀削到满足后面第一个字符串后,再for循环后面第二个字符串
return prefix
result = long_common_prefix(l1)
print(result)
------------------------------------------------
.
.
.
.
.
.
.
.
给定一个列表与一个目标值,从列表中找出两个值的和等于目标值,并返回该两个值的数组下标
# 给定一个列表与一个目标值,从列表中找出两个值的和等于目标值,并返回该两个值的数组下标
nums = [2, 5, 11, 15, 7]
target = 26
class Solution:
def two_sum(self, nums, target):
hash_map = {}
for i, num in enumerate(nums):
if target - num in hash_map:
return [hash_map[target - num], i]
hash_map[num] = i
return []
obj = Solution()
print(obj.two_sum(nums, target))
.
.
.
.
.
.
.
.
面试题1
str1 = ''
str2 = ' '
if not str1:
print(1)
elif not str2:
print(2)
else:
print(0)
# 打印的是1
print(str1 is None) # False
print(bool(str1)) # False
print(str2 is None) # False
print(bool(str2)) # True
None 代表的是一个空 什么都没有
而 '',是一个字符串对象,代表一个空的字符串。
所以只要是字符串就不是None 空字符串也不是空,是个对象
但是 空字符串的布尔值是False 而' ' 有个空格的字符串布尔值是true
# Python语言中,if后任何非0和非空(None)值为True,0或者null为False。
.
.
.
.
.
.
.
面试题2
# i j k 都可以取1 2 3 所有的组合中 i j k 值都不相等的组合有多少种?
# 就是用的排列组合知识
res = 0
for i in range(1, 4):
for j in range(1, 4):
for k in range(1, 4):
if i != j and i != k and j != k:
res += 1
print(res) # 6
.
.
.
.
.
.
.
面试题3
counter = 1
def doLotsOfStuff():
global counter # 不申明,代码就会报错
for i in (1, 2, 3):
counter += 1
doLotsOfStuff()
print(counter) # 4
# 局部名称空间可以引用全局的变量,但是不能改全局的变量
# 但是一旦申明局部用的变量就是全局的变量,那么在局部就可以直接改全局的该变量的值了
-------------------------------------
strs = 'I like python'
one = strs.find('a')
print(one) # 如果存在返回第一次出现位置的索引值,否则返回-1
two = strs.index('a')
print(two) # 如果str不在 string中会报一个异常
-------------------------------------
.
.
.
对列表排序后生成的列表与原列表指向的内存地址一样吗???不一样!!!
lis = [1,3,2]
a = id(lis)
lis = sorted(lis)
b = id(lis)
print(a==b) # False 排序以后生成的列表已经不是原列表了
lis = [1,3,2]
a = id(lis)
lis += [4,5]
b = id(lis)
print(a==b) # True 列表的拼接相当于往原列表里添加值,列表内存地址不变
tup = (1,3,2)
a = id(tup)
tup += (4,5)
b = id(tup)
print(a==b) # False 元组没法增删改操作,此处两元组拼接生成的是新元组,旧元组没变
-------------------------------------------------------
# 解析
使用sorted()进行排序会生成新的序列,生成的新序列和原序列id值必然不同。
元组是不可变对象,则操作前后序列的id值会改变
.
.
.
.
.
.
global与nonlocal的作用
-----------------------------------------------------------
global作用:
申明局部空间使用的变量为全局里面的变量 这样局部名称空间就可以修改全局名称空间的变量
nonlocal作用:
申明局部内层名称空间使用的变量为局部外层名称空间里面的变量
这样局部内层名称空间修改局部外层名称空间的变量
-----------------------------------------------------------
def index():
name = 'jason'
def inner():
nonlocal name
name = 'kevin'
inner()
print(name)
index() # kevin
.
.
.
.
.
.
在python3.x执行下列选项的程序,不会抛出异常的是()
b = 1
def fn():
nonlocal b
b = b + 1
print(b)
fn() # 报错!!!
---------------------------------------------------
tup = (('onion','apple'),('tomato','pear'))
for _,fruit in tup:
print(fruit) # 不报错
---------------------------------------------------
a = [b for b in range(10) if b % 2 == 0]
print(b) # 中间变量b在生成列表后被销毁,因此再次使用变量b会报错
---------------------------------------------------
lis = [1,2,'a',[1,2]]
set(lis) # 集合元素不能是列表这类不可散列对象,因此会报错。
---------------------------------------------------
A选项,变量b属于全局变量,所以应该使用global声明而不是nonlocal;
B选项,可以使用_作为占位符,所以B选项不会报错;
C选项,python3.x中,使用列表生成式,中间变量b在生成列表后被销毁,因此再次使用变量b会报错;
D选项,集合元素不能是列表这类不可散列对象,因此会报错。
.
.
.
.
.
排列与组合
组合计算公式


.
.
排列计算公式


.
.
.
.
.
.

浙公网安备 33010602011771号