目录
递归(DFS)
1.Hanoi问题
这个问题起源于一个类似传说故事,在Hanoi这个地方有一个寺庙,这里有3根柱子和64个大小不同的金碟子。每个碟子有一个孔可以穿过。所有的碟子都放在第一个柱子上,而且按照从上到下碟子的大小依次增大的顺序摆设。如下图:
现在,假定寺庙里的僧侣要移动这些碟子,将它们从最左边移动到最右边的柱子上。不过移动的规则如下:
1. 每次只能从一个柱子的最上面移动一个碟子到另外一个柱子上。
2. 不能将大碟子放到小碟子的上面。
按照前面这个规则,我们该怎么去移动这些碟子呢?假定单位时间内可以移动一片碟子,那么最终移动这些碟子到目的柱子需要多长的时间呢?
def hanoi(n,a,b,c):
if n>0:
hanoi(n-1,a,c,b)
print('moving from %s to %s'%(a,c))
hanoi(n-1,b,a,c)
hanoi(3,'A','B','C')
2.全排列(DFS)
n=int(input())
vis=[0]*(n+1)
num=[0]*(n+1)
def dfs(step):
if step==n+1:
for i in num[1:]:
print(i,end=' ')
print()
return
for i in range(1,n+1):
if vis[i]==0:
num[step]=i
vis[i]=1
dfs(step+1)
vis[i]=0
return
dfs(1)
查找
1.二分查找
class Solution:
def search(self, nums: list[int], target: int) -> int:
left = 0
right = len(nums) - 1
while left <= right:
mid = (left + right) // 2
if nums[mid] == target:
return mid
elif nums[mid] > target:
right = mid - 1
else:
left = mid + 1
else:
return -1
排序
1.冒泡排序
import random
def randlist(n):
a=list()
for i in range(n):
a.append(random.randrange(0,1000,1))
return a
def Bubble_sort(list):
for i in range(len(list)-1):
for j in range(len(list)-1):
if list[j]>list[j+1]:
list[j],list[j+1]=list[j+1],list[j]
return list
list1=randlist(20)
print(list1)
list1=Bubble_sort(list1)
print(list1)
2.选择排序
import random
def list_create(n):
a = list()
for i in range(n):
a.append(random.randint(0, 15))
print(a)
return a
def Select_Sort_1(list):
b = []
for i in range(len(list)):
min_num = min(list)
b.append(min_num)
list.remove(min_num)
print(b)
return b
def Select_Sort_2(li):
for i in range(len(li)):
max_num = 0
location = 0
for j in range(len(li) - i):
if li[j] > max_num:
max_num = li[j]
location = j
li[location], li[len(li) - i - 1] = li[len(li) - i - 1], li[location]
print(li)
return li
m = [1, 5, 3, 9, 6, 4, 7, 7, 2, 3, 5, 4]
n = [1, 5, 3, 9, 6, 4, 7, 7, 2, 3, 5, 4]
Select_Sort_1(m)
print(' * ' * 20)
Select_Sort_2(n)
3.插入排序
4.快速排序
import random
def list_create(n):
a = list()
for i in range(n):
a.append(random.randint(0, 100))
print(a)
return a
def partition(li, left, right):
tmp = li[left]
while left < right:
while tmp < li[right] and left < right:
right -= 1
if left >= right:
break
li[left] = li[right]
left += 1
if left >= right:
break
while tmp > li[left] and left < right:
left += 1
if left >= right:
break
li[right] = li[left]
right -= 1
li[left] = tmp
print(m)
return left
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)
return li
m = list_create(10)
print(m)
quick_sort(m, 0, len(m) - 1)
print(m)
链表
import random
#用一个类表示列表的一个节点
class Node:
def __init__(self,val):
self.val=val
self.next=None
#创建链表_头插法
def creat_linklist_head(list):
head = Node(list[0])
for i in list[1:]:
node=Node(i)
node.next=head
head=node
return head
#创建链表_尾插法
def creat_linklist_tail(list):
head = Node(list[0])
tail=head
for i in list[1:]:
node=Node(i)
tail.next=node
tail=node
return head
#链表打印
def linklist_print(head):
m=head
while m:
print(m.val,end=', ')
m=m.next
a=[1,3,5,9,7,8]
print(a)
b=creat_linklist_head(a)
c=creat_linklist_tail(a)
linklist_print(b)
print()
linklist_print(c)
哈希表
贪心算法
找零问题,有面值 100 50 20 5 1的RMB,怎么找零使得钱的数量最少
t=[100,50,20,5,1]
def greedy(money):
pieces=[0 for i in range(len(t))]
for i,temp in enumerate(t):
pieces[i]=money//t[i]
money%=t[i]
return pieces
print(greedy(7))
DP
1.切钢管问题——一维DP
#钢管切割问题
p=[0,1,5,8,9,10,17,17,20,24,30]
def Solution(p,n):
if n==0:
return p[n]
else:
waste_max=p[n]
for i in range(1,n):
waste_max=max(waste_max,Solution(p,i)+Solution(p,n-i))
return waste_max
print(Solution(p,9))
#使用递归算法加动态规划
2.01背包问题——二维DP
给你一个可装在W的背包和N个物品,每个物品的有重量和价值两个属性,第i个物品的重量是wt[i],价值为val[i],现在让你用这个背包装物品,最多能装的价值是多少?
def backage(N,W,wt,val):
dp = []
for i in range(N + 1):
dp.append([0] * (W + 1))
for i in dp:
print(i)
for i in range(N+1):
for w in range(W+1):
if i==0 or w==0:
dp[i][w]=0
elif w-wt[i]<0 :
dp[i][w]=dp[i-1][w]
else:
dp[i][w]=max(dp[i-1][w],dp[i-1][w-wt[i]]+val[i])
print(dp[i][w])
#N,W=map(int,input().split())
N,W=3,4
wt=[0,2,1,3]
val=[0,4,2,4]
backage(N,W,wt,val)
#dp[i][w]的含义为:选择前i个物品装入重量为w的背包中,所能创造的最大价值
3.分割两个子集——二维DP
给你一个 只包含正整数 的 非空 数组
nums
。请你判断是否可以将这个数组分割成两个子集,使得两个子集的元素和相等。示例 1:
输入:nums = [1,5,11,5] 输出:true 解释:数组可以分割成 [1, 5, 5] 和 [11] 。示例 2:
输入:nums = [1,2,3,5] 输出:false 解释:数组不能分割成两个元素和相等的子集。
def Solution(num):
plus = sum(num)
if plus % 2 != 0:
return False
else:
W = int(plus / 2)
N = len(num)
val = [0]
val.extend(num)
wt = [0]
wt.extend(num)
dp = []
for i in range(len(num) + 1):
dp.append([0] * (W + 1))
for i in range(N+1):
for w in range(W+1):
if i ==0 or w==0:
dp[i][w]=0
elif w-wt[i]<0 :
dp[i][w]=dp[i-1][w]
else:
dp[i][w]=max(dp[i-1][w],dp[i-1][w-wt[i]]+val[i])
if dp[i][w]==W:
print('可以分割成两个相等的子序列和,每个子序列的和为%d'%W)
else:
print('不可以分割成两个相等的子序列和')
nums = [1,11, 2, 2, 6, 4]
Solution(nums)