几类问题:

  1. 分治算法(递归,思路就是看这个问题能不能分解成几个规模较小的问题,然后由这几个规模较小的问题组合出原始问题的解。 另外一个思路就是数学归纳法,由f(n-1)推f(n)。

简单总结一下,整体思路就是假设n-1规模的问题已经解决了,然后去推规模n的问题)

  1. 动态规划(填表)
  2. 数学问题(数组类等等)
  3. 字符串
  4. 链表
  5. 树,矩阵(DFS, BFS,递归,迭代)

二叉树的DFS递归写法不用设visited数组,像图、矩阵之类DFS的递归写法需要visited数组,另外非递归写法都需要这个visited数组

  1. 双指针

 

 

几个常见思路:

 

分治(递归):假设这个问题已经解决了,然后从n-1推n (像 快排、汉诺塔、由树的前序中序遍历序列构造出原来的树等 都可以用分治)

 

动态规划:穷举1到n-1, 然后组合出 n 的解(像棋盘问题(从原点到(n,n)点有几种走法)等都可以用动态规划)

 

DFS:(深度优先,有子孩子就去访问子孩子)//像 全排列、图的遍历、二维数组的不规则遍历(孤岛问题) 都可以用DFS

递归写法:从根节点开始,分别DFS每个子节点。如果是图的话需要设置一个visited字典来记录当前节点是否被访问过。

示例:

DFS(根节点){

打印根节点

for(每个子节点){

DFS(子节点);

}

}

 

迭代写法:设置一个栈,一个visited字典。根节点入栈,然后取栈顶元素,遍历这个元素的子节点,如果有子节点没有被访问过则该子节点入栈并且将该子节点标记为已访问(即visited[该子节点]=true),继续下一次循环,如果所有子节点都被访问过了,那么该元素出栈,进入下一次循环。

关键点:节点入栈,出栈条件是该节点的所有子节点都被访问过了,用二叉树来说就是左右节点。

 

Stack stack;

Map visited<Node*, bool> visited;

stack.push(root);

while(!stack.empty()) {

Node* top = stack.top();

 

for(每个子节点){

if(!visited[子节点]){

stack.push(子节点);

break;

}

}

 

if( 子节点都被访问过 或者 子节点 是空)

   出栈

}

}

 

BFS:(广度优先,一层一层访问,一个节点的所有子孩子都访问完了再去访问下一级)

需要两个数组,一个数组记录当前层级的节点,另一个数组记录该层级的下一层级的节点(当然也可以用队列,原理一样,不过两个数组更容易理解)。如果是图的话也需要一个visited字典来记录当前节点是否被访问过。

 

Array *currentLevel = {root};

 

while(currentLevel.count != 0) {

Array *nextLevel = nil;

for(node in currentLevel) {

访问node

node的子节点放入nextLevel数组。

}

 

currentLevel = nextLevel;

 

}

 

posted on 2018-07-29 17:30  ximenchuixie  阅读(119)  评论(0编辑  收藏  举报