今后努力还是要刷算法题
一、 生成螺旋矩阵copy个6阶的螺旋矩阵过来~
[[ 1. 2. 3. 4. 5. 6.]
[20. 21. 22. 23. 24. 7.]
[19. 32. 33. 34. 25. 8.]
[18. 31. 36. 35. 26. 9.]
[17. 30. 29. 28. 27. 10.]
[16. 15. 14. 13. 12. 11.]]
找到一个很好的答案:https://www.cnblogs.com/pyonwu/p/12215086.html
思路:
1.先生成一个零矩阵,再往里面填充数字;
2.每填充完一个,都判断下一步该往哪走,下一步有四种状态:横+、纵+、横-、纵-,依次循环。
3.每种状态间切换的条件:原状态的下一步的元素已被填充(!=0)或索引溢出。
import numpy as np
def r_matrix(n):
mt = np.zeros(n**2).reshape(n,n)
x, y = 0, 0
num = 1
direction = 1
while mt[x][y] == 0:
mt[x][y] = num
num += 1
if -1<y+direction<n and mt[x][y+direction] == 0:
y += direction
elif x+direction<n and mt[x+direction][y] == 0:
x += direction
else:
direction = -direction
y += direction
return mt
二、递归问题:https://mp.weixin.qq.com/s/mJ_jZZoak7uhItNgnfmZvQ
1. 一个人赶着鸭子去每个村庄卖,每经过一个村子卖去所赶鸭子的一半又一只。这样他经过了七个村子后还剩两只鸭子,问他出发时共赶多少只鸭子?
import numpy as np
def sunn(n,m,p):
if n == m:
# sunn(7,7) == 2
return p
return (sunn(n+1,m)+1)*2
if __name__ =='__main__':
print(sunn(0,7,p))
2. n级台阶的楼梯,从下往上走,每跨一步只能向上1级或者2级台阶,共有多少种走法。
f(0)=0;f(1)=1;f(n)=f(n-1)+f(n-2)
递归过程之所以耗时,是因为每一次递归都需要在栈中开辟新的调用栈执行子方法,在栈的反复开辟、销毁过程中,不仅耗时激增,最为关键的是,反复的栈开辟让内存占用率急剧增长。
递归实现:缺点容易爆栈
def jumpFloor(number):
if number == 0:
return 0
if number == 1:
return 1
if number == 2:
return 2
return jumpFloor(number - 1) + jumpFloor(number - 2)
尾递归的方式,基本思路是通过一个参数来保存上次执行结果,另一个参数保存累计值
import time
def jumpFloor(number):
if number == 0:
return 0
if number == 1:
return 1
if number == 2:
return 2
return solute(number, 0, 1)
def solute(number, a, b):
if number == 0:
return b
return solute(number-1, b, a+b)
if __name__ == '__main__':
starttime = time.time()
print(jumpFloor(400))
print('耗时:' + str(time.time() - starttime))
#备忘录实现
def Floor_Memo(number):
memo = {1: 1, 2: 2} # 边界条件
count = 2
while count < number:
count += 1
memo[count] = memo[count - 1] + memo[count - 2] # 状态转移方程
return memo[number]
# 动态规划实现:以空间复杂度换时间复杂度,只记F(N-1)和F(N-2)
def Floor_DP(number):
if number == 1: # 边界条件
return 1
if number == 2: # 边界条件
return 2
result = [1, 2] # 只存储前2次结果
count = 2
while count < number:
nexta = sum(result)
result = [result[1], nexta] # 等同于状态转移方程
count += 1
return result[-1]
# 循环
def fibs(n):
a = [1, 1]
for i in range(n - 2):
a.append(a[-2] + a[-1])
return a[n-1]
print(fibs(6))
参考:
https://techlog.cn/article/list/10183325
3.一只青蛙一次可以跳上1级台阶,也可以跳上2级……它也可以跳上n级。求该青蛙跳上一个n级的台阶总共有多少种跳法。
因为n级台阶,第一步有n种跳法:跳1级、跳2级、到跳n级
跳1级,剩下n-1级,则剩下跳法是f(n-1)
跳2级,剩下n-2级,则剩下跳法是f(n-2)
所以f(n)=f(n-1)+f(n-2)+…+f(1)
因为f(n-1)=f(n-2)+f(n-3)+…+f(1)
所以f(n)=2*f(n-1)
4.我们可以用2*1的小矩形横着或者竖着去覆盖更大的矩形。请问用n个2*1的小矩形无重叠地覆盖一个2*n的大矩形,总共有多少种方法?
同 题2
三、 动态规划:https://www.cnblogs.com/kubidemanong/p/11854724.html
1.0-1背包问题
假设我们有n件物品,分别编号为1, 2…n。其中编号为i的物品价值为vi,它的重量为wi。为了简化问题,假定价值和重量都是整数值。现在,假设我们有一个背包,它能够承载的重量是W。现在,我们希望往包里装这些物品,使得包里装的物品价值最大化,那么我们该如何来选择装的东西
定义一个函数c[i, w]表示到第i个元素为止,在限制总重量为w的情况下我们所能选择到的最优解。
import numpy as np
def solve(vlist,wlist,totalWeight,totalLength):
resArr = np.zeros((totalLength+1,totalWeight+1),dtype=np.int32)
for i in range(1,totalLength+1):
for j in range(1,totalWeight+1):
if wlist[i] <= j:
resArr[i,j] = max(resArr[i-1,j-wlist[i]]+vlist[i],resArr[i-1,j])
else:
resArr[i,j] = resArr[i-1,j]
return resArr[-1,-1]
if __name__ == '__main__':
v = [0,60,100,120]
w = [0,10,20,30]
weight = 50
n = 3
result = solve(v,w,weight,n)
print(result)
参考:https://blog.csdn.net/ningngmei4328/article/details/91356784
2. 最长上升子序列
给定一个无序的整数数组,找到其中最长上升子序列的长度。
示例:
输入: [10,9,2,5,3,7,101,18]
输出: 4
解释: 最长的上升子序列是 [2,3,7,101],它的长度是 4。
时间复杂度应该为 O(n2)
class Solution:
def lengthOfLIS(self, nums):
if not nums:
return 0
n, res = len(nums), 1 # 序列长度和初始化最长上升子序列长度
dp = [1]*n # 初始化 dp
for i in range(1, n):
for j in range(i):
if nums[i] > nums[j]:
dp[i] = max(dp[i], dp[j]+1) # 更新 dp
res = max(res, dp[i]) # 更新最长上升子序列长度
return res
test = Solution()
nums = [10,9,2,5,3,7,101,18]
test.lengthOfLIS(nums)
二分法求解时间复杂度降低到 O(n log n)
class Solution:
def lengthOfLIS(self, nums):
if not nums:
return 0
top = [] # 整体数组
for i in range(len(nums)):
# 二分查找插入数组
left, right = 0, len(top)-1 # 左右边界索引
while left <= right:
mid = (left+right)//2 # 左中位数
if top[mid][-1] < nums[i]:
left = mid+1
else:
right = mid-1
# 若 left 等于数组的个数,则需要添加新数组;否则,在 left 数组尾部添加新值
if left == len(top):
top.append([nums[i]])
else:
top[left].append(nums[i])
return len(top)
参考:https://blog.csdn.net/qq_36512295/article/details/100835261
四、贪心算法:https://blog.csdn.net/sweetseven_/article/details/95197131
1. 已知一些孩子和一些糖果,每个孩子有需求因子g,每个糖果有大小s,当某个糖果的大小s>=某个孩子的需求因子g时,代表该糖果可以满足该孩子,求使用这些糖果,最多能满足多少孩子(注意,某个孩子最多只能用1个糖果满足)
虽说贪心算法并不一定能达到最优,但在这种情况感觉如下这样算应该使最优解?????
class Solution:
def findContentChild(self,g,s):
g = sorted(g)
s = sorted(s)
child = 0
cookie = 0
while child < len(g) and cookie < len(s):
if g[child] <= s[cookie]:
child +=1
cookie+=1
return child
if __name__ =="__main__":
g = [5,10,2,9,15,9]
s = [6,1,20,3,8]
S = Solution()
result = S.findContentChild(g,s)
print(result)