Python Prep随想练习-Day5

Day5-part1

Partition Problem 分块问题

问题描述

这里想解决的问题是,比如我们有一串数字:{1,2,4,2,5,2,1,1},咱们能不能把这串数字,分成两串,并且这两个串的和相等。
比如说分割成{1,2,4,2}和{5,2,1,1},这两串的和相等都是9.
或者分割成{4,5}和{1,2,2,2,1,1},这两串的和都是9.
那么改用什么方法找到分割方法呢?

解题思路

如果把一串数字,分割成等和的两个子串,那么每个子串的和应该是总和的一半对吧!
那就相当于找几个数字,满足他们相加起来等于这个sum/2
这是不是就相当于是一个背包容量为sum/2的 0/1背包问题!
咱们只需要找出一串满足,数字和为sum/2,另外一串肯定和也为sum/2。就相当于已经完成了平分问题了!
但是咱们在这里再考虑一下:如果sum是一个奇数,那肯定不能平分

但是sum是偶数的话,就存在平分的可能了!

a=[1,2,4,2,5,2,1,1]
def get_partition(a):
	sum=0
	for i in range(len(a)):
		sum+=a[i]
	if sum%2!=0:    #判断是否是奇数
		return 0
	else:
		half=sum/2

1.创建dp数组
参照0/1背包问题创建一下dp数组,创建出一个二维数组。dp[ i ][ j ]意味着当前情况下,你的背包能容纳的最大价值。同时对数组的第一行进行一个初始化!
在这里插入图片描述
在这里插入图片描述

a=[1,2,4,2,5,2,1,1]
def get_partition(a):
	sum=0
	for i in range(len(a)):
		sum+=a[i]
	if sum%2!=0:    #判断是否是奇数
		return =0
	else:
		half=sum/2
	dp=[[0 for i in range(half+1)] for j in range(len(a))]
	for i in range(a[0],half+1):
		dp[0][i]=a[0]

2.确定递推公式

递推公式完全参考0/1背包问题
if j>=a[ i ] dp[ i ][ j ]=max(dp[ i-1 ][ j ], dp[ i-1 ][ j-a[ i ] ]+a[ i ])
if j<a[ i ] dp[ i ][ j ]=dp[ i-1 ][ j ]
分别代表着能否放得下a[ i ]这个物体

在这里插入图片描述
随后就一步步递推,直到找到目标的half吧!
在这里插入图片描述
用代码实现一下吧!

a=[1,2,4,2,5,2,1,1]
def get_partition(a):
	sum=0
	for i in range(len(a)):
		sum+=a[i]
	if sum%2!=0:    #判断是否是奇数
		return 0
	else:
		half=sum/2
	dp=[[0 for i in range(half+1)] for j in range(len(a))]
	for i in range(a[0],half+1):
		dp[0][i]=a[0]
	for i in range(1,len(a)):
		for j in range(0,half+1):
			if j<a[i]:
				dp[i][j]=dp[i-1][j]
			else:
				dp[i][j]=max(dp[i-1][j],dp[i-1][j-a[i]]+a[i])
	return dp[len(a)-1][half]==half

在本节pdf最后,介绍了另外一种通过布尔(bool)数组,True False值来表示的矩阵,来表示dp数组,其实这两个东西确实没差别,我们掌握一个就够了!

Day5-part2

两个问题,第一个是深度优先搜索,第二个是斐波那契数列问题的重述。
写这个的时候深度优先搜索我还没太搞懂,先开斐波那契数列问题的重述吧。

斐波那契问题重述

回忆一下,什么是斐波那契问题?我们之前是怎么处理这个问题的呢?
递归得到结果,或者是建立dp数组递归得到结果,希望你有印象哦!
在这里插入图片描述
那么,通过矩阵的方式我们是不是可以对Fn进行表示呢?
在这里插入图片描述
你看一下这个表达式,我们是不是把An求出来,Fn+1就求出来了!
但是具体应该怎么求呢,这个就要求助于我们线性代数的知识了,其实最开始我也不怎么会,看了看别人怎么做的,也算是哼哼哧哧写下来了。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
得到这个表达式的好处是什么呢?其实就是我们可以直接通过公式求得斐波那契数列的值了!这样做,时间复杂度和空间复杂度很低!!

def get_fib(n):
    return pow((1+5**0.5)/2,n)/(5**0.5)-pow((1-5**0.5)/2,n)/(5**0.5)
print(int(get_fib(10)))

深度优先搜索

Depth-First Search 深度优先搜索

问题描述

在这里插入图片描述
在曾经所学的图论那里,我们想解决怎么从’Me’到‘Ed’的最短距离。想一下我们之前是怎么解决这个问题的?
我们之前所使用的方法是:借助队列问题实现广度搜索!一层一层实现遍历寻找目标点。
在这里我们想通过深度搜索去搜索目标点。

深度搜索实现

深度搜索的实现是:针对每个点走到最深处,如果没有寻找到目标点,那就从下一个点走到最深处。
广度搜索能够寻找到最短路径深度搜索能够实现快速搜素
深度搜索可以通过递归方式,回溯实现。

在这里插入图片描述
上面是深度搜索的伪代码,说的是什么意思呢?

同样是利用了 S:已经考虑过的结点的集合 T:N叉树
如果cur节点没有在S中出现过,才对其考虑,如果出现过,就不用考虑了。
cur节点添加在树中,再对cur的子节点进行深度搜索。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

G = { 'A' : [ 'B', 'J', 'Me' ],
         'B' : [ 'A' ],
         'C' : [ 'D', 'P' ],
         'D' : [ 'C', 'O' ],
         'E' : [ 'F', 'J', 'K' ],
         'F' : [ 'E', 'M' ],
         'G' : [ 'K', 'S', 'Ed' ],
         'H' : [ 'O', 'U' ],
         'Me': [ 'A', 'I', 'N', 'V' ],
         'I' : [ 'Me', 'Q' ],
         'J' : [ 'A', 'E', 'L', 'Q', 'W' ],
         'K' : [ 'E', 'G' ],
         'L' : [ 'J', 'W' ],
         'M' : [ 'E', 'S', 'T' ],
         'N' : [ 'Me', 'V' ],
         'O' : [ 'H', 'D' ],
         'P' : [ 'C', 'U' ],
         'Q' : [ 'I', 'J', 'X', 'Y' ],
         'R' : [ 'Ed' ],
         'S' : [ 'G', 'M', 'Y', 'Z' ],
         'T' : [ 'M' ],
         'U' : [ 'H', 'P' ],
         'V' : [ 'Me', 'N' ],
         'W' : [ 'J', 'L' ],
         'X' : [ 'Q', 'Y' ],
         'Y' : [ 'Q', 'S', 'X', 'Z' ],
         'Ed': [ 'G', 'R', 'Z' ],
         'Z' : [ 'S', 'Y', 'Ed' ] }
class tree:
    class treenode:
        def __init__(self,val,child=[]):
            self.val=val
            self.children=[]
    def __init__(self):
        self.root=None
    def add(self,cur,parent):
        if parent==None:
            self.root=cur
        else:
            parent.children.append(cur)
s=[]
T=tree()
def DFS(G,cur,parent):
    if cur not in s:
        s.append(cur)
        node=tree.treenode(val=cur)
        T.add(node,parent)
        for v in G[cur]:
            DFS(G,v,node)
DFS(G,'Me',T.root)

为什么要这么写呢
首先需要对N叉树进行创建,他的树节点应该包括value和children两个部分。并且对add方法进行创建!
最后对伪代码形成Python代码就好啦。

结语

第五天也就是第二周的内容学完了!我的渊宝是最棒的!
希望你这周作业一点问题都没有,写的嘎嘎好嘎嘎快!

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值