算法学习(三)

在经历的期中考试和一个快乐五一之后,还是要开始干活了。

这次学习主要是与简单搜索技术相关的总结。

(一).递归与全排列

下面是有关全排列的两个问题。

1.打印从n个数中任意m个数的全排列(这里以1~9的全排列为例)

这个题目,书上给出了两种方法:

第一种方法是用暴力法遍历,因为全排列中不存在重复序列,直接用暴力法循环遍历9次即可,当然,这个方法过于笨拙,但简单有效。

第二种方法则是使用递归,第一层递归是有关9个序列的,每次改变第一个数,这样每个序列就是不同的,再然后在第一层递归后,进行第二层递归,现在不看第一个数,把第二个数当成第一个数,重复上述操作,依次类推即可。下面是代码的复现:

这个问题实质上与求字典序类似。

2.打印n个数中任意m个数的组合

要注意,这个问题和第一个问题是有区别的,因为排列是有序的,组合是无序的,所以应该对重复元素去重是这个问题的关键。当然,这个题目也可以根据set容器的去重特性得到解决。这里我们使用另外一种思路:即把每个子集对应一个二进制数,则k个元素的集合,它对应二进制数中就有k个1。这个问题就转化为查找1的个数为k的二进制数即可。2^k(子集数) = 2^(k-1 )+2^(k-2)...+2^0+1(对应二进制数的个数)。而查找一个位串中k的个数,在离散数学中,我们学到过这个方法:可以使用按位与,即kk = kk&(kk-1),它只需要执行1的个数次这个操作即可。

(二).BFS(Breath-First Search,广度优先搜索)

用书上的一个比喻来解释BFS:一群老鼠走迷宫,假定老鼠无限多,每个路口派出老鼠探索所有没有走过的路,如果碰壁或者走到其他老鼠走过的路,就停下。显然,所有的道路都会被走到,那么这个问题就一定可以得到解决。所有该方法具有可行性。BFS可以看成是并行计算的模拟,通常用队列这种数据结构来实现BFS。下面用BFS来解决典型的状态图搜索——八数码问题。问题描述如下:(盗图,嘿嘿)

八数码问题从初始状态出发,每次转移都逐渐逼近目标,是从近到远的扩散过程。BFS比较适合运用于最短路径问题。这个问题理解起来很容易,但是会有一个问题:这样搜索下去,其实有很多路径是重复了的,这加大了不必要的计算成本。因此,八数码问题的关键在于去重。这里我们使用康托展开去重。康托展开简单来讲就是一个全排列所对应的字典序。此外,康托展开也是一个数组到一个数的映射,因此也是可用于hash,用于空间压缩。比如在保存一个序列,我们可能需要开一个数组,如果能够把它映射成一个自然数, 则只需要保存一个整数,大大压缩空间。比如八数码问题。

下面是这个问题的解决方案。

当然,就这个问题而言,仅有9! = 36288种情况,但是对于情况更为复杂的棋盘的问题,这种方法显然是不够的。所以这种BFS+Cantor的算法是存在着一定的局限性的。

当然,对于这个题可以使用双向BFS,即从目标状态和初始状态分别使用BFS,如果出现交集则问题有解。

(三).DFS(Depth-First Search,深度优先搜索)

用一个形象的说法解释DFS,就是一只老鼠走迷宫,一直走到不能继续往下走为止,走过的位置不在走,不能走时则回退一步,再换个方向走。这样每个路口可以视作几乎没有重复访问。DFS代码通常比BFS更为简单,用于求解可行解较为合适,BFS可用来求解最优解(如最短路径问题)。DFS常用递归来实现。

(四).回溯和剪枝

在使用DFS算法时,经常会遇到不符合要求的递归,在某一个条件不成立时,就应该立刻停止递归,以免增大不必要的计算,再然后返回到上一个状态,这个过程就是回溯。而判断递归是否符合要求,则可以使用剪枝函数。例如八皇后问题,要求皇后不能同行,同列,同对角线。如果递归到某一个后和另一个后同处一行,一列或者对角线时,递归就不必往下进行。剪枝函数可以对此进行判断,如:设定左上角为(0,0),已放好的皇后为(i,j),新后的坐标为(m,n),则:

比如两后不能同对角:所以|i-m| ≠ |j-n|。

 

 

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Python算法学习是指掌握使用Python语言来解决各种问题的方法和技巧。在学习过程中,有几个重要的方面需要注意。 首先,了解基本的算法概念是必不可少的。例如,了解常见的排序算法(如冒泡排序、快速排序)和查找算法(如二分查找)等。这有助于我们理解算法的原理和思想。 其次,学习Python中的内置数据结构和函数,如列表、字典和字符串等。熟悉这些数据结构和函数的使用方法,可以帮助我们更好地解决问题,并编写出高效的算法。 第,了解常用的算法设计技巧。例如,贪心算法、动态规划和分治法等。这些算法设计技巧可以应用于不同类型的问题,帮助我们找到解决问题的最佳方法。 第四,编写和调试算法代码是学习过程中的关键步骤。我们可以通过编写小型的算法程序来练习和巩固所学的知识。同时,调试是解决代码错误和优化算法的重要环节,需要耐心和细心。 最后,不断练习和实践是提高算法能力的关键。我们可以通过刷题、参加编程比赛和项目实践等方式来提高自己的算法水平。与其他程序员交流和分享经验也是相互学习的好机会。 总之,Python算法学习是一个渐进的过程,需要不断学习、实践和提高。通过合理的学习方法和坚持不懈的努力,我们可以不断提高自己的算法能力,并运用它来解决实际问题。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值