• Data Structure and Algorithm


    • Advanced Search

      • Pruning

      • Bidirectional Breadth First Search

      • Heuristic search (A* Search)

        public class AStar
        {
            public final static int BAR = 1; // 障碍值
            public final static int PATH = 2; // 路径
            public final static int DIRECT_VALUE = 10; // 横竖移动代价
            public final static int OBLIQUE_VALUE = 14; // 斜移动代价
        
            Queue<Node> openList = new PriorityQueue<Node>(); // 优先队列(升序)
            List<Node> closeList = new ArrayList<Node>();
        
            /**
             * 开始算法
             */
            public void start(MapInfo mapInfo)
            {
                if(mapInfo==null) return;
                // clean
                openList.clear();
                closeList.clear();
                // 开始搜索
                openList.add(mapInfo.start);
                moveNodes(mapInfo);
            }
        
            /**
             * 移动当前结点
             */
            private void moveNodes(MapInfo mapInfo)
            {
                while (!openList.isEmpty())
                {
                    Node current = openList.poll();
                    closeList.add(current);
                    addNeighborNodeInOpen(mapInfo,current);
                    if (isCoordInClose(mapInfo.end.coord))
                    {
                        drawPath(mapInfo.maps, mapInfo.end);
                        break;
                    }
                }
            }
        
            /**
             * 在二维数组中绘制路径
             */
            private void drawPath(int[][] maps, Node end)
            {
                if(end==null||maps==null) return;
                System.out.println("总代价:" + end.G);
                while (end != null)
                {
                    Coord c = end.coord;
                    maps[c.y][c.x] = PATH;
                    end = end.parent;
                }
            }
        
            /**
             * 添加所有邻结点到open表
             */
            private void addNeighborNodeInOpen(MapInfo mapInfo,Node current)
            {
                int x = current.coord.x;
                int y = current.coord.y;
                // 左
                addNeighborNodeInOpen(mapInfo,current, x - 1, y, DIRECT_VALUE);
                // 上
                addNeighborNodeInOpen(mapInfo,current, x, y - 1, DIRECT_VALUE);
                // 右
                addNeighborNodeInOpen(mapInfo,current, x + 1, y, DIRECT_VALUE);
                // 下
                addNeighborNodeInOpen(mapInfo,current, x, y + 1, DIRECT_VALUE);
                // 左上
                addNeighborNodeInOpen(mapInfo,current, x - 1, y - 1, OBLIQUE_VALUE);
                // 右上
                addNeighborNodeInOpen(mapInfo,current, x + 1, y - 1, OBLIQUE_VALUE);
                // 右下
                addNeighborNodeInOpen(mapInfo,current, x + 1, y + 1, OBLIQUE_VALUE);
                // 左下
                addNeighborNodeInOpen(mapInfo,current, x - 1, y + 1, OBLIQUE_VALUE);
            }
        
            /**
             * 添加一个邻结点到open表
             */
            private void addNeighborNodeInOpen(MapInfo mapInfo,Node current, int x, int y, int value)
            {
                if (canAddNodeToOpen(mapInfo,x, y))
                {
                    Node end=mapInfo.end;
                    Coord coord = new Coord(x, y);
                    int G = current.G + value; // 计算邻结点的G值
                    Node child = findNodeInOpen(coord);
                    if (child == null)
                    {
                        int H=calcH(end.coord,coord); // 计算H值
                        if(isEndNode(end.coord,coord))
                        {
                            child=end;
                            child.parent=current;
                            child.G=G;
                            child.H=H;
                        }
                        else
                        {
                            child = new Node(coord, current, G, H);
                        }
                        openList.add(child);
                    }
                    else if (child.G > G)
                    {
                        child.G = G;
                        child.parent = current;
                        openList.add(child);
                    }
                }
            }
        
            /**
             * 从Open列表中查找结点
             */
            private Node findNodeInOpen(Coord coord)
            {
                if (coord == null || openList.isEmpty()) return null;
                for (Node node : openList)
                {
                    if (node.coord.equals(coord))
                    {
                        return node;
                    }
                }
                return null;
            }
        
        
            /**
             * 计算H的估值:“曼哈顿”法,坐标分别取差值相加
             */
            private int calcH(Coord end,Coord coord)
            {
                return Math.abs(end.x - coord.x)
                        + Math.abs(end.y - coord.y);
            }
        
            /**
             * 判断结点是否是最终结点
             */
            private boolean isEndNode(Coord end,Coord coord)
            {
                return coord != null && end.equals(coord);
            }
        
            /**
             * 判断结点能否放入Open列表
             */
            private boolean canAddNodeToOpen(MapInfo mapInfo,int x, int y)
            {
                // 是否在地图中
                if (x < 0 || x >= mapInfo.width || y < 0 || y >= mapInfo.hight) return false;
                // 判断是否是不可通过的结点
                if (mapInfo.maps[y][x] == BAR) return false;
                // 判断结点是否存在close表
                if (isCoordInClose(x, y)) return false;
        
                return true;
            }
        
            /**
             * 判断坐标是否在close表中
             */
            private boolean isCoordInClose(Coord coord)
            {
                return coord!=null&&isCoordInClose(coord.x, coord.y);
            }
        
            /**
             * 判断坐标是否在close表中
             */
            private boolean isCoordInClose(int x, int y)
            {
                if (closeList.isEmpty()) return false;
                for (Node node : closeList)
                {
                    if (node.coord.x == x && node.coord.y == y)
                    {
                        return true;
                    }
                }
                return false;
            }
        }
        
    • 36. Valid Sudoku

      Determine if a 9 x 9 Sudoku board is valid. Only the filled cells need to be validated according to the following rules:

      1. Each row must contain the digits 1-9 without repetition.
      2. Each column must contain the digits 1-9 without repetition.
      3. Each of the nine 3 x 3 sub-boxes of the grid must contain the digits 1-9 without repetition.

      Note:

      • A Sudoku board (partially filled) could be valid but is not necessarily solvable.
      • Only the filled cells need to be validated according to the mentioned rules.
      Input: board = 
      [["5","3",".",".","7",".",".",".","."]
      ,["6",".",".","1","9","5",".",".","."]
      ,[".","9","8",".",".",".",".","6","."]
      ,["8",".",".",".","6",".",".",".","3"]
      ,["4",".",".","8",".","3",".",".","1"]
      ,["7",".",".",".","2",".",".",".","6"]
      ,[".","6",".",".",".",".","2","8","."]
      ,[".",".",".","4","1","9",".",".","5"]
      ,[".",".",".",".","8",".",".","7","9"]]
      Output: true
      

      Example 2:

      Input: board = 
      [["8","3",".",".","7",".",".",".","."]
      ,["6",".",".","1","9","5",".",".","."]
      ,[".","9","8",".",".",".",".","6","."]
      ,["8",".",".",".","6",".",".",".","3"]
      ,["4",".",".","8",".","3",".",".","1"]
      ,["7",".",".",".","2",".",".",".","6"]
      ,[".","6",".",".",".",".","2","8","."]
      ,[".",".",".","4","1","9",".",".","5"]
      ,[".",".",".",".","8",".",".","7","9"]]
      Output: false
      Explanation: Same as Example 1, except with the 5 in the top left corner being modified to 8. Since there are two 8's in the top left 3x3 sub-box, it is invalid.
      

      Constraints:

      • board.length == 9
      • board[i].length == 9
      • board[i][j] is a digit or '.'.
      class Solution {
          public boolean isValidSudoku(char[][] board) {
              boolean[][] rows = new boolean[9][9];
              boolean[][] cols = new boolean[9][9];
              boolean[][] blocks = new boolean[9][9];
              for (int i = 0; i < 9; i++) {
                  for (int j = 0; j < 9; j++) {
                      if (board[i][j] == '.') continue;
                      if (rows[i][board[i][j] - '1']) return false;
                      if (cols[j][board[i][j] - '1']) return false;
                      int block = i/3 * 3 + j/3;
                      if (blocks[block][board[i][j] - '1']) return false;
                      rows[i][board[i][j] - '1'] = true;
                      cols[j][board[i][j] - '1'] = true;
                      blocks[block][board[i][j] - '1'] = true;
                  }
              }
              return true;
          }
      }
      
    • 37. Sudoku Solver

      Write a program to solve a Sudoku puzzle by filling the empty cells.

      A sudoku solution must satisfy all of the following rules:

      1. Each of the digits 1-9 must occur exactly once in each row.
      2. Each of the digits 1-9 must occur exactly once in each column.
      3. Each of the digits 1-9 must occur exactly once in each of the 9 3x3 sub-boxes of the grid.

      The '.' character indicates empty cells.

      Input: board = [["5","3",".",".","7",".",".",".","."],["6",".",".","1","9","5",".",".","."],[".","9","8",".",".",".",".","6","."],["8",".",".",".","6",".",".",".","3"],["4",".",".","8",".","3",".",".","1"],["7",".",".",".","2",".",".",".","6"],[".","6",".",".",".",".","2","8","."],[".",".",".","4","1","9",".",".","5"],[".",".",".",".","8",".",".","7","9"]]
      Output: [["5","3","4","6","7","8","9","1","2"],["6","7","2","1","9","5","3","4","8"],["1","9","8","3","4","2","5","6","7"],["8","5","9","7","6","1","4","2","3"],["4","2","6","8","5","3","7","9","1"],["7","1","3","9","2","4","8","5","6"],["9","6","1","5","3","7","2","8","4"],["2","8","7","4","1","9","6","3","5"],["3","4","5","2","8","6","1","7","9"]]
      Explanation: The input board is shown above and the only valid solution is shown below:
      

      Constraints:

      • board.length == 9
      • board[i].length == 9
      • board[i][j] is a digit or '.'.
      • It is guaranteed that the input board has only one solution.
      class Solution {
          boolean[][] rows = new boolean[9][9];
          boolean[][] cols = new boolean[9][9];
          boolean[][] blocks = new boolean[9][9];
          char[] nums = {'1','2','3','4','5','6','7','8','9'};
          char[][] board;
          public void solveSudoku(char[][] board) {
              this.board = board;
              for (int i = 0; i < 9; i++) {
                  for (int j = 0; j < 9; j++) {
                      if (board[i][j] == '.') continue;
                      rows[i][board[i][j] - '1'] = true;
                      cols[j][board[i][j] - '1'] = true;
                      blocks[i/3 * 3 + j/3][board[i][j] - '1'] = true;
                  }
              }
              dfs(0, 0);
          }
      
          private boolean dfs(int i, int j) {
              if (j == 9){
                  i++;
                  j = 0;
                  if (i == 9) return true;
              }
              if (board[i][j] != '.') {
                  return dfs(i, j + 1);
              }
              for (char num : nums) {
                  if (rows[i][num - '1'] || cols[j][num - '1'] || blocks[i/3 * 3 + j/3][num - '1']) {
                      continue;
                  }
                  board[i][j] = num;
                  rows[i][num - '1'] = true;
                  cols[j][num - '1'] = true;
                  blocks[i/3 * 3 + j/3][num - '1'] = true;
                  if (dfs(i, j + 1)) return true;
                  rows[i][num - '1'] = false;
                  cols[j][num - '1'] = false;
                  blocks[i/3 * 3 + j/3][num - '1'] = false;
                  board[i][j] = '.';
              }
              return false;
          }
      }
      
    • 1091. Shortest Path in Binary Matrix

      Given an n x n binary matrix grid, return the length of the shortest clear path in the matrix. If there is no clear path, return -1.

      A clear path in a binary matrix is a path from the top-left cell (i.e., (0, 0)) to the bottom-right cell (i.e., (n - 1, n - 1)) such that:

      • All the visited cells of the path are 0.
      • All the adjacent cells of the path are 8-directionally connected (i.e., they are different and they share an edge or a corner).

      The length of a clear path is the number of visited cells of this path.

      Example 1:

      img

      Input: grid = [[0,1],[1,0]]
      Output: 2
      

      Example 2:

      img

      Input: grid = [[0,0,0],[1,1,0],[1,1,0]]
      Output: 4
      

      Example 3:

      Input: grid = [[1,0,0],[1,1,0],[1,1,0]]
      Output: -1
      

      Constraints:

      • n == grid.length
      • n == grid[i].length
      • 1 <= n <= 100
      • grid[i][j] is 0 or 1
      class Solution {
          int[][] dirs = {{0,1},{0,-1},{1,0},{-1,0},{1,1},{1,-1},{-1,1},{-1,-1}};
          public int shortestPathBinaryMatrix(int[][] grid) {
              if (grid[0][0] == 1) return -1;
              Deque<int[]> deque = new LinkedList<>();
              int m = grid.length, n = grid[0].length;
              deque.addLast(new int[]{0,0});
              grid[0][0] = 1;
              int res = 0;
              while (!deque.isEmpty()) {
                  int size = deque.size();
                  res++;
                  while (size-- > 0) {
                      int[] pos = deque.pollFirst();
                      int x = pos[0], y = pos[1];
                      if (x == m - 1 && y == n - 1) {
                          return res;
                      }
                      for (int[] dir : dirs) {
                          int i = x + dir[0], j = y + dir[1];
                          if (i >= 0 && i < grid.length && j >= 0 && j < grid[0].length && grid[i][j] == 0) {
                              deque.addLast(new int[]{i, j});
                              grid[i][j] = 1;
                          } 
                      }
                  }
              }
              return -1;
          }
      }
      
    • AVL Tree

    • Red Black Tree

      vs AVL Tree

    • Bit Operation

      <<: 0011=>0110
      >>: 0110=>0011
      | : 0011|1011=>1011
      & : 0011&1011=>0011
      ~ : 0011=>1100
      ^ : 0011^1011=>1000
      
      x ^ 0 = x
      x ^ (~x) = (~0) = 1s(all one)
      x ^ 1s = ~x
      x ^ x = 0
      

      apply

    • 191. Number of 1 Bits

      Write a function that takes an unsigned integer and returns the number of '1' bits it has (also known as the Hamming weight).

      Note:

      • Note that in some languages, such as Java, there is no unsigned integer type. In this case, the input will be given as a signed integer type. It should not affect your implementation, as the integer's internal binary representation is the same, whether it is signed or unsigned.
      • In Java, the compiler represents the signed integers using 2's complement notation. Therefore, in Example 3, the input represents the signed integer. -3.

      Example 1:

      Input: n = 00000000000000000000000000001011
      Output: 3
      Explanation: The input binary string 00000000000000000000000000001011 has a total of three '1' bits.
      

      Example 2:

      Input: n = 00000000000000000000000010000000
      Output: 1
      Explanation: The input binary string 00000000000000000000000010000000 has a total of one '1' bit.
      

      Example 3:

      Input: n = 11111111111111111111111111111101
      Output: 31
      Explanation: The input binary string 11111111111111111111111111111101 has a total of thirty one '1' bits.
      

      Constraints:

      • The input must be a binary string of length 32.
      public class Solution {
          public int hammingWeight(int n) {
              int res = 0;
              while (n != 0) {
                  res += (n&1) == 1 ? 1 : 0;
                  n = n >>> 1;
              }
              return res;
          }
      }
      
    • 231. Power of Two

      Given an integer n, return true if it is a power of two. Otherwise, return false.

      An integer n is a power of two, if there exists an integer x such that n == 2x.

      Example 1:

      Input: n = 1
      Output: true
      Explanation: 20 = 1
      

      Example 2:

      Input: n = 16
      Output: true
      Explanation: 24 = 16
      

      Example 3:

      Input: n = 3
      Output: false
      

      Example 4:

      Input: n = 4
      Output: true
      

      Example 5:

      Input: n = 5
      Output: false
      

      Constraints:

      • -231 <= n <= 231 - 1
      class Solution {
          public boolean isPowerOfTwo(int n) {
              return n > 0 && (n & (n - 1)) == 0;
          }
      }
      
    • 190. Reverse Bits

      Reverse bits of a given 32 bits unsigned integer.

      Note:

      • Note that in some languages such as Java, there is no unsigned integer type. In this case, both input and output will be given as a signed integer type. They should not affect your implementation, as the integer's internal binary representation is the same, whether it is signed or unsigned.
      • In Java, the compiler represents the signed integers using 2's complement notation. Therefore, in Example 2 above, the input represents the signed integer -3 and the output represents the signed integer -1073741825.

      Follow up:

      If this function is called many times, how would you optimize it?

      Example 1:

      Input: n = 00000010100101000001111010011100
      Output:    964176192 (00111001011110000010100101000000)
      Explanation: The input binary string 00000010100101000001111010011100 represents the unsigned integer 43261596, so return 964176192 which its binary representation is 00111001011110000010100101000000.
      

      Example 2:

      Input: n = 11111111111111111111111111111101
      Output:   3221225471 (10111111111111111111111111111111)
      Explanation: The input binary string 11111111111111111111111111111101 represents the unsigned integer 4294967293, so return 3221225471 which its binary representation is 10111111111111111111111111111111.
      

      Constraints:

      • The input must be a binary string of length 32
      public class Solution {
          // you need treat n as an unsigned value
          public int reverseBits(int n) {
              int res = 0;
              for (int i = 0; i < 32; i++) {
                  res <<= 1;
                  res += n & 1;
                  n >>>= 1;
              }
              return res;
          }
      }
      
    • 338. Counting Bits

      Given an integer num, return an array of the number of 1's in the binary representation of every number in the range [0, num].

      Example 1:

      Input: num = 2
      Output: [0,1,1]
      Explanation:
      0 --> 0
      1 --> 1
      2 --> 10
      

      Example 2:

      Input: num = 5
      Output: [0,1,1,2,1,2]
      Explanation:
      0 --> 0
      1 --> 1
      2 --> 10
      3 --> 11
      4 --> 100
      5 --> 101
      

      Constraints:

      • 0 <= num <= 105
      // stupid count
      class Solution {
          public int[] countBits(int num) {
              int[] res = new int[num + 1];
              for (int i = 1; i <= num; i++) {
                  res[i] = countBit(i);
              }
              return res;
          }
      
          private int countBit(int num) {
              if (num == 0) return 0;
              return 1 + countBit(num & (num - 1));
          }
      }
      
      // DP
      class Solution {
          public int[] countBits(int num) {
              int[] bits = new int[num + 1];
              for (int i = 1; i <= num; i++) {
                  bits[i] = bits[i >> 1] + (i & 1);
              }
              return bits;
          }
      }
      
  • 相关阅读:
    Meet Hadoop
    C++常用函数
    Summary
    获得小黄衫感想
    课程作业(八)
    课程作业(七)
    课程作业(六)
    课程作业(五)
    课程作业(四)
    课程作业(三)
  • 原文地址:https://www.cnblogs.com/peng8098/p/algorithm12.html
Copyright © 2020-2023  润新知