Showing posts with label Thinking. Show all posts
Showing posts with label Thinking. Show all posts

LeetCode 1036 - Escape a Large Maze


https://xingxingpark.com/Leetcode-1036-Escape-a-Large-Maze/
In a 1 million by 1 million grid, the coordinates of each grid square are (x, y) with 0 <= x, y < 10^6.
We start at the source square and want to reach the target square. Each move, we can walk to a 4-directionally adjacent square in the grid that isn’t in the given list of blocked squares.
Return true if and only if it is possible to reach the target square through a sequence of moves.
Example 1:
Input: blocked = [[0,1],[1,0]], source = [0,0], target = [0,2]
Output: false
Explanation: The target square is inaccessible starting from the source square, because we can’t walk outside the grid.
Example 2:
Input: blocked = [], source = [0,0], target = [999999,999999]
Output: true
Explanation: Because there are no blocked cells, it’s possible to reach the target square.
Note:

  1. 0 <= blocked.length <= 200
  2. blocked[i].length == 2
  3. 0 <= blocked[i][j] < 10^6
  4. source.length == target.length == 2
  5. 0 <= source[i][j], target[i][j] < 10^6
  6. source != target

https://blog.baozitraining.org/2019/05/leetcode-solution-1036-escape-large-maze.html
At first, I am puzzled why this problem would be a hard one. It seems simply applying a BFS would get the answer. So here we go.
  

Brute force, simple BFS

Of course it will hit memory limit because I am allocating a 2-dimensional visited array. Assume boolean is 8 bit -> 1B, 1 Million * 1 Million = 1TB, OMG, immediately using a set instead.

P.S. fun fact, you can use this method to test how much memory leetcode allocate to this problem, you can use binary search and memory is around 300MB

However, this would start hitting Time Limit Exception. Now I begin to notice a few constrains, e.g., the block size is only 200 while the grid is 1M*1M. Simply going from source to target worst case would cause a timeout.

Next thought would be does it help if we sort the block array? While we are doing the BFS, if the block is already larger/smaller than the max/min of the block, we can early stop. However, this won't help if we simply place a block near the target. Also, this would be a nightmare to implement. 

Check block loops on source and target

Following the two hints, it would be natural to come up with this idea. Given such huge contrast between the block size (0,200) and the grid size (1M, 1M), all we need to do is to check if there is any loops built by block on source and target b/c if there is a loop, we cannot explore outside of the loop. However, notice if target and source are in the same loop, then we are fine.

There are two ways to early stop this loop checking. One way is to count the BFS steps, the other way is to follow the hints, given 200 blocks, what's the max area it can cover. Given the length 200, Fig 2 in the below graph can result in the largest area. Therefore, we can early terminate the BFS search once we covered more than 19900 blocks. (We can relax this a bit to 20000, doesn't matter)
  • Fig 1 area = 100 * 100 = 10000
  • Fig 2 area = 1 + 2 + 3 + ... + 199 = (1+199)*199/2 = 19900
  • Fig 3 area = 1 * 200 = 200
  • Fig 4 area = 790 (2*Pi*R = 100, thus R = 15.92, Pi * R^2 = 790 )


X. DFS
https://leetcode.com/problems/escape-a-large-maze/discuss/282889/My-Java-DFS-Solution-with-Some-Thoughts-(Triangle-v.s.-14-Circle-in-Pixels)
Note it states blocks.length <= 200. We can make use of it.
Find as many sqaures as possible from source and target individually. If both can reach more than a specified amount of squares (i.e. the largest closed area the block squares and the grid borders can form), it means they can both go beyond the blocks.
Code Updated (as pointed out by @andrew18):
---
You ignore the case that it can move directly from the source to target below the limit of number of moves. Consider the following case:
blocked: [[0,2],[1,0],[1,1]]
source: [0,0]; target: [0,1]
But how can we get the largest closed area? The largest one I can come up with is a 1/4 circle with its arc 200 in length. Then the area is 12,732 roughly.
However, we are facing a pixel problem. It's not a continous line, but is composed by pixels, which don't need to be adjacent to form a line (i.e. two pixels are positioned diagonally). In this case, the circle might not be the largest.
We can come up with another example: the 200-long line in exactly 45 degree which forms a triangle. The line is made up with 200 pixels but actually is 200 * sqrt(2) in length. The square is roughly (200 * sqrt(2)) * (200 * sqrt(2) / 2) / 2 = 20000. The number of accurate pixels is 1 + 2 + ... + 200 = 20100 (we can reduce 200 because they are blocks themselves XD. Then it's actuall 19900).
Let's see the 1/4 circle again. When we are trying to make a circle, we actually make some diagonally positioned pixels become adjacent. This will reduce the area at every step. So the triangle should be the larger one when the pixel count is fixed.
The following image shows the two examples when pixel count of the border is 13.


image
    final int MAX_VISIT = 20000;
 
    public boolean isEscapePossible(int[][] blocked, int[] source, int[] target) {
        Set<String> blockedSet = new HashSet<>();
        for (int[] point : blocked) {
            blockedSet.add(getKey(point));
        }
        return canVisit(blockedSet, source, getKey(target)) && canVisit(blockedSet, target, getKey(source));
    }
    
    String getKey(int[] point) {
        return point[0] + "," + point[1];
    }
    
    boolean canVisit(Set<String> blocked, int[] source, String targetKey) {
        Set<String> visited = new HashSet<>();
        dfs(blocked, source, targetKey, visited);
        return visited.size() >= MAX_VISIT || visited.contains(targetKey);
    }
    
    void dfs(Set<String> blocked, int[] curr, String targetKey, Set<String> visited) {
        int i = curr[0], j = curr[1];
        if (i < 0 || j < 0 || i >= 1e6 || j >= 1e6) { return; }
        
        String key = getKey(curr);
        if (blocked.contains(key)) { return; }
        if (visited.size() >= MAX_VISIT || visited.contains(targetKey)) { return; }
        
        if (visited.contains(key)) { return; }
        visited.add(key);
        
        for (int[] next : new int[][] {{i-1 ,j}, {i+1, j}, {i, j-1}, {i, j+1}}) {
            dfs(blocked, next, targetKey, visited);
        }
    }
https://leetcode.com/problems/escape-a-large-maze/discuss/282849/Python-BFS-and-DFS-Maximum-Blocked-19900

DFS:

    def isEscapePossible(self, blocked, source, target):
        blocked = set(map(tuple, blocked))

        def dfs(x, y, target, seen):
            if not (0 <= x < 10**6 and 0 <= y < 10**6) or (x, y) in blocked or (x, y) in seen: return False
            seen.add((x, y))
            if len(seen) > 20000 or [x, y] == target: return True
            return dfs(x + 1, y, target, seen) or \
                dfs(x - 1, y, target, seen) or \
                dfs(x, y + 1, target, seen) or \
                dfs(x, y - 1, target, seen)
        return dfs(source[0], source[1], target, set()) and dfs(target[0], target[1], source, set())

Python, BFS:

    def isEscapePossible(self, blocked, source, target):
        blocked = {tuple(p) for p in blocked}

        def bfs(source, target):
            bfs, seen = [source], {tuple(source)}
            for x0, y0 in bfs:
                for i, j in [[0, 1], [1, 0], [-1, 0], [0, -1]]:
                    x, y = x0 + i, y0 + j
                    if 0 <= x < 10**6 and 0 <= y < 10**6 and (x, y) not in seen and (x, y) not in blocked:
                        if [x, y] == target: return True
                        bfs.append([x, y])
                        seen.add((x, y))
                if len(bfs) == 20000: return True
            return False
        return bfs(source, target) and bfs(target, source)

https://blog.baozitraining.org/2019/05/leetcode-solution-1036-escape-large-maze.html
题目给我们一个1百万乘1百万的迷宫,同时告诉你其中一些点是阻隔的,不能通过。问你是否有一条通路可以从点source连接到target
按照常规思路,我们首先想到的肯定是用DFS或者BFS的方法,从一个点开始,暴力搜索所有能到的点。但是,由于迷宫非常大,这样做的时间复杂度会达到O(10^12),你提交的解法会 TLE。
我们回头仔细看题目给我们的Note, 发现blocked的长度是有限制的,最多不超过200。这能给我们带来启发。首先,两个点之所以不能联通,一定是因为被blocked中的点分隔开了。那意味着blocked中的点能将迷宫分割成两个部分,每个部分分别包含sourcetarget中的一个点。而因为blocked的点数量不超过200,因此,它所能围城的面积也是有限制的。
我们可以将问题抽象成这样一个数学问题,在一个1000000 \* 1000000的矩形中,用一条长200的线,最多能围出多大的面积?这个问题可以用泛函的知识求解,这里不多做说明。但其实我们利用对称性可以知道,在任意一个角,围出一个弧长2001/4圆就是最大的面积,也就是4/pi \* 10000
知道了这个面积,我们只需要对sourcetarget分别做两次BFS。每次BFS,我们设定所搜的次数不超过我们求出的这个最大面积。如果在这些点中找到了targetsource,那自然说明有这样一条通路。否则:
  1. 如果我们发现BFS在我们设定的搜索次数内,已经完成,那么说明source或者target处于被blocked点和迷宫边界构成的一个封闭区间内,不存在通路。
  2. 如果BFS在设定的搜索次数内没有完成,说明并没有这样一个封闭区间能包裹住source或者target,那它们两个点一定是能够连通的。
下图给出targetsource别阻隔时,可能的情况。(图片引子Discuss2017111303的帖子)
  1. 由于 block 列表的长度 m 最多只有 200,而网格却有 10^6 x 10^6。如果最终不能从起点到终点,则从起点终点出发能到达的格子数量不超过 m^2/2;如果起点和终点超过了这么多可达的格子,则一定能从起点到终点。(考虑极端情况,起点在角上,m 个点最多能封闭多少空间)
  2. 基于此,我们先从起点开始 BFS,如果过程中遇到了终点或者可达格子个数超过了 m^2/2 个,则返回 true;然后同理再从终点开始 BFS,二者均返回 true 则最终返回 true。

时间复杂度

  • 消耗的时间为 BFS 中的可达点数,最多为 O(m^2)

空间复杂度

  • BFS 队列需要 O(m^2) 的空间。



https://www.acwing.com/solution/LeetCode/content/1695/
在一个 10^6 x 10^6 的网格中,每个网格块的坐标为 (x, y),其中 0 <= x, y < 10^6
我们从源方格 source 开始出发,意图赶往目标方格 target。每次移动,我们都可以走到网格中在四个方向上相邻的方格,只要该方格不在给出的封锁列表 blocked 上。
只有在可以通过一系列的移动到达目标方格时才返回 true。否则,返回 false

样例

输入:blocked = [[0,1],[1,0]], source = [0,0], target = [0,2]
输出:false
解释:
从源方格无法到达目标方格,因为我们无法在网格中移动。
输入:blocked = [], source = [0,0], target = [999999,999999]
输出:true
解释:
因为没有方格被封锁,所以一定可以到达目标方格。




X. Video
Baozi Training Leetcode 1036 solution: Escape a Large Maze

LeetCode 1007 - Minimum Domino Rotations For Equal Row


https://leetcode.com/problems/minimum-domino-rotations-for-equal-row/
In a row of dominoes, A[i] and B[i] represent the top and bottom halves of the i-th domino.  (A domino is a tile with two numbers from 1 to 6 - one on each half of the tile.)
We may rotate the i-th domino, so that A[i] and B[i] swap values.
Return the minimum number of rotations so that all the values in A are the same, or all the values in B are the same.
If it cannot be done, return -1.

Example 1:
Input: A = [2,1,2,4,2,2], B = [5,2,6,2,3,2]
Output: 2
Explanation: 
The first figure represents the dominoes as given by A and B: before we do any rotations.
If we rotate the second and fourth dominoes, we can make every value in the top row equal to 2, as indicated by the second figure.
Example 2:
Input: A = [3,5,1,2,3], B = [3,6,3,3,4]
Output: -1
Explanation: 
In this case, it is not possible to rotate the dominoes to make one row of values equal. 
Note:
  1. 1 <= A[i], B[i] <= 6
  2. 2 <= A.length == B.length <= 20000

https://www.acwing.com/solution/LeetCode/content/1145/

http://www.noteanddata.com/leetcode-1007-Minimum-Domino-Rotations-For-Equal-Row-java-solution-note-2.html
  1. 有两行骰子, 每行个数一样多
  2. 然后定义一个换位操作,就是在某一个index, 把两行骰子在这个index上的位置互换
  3. 问, 最少经过多少次操作以后,可以让两行骰子里面的某一行的值都是一样的
  1. 无论怎么换位置,如果最后可以让某一行的数字完全一样,每个位置上只有两个可能,这个数要么是A的,要么是B的。 那么,对第0个数字来说,要么是A[0], 要么是B[0]。
  2. 那么,不管在那一行,后面的数字要么和A[0]相同, 要么和B[0]相同, 否则就不能达到效果。
  3. 所以,
    –遍历数组一次, 如果可以在A或者B里面在每个位置上都找到和A[0]相同的元素,那么就可以把某一行全部变成A[0]
    –再遍历数组一次, 如果可以在A或者B里面在每个位置上都找到和B[0]相同的元素,那么就可以把某一行全部变成B[0]
然后,在两次遍历的时候都分别计数,看看有几个一样的, 那么n-count就是需要换的个数。
public int minDominoRotations(int[] A, int[] B) {
    int n = A.length;
    for(int i = 0, a = 0, b = 0; i < n && (A[i] == A[0] || B[i] == A[0]); ++i) {
        if(A[i] == A[0]) a++;
        if(B[i] == A[0]) b++;
        if(i == n-1) return Math.min(n-a, n-b);
    }
    for(int i = 0, a = 0, b = 0; i < n && (A[i] == B[0] || B[i] == B[0]); ++i) {
        if(A[i] == B[0]) a++;
        if(B[i] == B[0]) b++;
        if(i == n-1) return Math.min(n-a, n-b);
    }
    return -1;
}

X. https://leetcode.com/problems/minimum-domino-rotations-for-equal-row/discuss/252266/C%2B%2B-check-A0-and-B0
We are as good as our very first domino :) So, we just need to check for A[0] (top) and B[0] (bot).
If we find a domino that does not have top or bot, then we exclude that number from consideration. We count how many times a number appear in the top or bottom of each domino and use these numbers to detect the minimum number of flips
int minDominoRotations(vector<int>& A, vector<int>& B) {
  auto top = A[0], bot = B[0], top1 = 0, bot1 = 0, top2 = 0, bot2 = 0;
  for (auto i = 0; i < A.size(); ++i) {
    if (A[i] != top && B[i] != top) top = 0;
    if (A[i] != bot && B[i] != bot) bot = 0;
    top1 += A[i] == top;
    bot1 += B[i] == top;
    top2 += A[i] == bot;
    bot2 += B[i] == bot;
  }
  return top || bot ? min(A.size() - max(top1, bot1), A.size() - max(top2, bot2)) : -1;
}

X. https://leetcode.com/problems/minimum-domino-rotations-for-equal-row/discuss/252633/Java-one-pass-counting-O(A-%2B-B)
  1. Count the frequency of each number in A and B, respectively;
  2. Count the frequency of A[i] if A[i] == B[i];
  3. If countA[i] + countB[i] - same[i] == A.length, we find a solution; otherwise, return -1;
  4. min(countA[i], countB[i]) - same[i] is the answer.
    public int minDominoRotations(int[] A, int[] B) {
        int[] countA = new int[7]; // countA[i] records the occurrence of i in A.
        int[] countB = new int[7]; // countB[i] records the occurrence of i in B.
        int[] same = new int[7]; // same[k] records the occurrence of k, where k == A[i] == B[i].
        for (int i = 0; i < A.length; ++i) {
            ++countA[A[i]];
            ++countB[B[i]];
            if (A[i] == B[i]) { ++same[A[i]]; }
        }
        for (int i = 1; i < 7; ++i) {
            if (countA[i] + countB[i] - same[i] >= A.length) {
                return Math.min(countA[i], countB[i]) - same[i];
            }
        }
        return -1;
    }

https://leetcode.com/problems/minimum-domino-rotations-for-equal-row/discuss/252242/JavaPython-Find-Intersection-of-Dominos

Solution 1:

Check all possibilities.
    def minDominoRotations(self, A, B):
        for x in range(1, 7):
            if all(x == a or x == b for a, b in zip(A, B)):
                return min(len(A) - A.count(x), len(B) - B.count(x))
        return -1

Solution 2

Try A[0] or B[0]
    public int minDominoRotations(int[] A, int[] B) {
        int n = A.length;
        for (int i = 0, a = 0, b = 0; i < n && (A[i] == A[0] || B[i] == A[0]); ++i) {
            if (A[i] != A[0]) a++;
            if (B[i] != A[0]) b++;
            if (i == n - 1) return Math.min(a, b);
        }
        for (int i = 0, a = 0, b = 0; i < n && (A[i] == B[0] || B[i] == B[0]); ++i) {
            if (A[i] != B[0]) a++;
            if (B[i] != B[0]) b++;
            if (i == n - 1) return Math.min(a, b);
        }
        return -1;
    }

Solution 3

Find intersection set s of {A[i], B[i]}
s.size = 0, no possible result.
s.size = 1, one and only one result.
s.size = 2, it means all dominos are [a,b] or [b,a], try either one.
s.size > 2, impossible.
    public int minDominoRotations(int[] A, int[] B) {
        HashSet<Integer> s = new HashSet<>(Arrays.asList(1, 2, 3, 4, 5, 6));
        int[] countA = new int[7], countB = new int[7];
        for (int i = 0; i < A.length; ++i) {
            s.retainAll(new HashSet<>(Arrays.asList(A[i], B[i])));
            countA[A[i]]++;
            countB[B[i]]++;
        }
        for (int i : s) return Math.min(A.length - countA[i], B.length - countB[i]);
        return -1;
    }

X.
因为 1 <= A[i], B[i] <= 6,所以如果能使得A或者B中所有元素的值一样,那么就只有12种情况,即A中元素或者B中元素全为1/2/3/4/5/6,依次判断这6种情况即可,如假设变换后A中元素全为1,从头遍历A与B,如果A[i] != 1 并且B[i] != 1表示无法使得A中元素全为1,继续判断2的情况;否则如果A[i] != 1 并且B[i] = 1,那么交换的次数加1;同理可求得B中元素也全为1的交换次数。遍历完这6种情况后,如果无法满足则返回-1,可以的话返回交换的最小值
https://zxi.mytechroad.com/blog/algorithms/array/1007-minimum-domino-rotations-for-equal-row/
  int minDominoRotations(vector<int>& A, vector<int>& B) {
    int ans = INT_MAX;
    for (int r = 1; r <= 6; ++r) {
      bool flag = true;
      int count_a = 0;
      int count_b = 0;
      for (int i = 0; i < A.size(); ++i) {
        if (A[i] != r && B[i] != r) {
          flag = false;
          break;
        }
        else if (A[i] == r && B[i] == r) continue;
        else if (A[i] == r) {
          ++count_a;
        } else if (B[i] == r) {
          ++count_b;
        }
      }
      if (flag) ans = min(ans, min(count_a, count_b));
    }
    return ans == INT_MAX ? -1 : ans;
  }

    int minDominoRotations(vector<int>& A, vector<int>& B) {
        vector<int> nums;
        int min=0;
        for(int i = 1; i <= 6; i++)
        {
            int changeA=0,changeB=0;
            for(int j = 0; j < A.size(); j++)
            {
                if(A[j] != i && B[j] !=i)
                {break;}
                if(A[j] == i && B[j] !=i)
                    changeB++;
                if(A[j] != i && B[j] ==i)
                    changeA++;
                if(j == A.size()-1)
                {
                    nums.push_back(i);
                    min = changeA<changeB?changeA:changeB;
                }
            }
        }
        if(nums.empty()) return -1;
        return min;
    }

X. https://blog.csdn.net/fuxuemingzhu/article/details/88379160
我们需要对这个题做分析:先把A,B两面的数字做一个统计,如果出现最多的点数<牌的个数,那么无论如何都无法翻转成功。如果出现最多的点数=牌的个数,那么这个时候需要保证每一个牌的都有且只有一面的点数是这个最多的点数。如果出现最多的点数>牌的个数,那么需要保证每个牌都至少有一面是这个数字,此时两面都是这个数字的话,就不用翻转。

所以:

如果两面相等都等于出现最多的数字target,不用翻转。

我们需要使用两个数字分别表示向该面翻转的次数。如果只有一面等于target,就把向另一面翻转的次数+1.

在任何时候,只要这个牌的正反面有一面不是出现最多的数字,那么一定返回-1.

我们最终只需要返回两个方向翻转的次数的最小值即可。

下面做一下讨论:为什么只用统计出现最多的数字就行,为什么出现次数第二多的次数一定没有机会?

1.如果出现最多的数字的次数<长度,无论第一第二都不行。
2.如果出现最多的次数=长度,这个时候第二多次数如果等于N,那么两者效果一样,如果第二多次数如果小于N,那么不可能。
3.如果出现最多的次数>N,这个时候一定会出现某些牌的正反面都是该最多的数字。此时第二多的数字没有机会。

总之,只需要判断出现最多的数字即可。

    def minDominoRotations(self, A, B):
        """
        :type A: List[int]
        :type B: List[int]
        :rtype: int
        """
        N = len(A)
        count = collections.Counter(A + B)
        if count.most_common(1)[0][1] < N:
            return -1
        target = count.most_common(1)[0][0]
        a_swap = 0
        b_swap = 0
        for i in range(N):
            if A[i] == B[i]:
                if A[i] == target:
                    continue
                else:
                    return -1
            elif A[i] == target:
                b_swap += 1
            elif B[i] == target:
                a_swap += 1
            else:
                return -1
        return min(a_swap, b_swap)


Labels

LeetCode (1432) GeeksforGeeks (1122) LeetCode - Review (1067) Review (882) Algorithm (668) to-do (609) Classic Algorithm (270) Google Interview (237) Classic Interview (222) Dynamic Programming (220) DP (186) Bit Algorithms (145) POJ (141) Math (137) Tree (132) LeetCode - Phone (129) EPI (122) Cracking Coding Interview (119) DFS (115) Difficult Algorithm (115) Lintcode (115) Different Solutions (110) Smart Algorithm (104) Binary Search (96) BFS (91) HackerRank (90) Binary Tree (86) Hard (79) Two Pointers (78) Stack (76) Company-Facebook (75) BST (72) Graph Algorithm (72) Time Complexity (69) Greedy Algorithm (68) Interval (63) Company - Google (62) Geometry Algorithm (61) Interview Corner (61) LeetCode - Extended (61) Union-Find (60) Trie (58) Advanced Data Structure (56) List (56) Priority Queue (53) Codility (52) ComProGuide (50) LeetCode Hard (50) Matrix (50) Bisection (48) Segment Tree (48) Sliding Window (48) USACO (46) Space Optimization (45) Company-Airbnb (41) Greedy (41) Mathematical Algorithm (41) Tree - Post-Order (41) ACM-ICPC (40) Algorithm Interview (40) Data Structure Design (40) Graph (40) Backtracking (39) Data Structure (39) Jobdu (39) Random (39) Codeforces (38) Knapsack (38) LeetCode - DP (38) Recursive Algorithm (38) String Algorithm (38) TopCoder (38) Sort (37) Introduction to Algorithms (36) Pre-Sort (36) Beauty of Programming (35) Must Known (34) Binary Search Tree (33) Follow Up (33) prismoskills (33) Palindrome (32) Permutation (31) Array (30) Google Code Jam (30) HDU (30) Array O(N) (29) Logic Thinking (29) Monotonic Stack (29) Puzzles (29) Code - Detail (27) Company-Zenefits (27) Microsoft 100 - July (27) Queue (27) Binary Indexed Trees (26) TreeMap (26) to-do-must (26) 1point3acres (25) GeeksQuiz (25) Merge Sort (25) Reverse Thinking (25) hihocoder (25) Company - LinkedIn (24) Hash (24) High Frequency (24) Summary (24) Divide and Conquer (23) Proof (23) Game Theory (22) Topological Sort (22) Lintcode - Review (21) Tree - Modification (21) Algorithm Game (20) CareerCup (20) Company - Twitter (20) DFS + Review (20) DP - Relation (20) Brain Teaser (19) DP - Tree (19) Left and Right Array (19) O(N) (19) Sweep Line (19) UVA (19) DP - Bit Masking (18) LeetCode - Thinking (18) KMP (17) LeetCode - TODO (17) Probabilities (17) Simulation (17) String Search (17) Codercareer (16) Company-Uber (16) Iterator (16) Number (16) O(1) Space (16) Shortest Path (16) itint5 (16) DFS+Cache (15) Dijkstra (15) Euclidean GCD (15) Heap (15) LeetCode - Hard (15) Majority (15) Number Theory (15) Rolling Hash (15) Tree Traversal (15) Brute Force (14) Bucket Sort (14) DP - Knapsack (14) DP - Probability (14) Difficult (14) Fast Power Algorithm (14) Pattern (14) Prefix Sum (14) TreeSet (14) Algorithm Videos (13) Amazon Interview (13) Basic Algorithm (13) Codechef (13) Combination (13) Computational Geometry (13) DP - Digit (13) LCA (13) LeetCode - DFS (13) Linked List (13) Long Increasing Sequence(LIS) (13) Math-Divisible (13) Reservoir Sampling (13) mitbbs (13) Algorithm - How To (12) Company - Microsoft (12) DP - Interval (12) DP - Multiple Relation (12) DP - Relation Optimization (12) LeetCode - Classic (12) Level Order Traversal (12) Prime (12) Pruning (12) Reconstruct Tree (12) Thinking (12) X Sum (12) AOJ (11) Bit Mask (11) Company-Snapchat (11) DP - Space Optimization (11) Dequeue (11) Graph DFS (11) MinMax (11) Miscs (11) Princeton (11) Quick Sort (11) Stack - Tree (11) 尺取法 (11) 挑战程序设计竞赛 (11) Coin Change (10) DFS+Backtracking (10) Facebook Hacker Cup (10) Fast Slow Pointers (10) HackerRank Easy (10) Interval Tree (10) Limited Range (10) Matrix - Traverse (10) Monotone Queue (10) SPOJ (10) Starting Point (10) States (10) Stock (10) Theory (10) Tutorialhorizon (10) Kadane - Extended (9) Mathblog (9) Max-Min Flow (9) Maze (9) Median (9) O(32N) (9) Quick Select (9) Stack Overflow (9) System Design (9) Tree - Conversion (9) Use XOR (9) Book Notes (8) Company-Amazon (8) DFS+BFS (8) DP - States (8) Expression (8) Longest Common Subsequence(LCS) (8) One Pass (8) Quadtrees (8) Traversal Once (8) Trie - Suffix (8) 穷竭搜索 (8) Algorithm Problem List (7) All Sub (7) Catalan Number (7) Cycle (7) DP - Cases (7) Facebook Interview (7) Fibonacci Numbers (7) Flood fill (7) Game Nim (7) Graph BFS (7) HackerRank Difficult (7) Hackerearth (7) Inversion (7) Kadane’s Algorithm (7) Manacher (7) Morris Traversal (7) Multiple Data Structures (7) Normalized Key (7) O(XN) (7) Radix Sort (7) Recursion (7) Sampling (7) Suffix Array (7) Tech-Queries (7) Tree - Serialization (7) Tree DP (7) Trie - Bit (7) 蓝桥杯 (7) Algorithm - Brain Teaser (6) BFS - Priority Queue (6) BFS - Unusual (6) Classic Data Structure Impl (6) DP - 2D (6) DP - Monotone Queue (6) DP - Unusual (6) DP-Space Optimization (6) Dutch Flag (6) How To (6) Interviewstreet (6) Knapsack - MultiplePack (6) Local MinMax (6) MST (6) Minimum Spanning Tree (6) Number - Reach (6) Parentheses (6) Pre-Sum (6) Probability (6) Programming Pearls (6) Rabin-Karp (6) Reverse (6) Scan from right (6) Schedule (6) Stream (6) Subset Sum (6) TSP (6) Xpost (6) n00tc0d3r (6) reddit (6) AI (5) Abbreviation (5) Anagram (5) Art Of Programming-July (5) Assumption (5) Bellman Ford (5) Big Data (5) Code - Solid (5) Code Kata (5) Codility-lessons (5) Coding (5) Company - WMware (5) Convex Hull (5) Crazyforcode (5) DFS - Multiple (5) DFS+DP (5) DP - Multi-Dimension (5) DP-Multiple Relation (5) Eulerian Cycle (5) Graph - Unusual (5) Graph Cycle (5) Hash Strategy (5) Immutability (5) Java (5) LogN (5) Manhattan Distance (5) Matrix Chain Multiplication (5) N Queens (5) Pre-Sort: Index (5) Quick Partition (5) Quora (5) Randomized Algorithms (5) Resources (5) Robot (5) SPFA(Shortest Path Faster Algorithm) (5) Shuffle (5) Sieve of Eratosthenes (5) Strongly Connected Components (5) Subarray Sum (5) Sudoku (5) Suffix Tree (5) Swap (5) Threaded (5) Tree - Creation (5) Warshall Floyd (5) Word Search (5) jiuzhang (5)

Popular Posts