递归,排序

面试题:

归并算法
	两个有序序列进行归并
	l1 = [1, 2, 5, 6, 8,10]
	l2 = [3, 4, 7,9,12]
	l3 = []
	i = 0
	j = 0

	while i < len(l1) and j < len(l2):
		if l1[i] < l2[j]:
			l3.append(l1[i])
			i += 1
		else:
			l3.append(l2[j])
			j = j + 1
	while i < len(l1):
		l3.append(l1[i])
		i += 1
	while i < len(l2):
		l3.append(l2[i])
		i += 1

	print(l3)

求阶乘后结果的末尾0的个数
	n= 5
	rus = 1
	while n>0:
		rus = rus*n
		n-=1
	s = str(rus)
	count =0
	s= '120000000'
	for i in range(len(s)-1,-1,-1):
		if s[i]=='0':
			count +=1
		else:
			break
	print(count)

字典排序:
	alist =[{'name':'a','age':20},{'name':'b','age':30},{'name':'c','age':25}]
	alist = sorted(alist,key=lambda dic:dic['age'])
	print(alist)

斐波那契数列
a, b, c = 1, 2, 3
n = 400000
i = 0
while a < n:
	print(a)
	i += 1
	a, b, c = b, c, b + c
print(i)


def fib(n):
    li = [1,1]
    for i in range(2,n+1):
         li.append(li[-1]+li[-2])
    return li[-1]

def fib(n):
    if n ==0 or n == 1:
        return 1
    a = 1
    b = 1
    c = 1
    for i in range(2,n+1):
        a = b
        b = c
        c = a + b
    return c
	
# 青蛙跳台阶问题
def func(n):
    if n == 0:
        return 0
    if n == 1:
        return 1
    if n == 2:
        return 2
    return func(n - 1) + func(n - 2)


print(func(4))

递归
汉诺塔问题
def hanoi(n,A,B,C):
	if n>0:
		hanoi(n-1,A,C,B)
		print('%s -> %s' % (A,C))
		hanoi(n-1,B,A,C)
	hanoi(2,'A','B','C')


二分查找
def bin_search(li, val):
	'''使用low和high标注索引,mid为中间索引,这里的索引代表指针,每次以中间值比较大小,比较完后改变索引'''
    low = 0
    high = len(li) - 1
    while low <= high:
        mid = (high - low) // 2
        if li[mid] > val:
            high = mid - 1
        elif li[mid] < val:
            low = mid + 1
        else:
            return mid
    return -1
	
	
	
使用and代替if语句
def func():
    print('aaa')

x = -3
x > 0 and func()
# 等价于
if x > 0:
    func()
# 所以可以使用and代替if语句()
# a and b <==> a if a == 0 else b
# a or b  <==> b if a == 0 else a


[外排序,对大内存有效](https://www.cnblogs.com/codeMedita/p/7425291.html)
简单的说就是先分段,将每段排好后,然后使用归并排序,对于两段进行归并排序时,可以一点点读数据归并,然后数据一点点写入磁盘
如 1 2 3 5 6 12 18 20 24 和 4 5 7 20 25 30 21 25 26 进行归并时,可以先归并前5个结果是 1 2 3 4 5 5 6 7 12 18 然后将归并后结果写入磁盘 十种排序算法 # 推荐:https://blog.csdn.net/yangnianjinxin/article/details/77918882 选择排序、快速排序、希尔排序、堆排序不是稳定的排序算法,而冒泡排序、插入排序、归并排序和基数排序是稳定的排序算法 low逼三人组 冒泡(稳定 o(n2)) # 走n趟,没趟交换比较选出最大的 def bubble_sort(li): for i in range(len(li) - 1): exchange = False # 没有交换表示已经排好序了,就不用再继续执行了 for j in range(len(li) - 1 - i): if li[j] > li[j + 1]: li[j], li[j + 1] = li[j + 1], li[j] exchange = True if not exchange: return 选择排序(不稳定) # 一趟遍历选择记录中最小的数,放到第一个位置 # 再一趟遍历记录剩余列表中最小的数,继续放置 def select_sort(li): for i in range(len(li) - 1): min_pos = i for j in range(i + 1, len(li)): if li[j] < li[min_pos]: min_pos = j li[min_pos], li[j] = li[j], li[min_pos] 插入排序 # 列表分为有序区和无序区两个部分,最初有序区只有一个元素 # 每次从无序区选择一个元素,插入到有序区的位置,直到无序区变空 # 类似于玩纸牌时的插牌 # 可以优化空间使用二分查找来寻找插入点(并没有什么卵用) def insert_sort(li): for i in range(1, len(li)): # 无序区 j = i-1 # 有序区最后一个数 tmp = li[i] while j >= 0 and li[j] > tmp: # 有序区从大到小逐一比较,直到有序区数小于li[i] li[j+1] = li[j] j -= 1 li[j+1] = tmp 牛逼三人组(o(nlogn)) 快排 # 取一个元素p(第一元素),使元素p归位 # 列表被p分为两部分,左边的都比p小,右边的都比p大 # 递归完成排序 def _quick_sort(li, left, right): if left < right: # 至少两个元素 mid = partition(li, left, right) _quick_sort(li, left, mid-1) _quick_sort(li, mid+1, right) def quick_sort(li): _quick_sort(li, 0, len(li)-1) def partition(li, left, right): i = random.randint(left, right) # 随机选一个数,防止最坏情况 li[left], li[i] = li[i], li[left] tmp = li[left] while left < right: while left < right and li[right] >= tmp: #从右开始选,直到找到一个小于tmp的数,把这个数填在left位置 right -= 1 li[left] = li[right] while left < right and li[left] <= tmp: #从左开始选,直到找到一个大于tmp的数,把这个数填在right位置 left += 1 li[right] = li[left] li[left] = tmp return left # 一行代码实现快排 # 这样空间复杂度会高 def quicksortshort(arr): return [] if arr==[] else quicksortshort([y for y in arr[1:] if y<arr[0]]) + [arr[0]]+ quicksortshort([y for y in arr[1:] if y>=arr[0]]) 堆排 # 1,建立堆 # 2,得到堆顶元素,为最大元素 # 3,去掉堆顶,将堆最后一个元素放到堆顶,此时可通过一个调整重新使堆有序 # 4,堆顶元素为第二大元素 # 5,重复步骤3,直到堆变空 def sift(li, low, high): # 调整,从子孩子中选出最大的和父节点比较,如果大于父节点就和父节点的值交换,然后父节点的值继续和子节点的子节点进行比较 # low 表示根位置 high 表示最后元素的位置 tmp = li[low] i = low # i指向空位 j = 2 * i + 1 # j指向孩子 # 把tmp写回来有两种条件 1. tmp > li[j] 2. j位置没有值 (也就是i已经是叶子了) while j <= high: # 对应退出条件2 if j + 1 <= high and li[j+1] > li[j]: # 如果右孩子存在且右孩子更大 j += 1 if li[j] > tmp: li[i] = li[j] i = j j = 2 * i + 1 else: # 对应退出条件1 break li[i] = tmp li = [3,5,6,2,0,4,1,9,8,7] def heap_sort(li): n = len(li) # 1. 建立堆 for low in range(n//2-1, -1, -1): # li = [3,5,6,2,0,4,1,9,8,7] ''' 3(索引0) 5(1) 6(2) 2(3) 0(4) 4(5) 1(6) 9(7) 8(8) 7(9) ''' # 如 n=10时,low的值依次是 4,3,2,1,0 从最后的非叶子节点开始调整 sift(li, low, n-1) print(li) # 此时的li已经是一个大根堆了 # [9, 8, 6, 5, 7, 4, 3, 0, 1, 2] ''' 9(索引0) 8(1) 6(2) 5(3) 7(4) 4(5) 3(6) 0(7) 1(8) 2(9) ''' # 2. 挨个出数 退休-棋子-调整 for high in range(n-1, -1, -1): # high 的值 9,8,7,6,,5,4,3,2,1,0 li[0], li[high] = li[high], li[0] # 这样交换后最大的就变到了列表的最后位置上, sift(li, 0, high-1) # 然后调整的时候就不把已经退休的(最大的)考虑在内了 python内置的堆模块 import heapq li = [2,5,7,8,9,6,1,4,3] heapq.heapify(li) #调整变为小根堆 print(li) # [1, 3, 2, 4, 9, 6, 7, 5, 8] heapq.heappush(li, 0) # 插入新值,自动调整为小根堆 print(li) # [0, 1, 2, 4, 3, 6, 7, 5根堆, 8, 9] print(heapq.heappop(li)) # 堆顶退休(最小值),继续调整为小 print(heapq.heappop(li)) print(heapq.nlargest(5, li)) # 输出最大的5个数 # [9, 8, 7, 6, 5] print(heapq.nsmallest(5, li)) # 输出最小的5个数 # [2, 3, 4, 5, 6] 列表中取出前k大的数 # 1,取列表前k个元素建立一个小根堆,堆顶就是这个堆中最小的数,也是这个堆中第k大的数 # 2,依次向后遍历原列表,对于列表中的元素,如果小于堆顶,则忽略该元素,如果大于堆顶则将堆顶更换为改元素,并且对堆进行一次调整 # 3,遍历列表所有元素后,倒序弹出堆顶 归并 def merge(li, low, mid, high): li_tmp = [] i = low j = mid + 1 while i <= mid and j <= high: if li[i] <= li[j]: li_tmp.append(li[i]) i += 1 else: li_tmp.append(li[j]) j += 1 while i <= mid: li_tmp.append(li[i]) i += 1 while j <= high: li_tmp.append(li[j]) j += 1 for i in range(len(li_tmp)): # 把归并排好的两个列表放回到li中 li[i+low] = li_tmp[i] def _merge_sort(li, low, high): if low < high: # 2个元素及以上 mid = (low + high) // 2 _merge_sort(li, low, mid) _merge_sort(li, mid+1, high) #print(li[low:mid+1], li[mid+1:high+1]) merge(li, low, mid, high) #print(li[low:high + 1]) def merge_sort(li): _merge_sort(li, 0, len(li)-1) 没什么人用的排序 基数排序 希尔排序 桶排序 二叉树 列表中索引:父节点 -> 左孩子节点 i -> 2i+1 父节点 -> 右孩子节点 i -> 2i+2 孩子节点 -> 父节点 i -> (i-1)//2 堆顶 i = 0 所有父节点 i_list =[i for i in range(len(li)//2)] 大根堆:一个完全二叉树,满足任一节点都比其孩子节点大 小根堆:一个完全二叉树,满足任一节点都比其孩子节点小 当根节点的左右子树都是堆时(这里的示例是大根堆),可以通过一次向下调整来将其变换成一个堆

  

 

转载于:https://www.cnblogs.com/perfey/p/10200377.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值