五大算法的理解

1.回溯算法:来一个简单直白的伪码

 path;

 for e in list{
    // 前进一步
    path.push(e);
    {...} // 探索
    // 再退回去
    paht.pop(e);
}

  

  可以看到,回溯算法和stack有很深的关系,典型的回溯算法如打印所有根节点到叶子节点的路径。

public void dfs(TreeNode node,Stack<Node> path){
    // 找到一条路
   if(node==null){
       print(path);
       return;
   }
   path.push(node.left);
   dfs(node.left,path);
   path.pop(node.left);
   // 更新自己所在位置和走过的路径
  path.push(node.right,path);
   dfs(node.right,path);    
}

  还有经典的n皇后问题,回溯算法简单,但是其时间复杂度约是pow(M,n)级别, 爆炸型增长,当n很大时,往往会超时,或者栈溢出。这是在回溯算法中,没有充分使用图中的其他信息,或者按照一定的策略去搜索,比如迪杰特斯拉算法。

for 选择 in 选择列表:
    # 做选择
    将该选择从选择列表移除
    路径.add(选择)
    backtrack(路径, 选择列表)
    # 撤销选择
    路径.remove(选择)
    将该选择再加入选择列表

  

2.动态规划算法:也叫查表法,其实就是找到从小规模到大规模的递推公式。典型的是背包问题,看一下动态规划的简单例子:计算斐波那契数列

f(n) = f(n-1) +f(n-2)
f(5) = f(4)  + f(3) ;

  

 动态规划可以简单理解为求递推公式。在具体的程序求解问题中,可以使用函数递归,也可以使用数组迭代,优先使用迭代,这个一般会更快,并且能够处理重叠子问题。

3.分治算法:分治的思想在生活中随处可见,都是将大问题划分为小问题,比如全国行政区的划分,分子的组成等。分治的核心就是划分子问题,使划分的各个子部分不会互  相影响。 典型的如快速排序。

QUICKSORT(A, p, r)  
 if p < r  //仅当区间长度大于1才开始排序
    then q ← PARTITION(A, p, r)  //选取pivot主元
         QUICKSORT(A, p, q - 1)  //对左子序列排序
         QUICKSORT(A, q + 1, r)  //对右子序列排序
PARTITION(A, p, r)  
  x ← A[r]  
  i ← p - 1  
  for j ← p to r - 1  
       do if A[j] ≤ x  
             then i ← i + 1  
                  exchange A[i] ←→ A[j]  
 // 这个就很奇怪
  exchange A[i + 1] ←→ A[r]  
  return i + 1
// 这个总是在pivot预留一个,用于交换,节省空间。
// 快速排序算法的思想非常简单,但是就是PARTITION方法不好理解
// do--if就是if 
//思想: 使用j作为指针,去遍历所有的元素,然后将小于pivot的元素放在左边,但是为了//保证不占用空间,pivot也要又移。

参考书籍:《算法设计》

     《计算机程序的构造和解释》

      快速排序算法

     快速排序的非递归实现

      归并排序算法图解

     回溯算法理解

     动态规划算法详解

     背包问题

posted @ 2018-10-06 22:17  懂得了才能做一些改变  阅读(277)  评论(0编辑  收藏  举报