Skip to content

Latest commit

 

History

History
 
 

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 

README.md

学习笔记 04

深度优先搜索和广度优先搜索

遍历搜索:在树(图/状态集)中寻找特定节点

  • 每个节点都要访问一次

  • 每个节点仅仅要访问一次

  • 对于节点的访问顺序不限

    • 深度优先:对每一个可能的分支路径深入到不能再深入为止,而且每个结点只能访问一次。要特别注意的是,二叉树的深度优先遍历比较特殊,可以细分为先序遍历、中序遍历、后序遍历。

      public List<List<Integer>> levelOrder(TreeNode root) {
          List<List<Integer>> allResults = new ArrayList<>();
          if(root==null){
              return allResults;
          }
          travel(root,0,allResults);
          return allResults;
      }
      private void travel(TreeNode root,int level,List<List<Integer>> results){
          if(results.size()==level){
              results.add(new ArrayList<>());
          }
          results.get(level).add(root.val);
          if(root.left!=null){
              travel(root.left,level+1,results);
          }
          if(root.right!=null){
              travel(root.right,level+1,results);
          }
      }
    • 广度优先:又叫层次遍历,从上往下对每一层依次访问,在每一层中,从左往右(也可以从右往左)访问结点,访问完一层就进入下一层,直到没有结点可以访问为止。 

      //Java
      public class TreeNode {
          int val;
          TreeNode left;
          TreeNode right;
      
          TreeNode(int x) {
              val = x;
          }
      }
      
      public List<List<Integer>> levelOrder(TreeNode root) {
          List<List<Integer>> allResults = new ArrayList<>();
          if (root == null) {
              return allResults;
          }
          Queue<TreeNode> nodes = new LinkedList<>();
          nodes.add(root);
          while (!nodes.isEmpty()) {
              int size = nodes.size();
              List<Integer> results = new ArrayList<>();
              for (int i = 0; i < size; i++) {
                  TreeNode node = nodes.poll();
                  results.add(node.val);
                  if (node.left != null) {
                      nodes.add(node.left);
                  }
                  if (node.right != null) {
                      nodes.add(node.right);
                  }
              }
              allResults.add(results);
          }
          return allResults;
      }

image-20201224135941344

贪心算法 Greedy

贪心算法是一种在每一步选择中都采取在当前状态下最好或最优(即最有利)的选择,从而希望导致结果是全局最好或最优的算法。 贪心算法与动态规划的不同在于它对每个子问题的解决方案都做出选择,不能回退。动态规划则会保存以前的运算结果,并根据以前的结果对当前进行选择,有回退功能。

贪心法可以解决一些最优化问题,如:求图中的最小生成树、求哈夫曼编码等。然而对于工程和生活中的问题,贪心法一般不能得到我们所要求的答案。 一旦一个问题可以通过贪心法来解决,那么贪心法一般是解决这个问题的最好办法。由于贪心法的高效性以及其所求得的答案比较接近最优结果,贪心法也可以用作辅助算法或者直接解决一些要求结果不特别精确的问题。

适用贪心算法的场景:问题能够分解成子问题来解决,子问题的最优解能递推到最终问题的最优解。这种子问题最优解称为最优子结构。

二分查找

二分查找的前提

  1. 目标函数单调性(单调递增或者递减)
  2. 存在上下界(bounded)
  3. 能够通过索引访问(index accessible)
// Java
public int binarySearch(int[] array, int target) {
    int left = 0, right = array.length - 1, mid;
    while (left <= right) {
        mid = (right - left) / 2 + left;

        if (array[mid] == target) {
            return mid;
        } else if (array[mid] > target) {
            right = mid - 1;
        } else {
            left = mid + 1;
        }
    }

    return -1;
}