算法题

.
.
.

如何查找出给定的目录路径下的所有的文件路径


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的最小值

image
.
.
.
.
.
.
.

杨辉三角

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选项,集合元素不能是列表这类不可散列对象,因此会报错。

.
.
.
.
.

排列与组合


组合计算公式
image
image
.
.
排列计算公式
image
image
.
.
.
.
.
.

posted @ 2023-04-25 01:11  tengyifan  阅读(24)  评论(0)    收藏  举报