LeetCode 995 - Minimum Number of K Consecutive Bit Flips


https://leetcode.com/problems/minimum-number-of-k-consecutive-bit-flips/
In an array A containing only 0s and 1s, a K-bit flip consists of choosing a (contiguous) subarray of length K and simultaneously changing every 0 in the subarray to 1, and every 1 in the subarray to 0.
Return the minimum number of K-bit flips required so that there is no 0 in the array.  If it is not possible, return -1.

Example 1:
Input: A = [0,1,0], K = 1
Output: 2
Explanation: Flip A[0], then flip A[2].
Example 2:
Input: A = [1,1,0], K = 2
Output: -1
Explanation: No matter how we flip subarrays of size 2, we can't make the array become [1,1,1].
Example 3:
Input: A = [0,0,0,1,0,1,1,0], K = 3
Output: 3
Explanation:
Flip A[0],A[1],A[2]: A becomes [1,1,1,1,0,1,1,0]
Flip A[4],A[5],A[6]: A becomes [1,1,1,1,1,0,0,0]
Flip A[5],A[6],A[7]: A becomes [1,1,1,1,1,1,1,1]

Note:
  1. 1 <= A.length <= 30000
  2. 1 <= K <= A.length
X. https://www.cnblogs.com/lz87/p/10398670.html
Formation and proof of greedy algorithm: Intuitively, we know if A[0] is 0, then we must flip from the left side since there is only this way to flip A[0].  So the following greedy algorithm may be the right algorithm here. But we must prove it is the correct algorithm. 
Greedy Algorithm: from left to right, after considering the previous flips, if A[i] is 0, flip subarray A[i] to A[i + K - 1]. Otherwise don't flip. If A[i] needs to be flipped but the remaining subarray does not have K elements to operate flip on  (A.length - i < K), return -1.
Proof of correctness:  The above algorithm gives a solution S by greedily flipping 0s from left to right, considering previous flips. We claim to if A[i] is already 1, then we never flip it, else always flip subarray starting from A[i]. Now we'll prove the following solutions does not yield a solution that is better than S.
1. Without loss of generosity, let the i-th bit be the first 0. There is a solution S' that does a flip at A[j], j < i. Since A[j] == 1, a flip will set A[j] to 0. Eventually A[j] must be flipped back to 1, and this can only happen for flips whose start index is in [j - K + 1, j] range. Obviously we can eliminate start index j as that is doing the same flip starting from A[j] twice, essentially wasting 2 flips and achieving nothing. So we know in order to flip A[j] back to 1, a flip that starts at a smaller index j must occur. Because all the bits that come ahead index j are also 1s, we can induct the same reasoning: to flip back a bit that was originally 1, we can only resort to another flip that starts at an smaller index until we reach A[0]. At this point, we can only flip at A[0], wasting 2 flips and achieves nothing. So this proves that from left to right, skipping 1s is always better than flipping 1s.
2. Assume we don't start from left to right, but at some middle index i. 
2a. A[i] == 1, based on the case 1 argument, we know skipping A[i] is better.
2b. A[i] == 0. There are two possible cases. 1. If there is no 0s to the left of A[i], then this is the greedy algorithm we formed. 2. If there are 0s to the left of A[i], let j be the index of the first 0 from A[0...i - 1]. Again by case 1 argument, we know that we simply flip A[j]. The same argument applies to rest of 0s in A[0.... i - 1]. As a result, we know starting in the middle does not yield a better result that starting from left.
    public int minKBitFlips(int[] A, int K) {
        int count = 0;
        for(int i = 0; i < A.length; i++) {
            if(A[i] == 0 && i + K <= A.length) {
                for(int j = 0; j < K; j++) {
                    A[i + j] = A[i + j] == 0 ? 1 : 0;
                }
                count++;
            }
            else if(A[i] == 0) {
                return -1;
            }
        }
        return count;
    }
https://leetcode.com/problems/minimum-number-of-k-consecutive-bit-flips/discuss/239284/C%2B%2B-greedy-stack-and-O(1)-memory
Just want to share my thought process; I am sure that there is a formal proof somewhere.
  1. Since K is fixed, it does not make sense to do the flip for any given index more than once. It's a XOR operation, even flips will be equal to zero flips, odd flips will be equal to one flip. So, there could be up to n - K flips.
  2. Since it's a XOR operation, we can do flips in any order.
  3. Say we start do flips left to right. That means that, when we encounter zero, we have no choice but flip.
At this point, this intuition is sound enough to try a greedy approach.

Naïve Greedy Solution

Go through the array and flip K elements when encounter zero. Return -1 if you cannot do K flips.
int minKBitFlips(vector<int>& A, int K, int res = 0) {
  for (auto i = 0; i < A.size(); ++i) {
    if (A[i] != 1) {
      if (i + K - 1 >= A.size()) return -1;
      for (auto j = i; j < i + K; ++j) A[j] = !A[j];
      ++res;
    }
  }
  return res;
}

The time complexity of this solution is O(n * K), where n is the length of A. This solution is not accepted by the online judge.

https://leetcode.com/problems/minimum-number-of-k-consecutive-bit-flips/discuss/238557/Java-clean-O(n*k)-greedy-solution
    private void flip(int[]A,int K,int i){
        for(int j=i;j<i+K;j++){
            A[j]=1-A[j];
        }
    }
    public int minKBitFlips(int[] A, int K) {
        int cnt=0;
        for(int i=0;i<A.length;i++){
            if(A[i]==0){
                if(i+K>A.length)return -1;
                flip(A,K,i);
                cnt++;
            }
        }
        return cnt;
    }
X.
The bottleneck of the naive solution is that it does not use the previous flip information. For a given index i, whether there needs to be a flip starting from A[i] or not depends the original A[i] value and the impacts of possible flips starting from index [i - K + 1, i - 1]. Flips that occur at index smaller than i - K + 1 do not have any impact on A[i]'s flip decision. To save/update the previous K indices's flip events, we need a sliding window of size K. 
1. Use an ArrayDeque of size K to keep the indices of bits that are flipped and a count variable currentEffectiveFlips to keep the flips that occur previously that are also still effective on the current bit A[i]. 
2. If the earliest flip event saved in the deque is no longer effective, remove it and decrement currentEffectiveFlips by 1. 
3. At this point, we have A[i]'s value and the effective previous flip counts, we do the following:
3a. If A[i] has been flipped even number times and A[i] is originally 0,  we know A[i] is still 0 so flip it.
3b. or if A[i] has been flipped odd number times and A[i] is originally 1, we know A[i] has been flipped to 0 so flip it.
    public int minKBitFlips(int[] A, int K) {
        int totalFlips = 0, currentEffectiveFlips = 0;
        Deque<Integer> flipIndices = new ArrayDeque<>();
        for(int i = 0; i < A.length; i++) {
            if(flipIndices.size() > 0 && flipIndices.peekFirst() + K == i) {
                flipIndices.remove();
                currentEffectiveFlips--;
            }
            if(A[i] == 0 && currentEffectiveFlips % 2 == 0 
               || A[i] == 1 && currentEffectiveFlips % 2 != 0) {
                if(i + K > A.length) {
                    return -1;
                }
                flipIndices.addLast(i);
                currentEffectiveFlips++;
                totalFlips++;
            }
        }
        return totalFlips;
    }

Since we are doing XOR operation, even flips will be equal to zero flips, odd flips will be equal to one flip. So, instead of modifying K bits every time we encounter zero, we can just track the current number of flips.

Linear Solution

Here, we are using a queue to track flips. When we 'flip', we put the end index of our flip (i + K - 1) into our queue. The size of the queue will indicate number of flips; we also remove past 'flips' from our queue.
int minKBitFlips(vector<int>& A, int K, int res = 0) {
  queue<int> flips;
  for (auto i = 0; i < A.size(); ++i) {
    if (A[i] != (flips.size() % 2 ? 0 : 1)) {
      ++res;
      flips.push(i + K - 1);
    }
    if (!flips.empty() && flips.front() <= i) flips.pop();
  }
  return flips.empty() ? res : -1;
}

Complexity Analysis

The time complexity of this solution is O(n), and the memory complexity is O(K).

Constant Memory Solution

Instead of using the queue, we can track the total number of flips, and use the source array to mark flips with negative values.
Note that we restore original values after the processing, so the source array is not changed.
int minKBitFlips(vector<int>& A, int K, int res = 0, int flips = 0) {
  for (auto i = 0; i < A.size(); ++i) {
    if (A[i] == flips % 2) {
      if (i > A.size() - K) return -1;
      ++res, ++flips, A[i] -= 2;
    }
    if (i >= K - 1 && A[i - K + 1] < 0) --flips, A[i - K + 1] += 2;
  }
  return res;
}
http://www.noteanddata.com/leetcode-995-Minimum-Number-of-K-Consecutive-Bit-Flips-java-solution-note.html
  1. 最naive的想法是暴力bfs,扫描所有的操作, 然后看是否走到最终状态或者重复状态, 结果当然是超时
  2. 然后试图用动态规划做, 试图对中间操作, 然后把数组分成两边, 然后对两边分别做, 最后求出最小值, 这个也只写了bug
    中间也试图想能否先得到最右边都是1或者最右边都是0的状态,
  3. 结果最后看别人的答案, 居然是直接一次遍历做贪心!!! 又受到一万点暴击!
  4. 贪心代码非常简洁,就是从左向右遍历, 遇到0就做flip,然后一直到数组结尾就好了!!!
  5. 这里,重点是为什么贪心是对的?
    我们有如下思路:
    a. 对于任何一个位置,要么不flip, 要么flip一次, 因为flip两次是没有意义的
    b. 从左向右遍历,如果左边第一个是1, 那么,因为我们要么不flip,要么flip一次, 所以,对于最左边的1, 一定是不需要flip的
    c. 如果左边第一个是0, 那么,我们一定是需要在这个位置flip一次, 因为没有其他选择可以让这个数变成1
    d. 现在我们已经对第一个元素做了最佳处理,然后我们考虑第二个元素,同样的推理过程也是适用的,如果是1就不处理,如果是0就flip,
    e. 这里,正确性的关键在于, 每个步骤,一定是属于最佳答案的一部分, 并且,前面的处理完了以后,后面无论怎么样处理,
    都不会影响到前面的处理结果和状态, 所以,这个过程一定是正确的。
  6. 还有一个问题是, 如何分析到贪心? (比如我就没有分析出来)
    这个题目除了暴力的思路, 尝试了尾部dp的思路(试图寻找dp[i]和dp[j]的关系),尝试了中间的dp(中间处理,然后对两边单独做处理),
    尝试了试图把尾部全部变成1或者0(这里其实有点接近了, 因为从左往右做的过程效果就是把0都放到最右边), 也尝试了小规模数据,
    都没有分析到贪心的思路。
X.
https://leetcode.com/problems/minimum-number-of-k-consecutive-bit-flips/discuss/238609/JavaC%2B%2BPython-One-Pass-and-O(1)-Space
There is only one way to filp A[0],
and A[0] will tell us if we need to filp the range A[0] ~ A[K -1].
So we start from the leftmost one by one using a greedy idea to solve this problem.

Solution 1

Explanation
Create a new array isFlipped[n].
isFlipped[i] = 1 iff we flip K consecutive bits starting at A[i].
We maintain a variable flipped and flipped = 1 iff the current bit is flipped.
If flipped = 0 and A[i] = 0, we need to flip at A[i].
If flipped = 1 and A[i] = 1, we need to flip at A[i].


Complexity
O(N) time for one pass
O(N) extra space for isFlipped[n].
    public int minKBitFlips(int[] A, int K) {
        int n = A.length, flipped = 0, res = 0;
        int[] isFlipped = new int[n];
        for (int i = 0; i < A.length; ++i) {
            if (i >= K)
                flipped ^= isFlipped[i - K];
            if (flipped == A[i]) {
                if (i + K > A.length)
                    return -1;
                isFlipped[i] = 1;
                flipped ^= 1;
                res++;
            }
        }
        return res;
    }

Solution 2


Explanation
Instead an array isFlipped of size n,
use a deque to maintain the state of a sliding window of size k.
Complexity
O(N) time for one pass
O(K) extra space for isFlipped[n].

Solution 3

Explanation:
One pass, count the cur filp numbers in a sliding window of size K.
If cur is even and A[i] is 0, we need to flip.
If cur is odd and A[i] is 1, we need to flip.
Complexity:
O(N) time for one pass
O(1) extra space.
     public int minKBitFlips(int[] A, int K) {
        int cur = 0, res = 0;
        for (int i = 0; i < A.length; ++i) {
            if (i >= K) cur -= A[i - K] / 2;
            if ((cur & 1 ^ A[i]) == 0) {
                if (i + K > A.length) return -1;
                A[i] += 2;
                cur++;
                res++;
            }
        }
        return res;
    }

https://leetcode.com/articles/minimum-number-of-k-consecutive-bit-flips/
If the leftmost element is a 0, we must flip the subarray starting at index 0. Similarly, if the leftmost element is a 1, we should not flip the subarray starting at index 0. This proves we can proceed in a greedy manner: after finding out whether we have to flip the first subarray (positions 0 to K-1) or not, we can consider the array with the first element (value 1) removed, and repeat this process.
We can do better. Every time we flip a subarray A[i], A[i+1], ..., A[i+K-1], we can consider this as two "events", one 'opening event' at position i that marks the start of the subarray, and one 'closing event' at position i+K that marks the end of the subarray. Using these events, we always know how many overlapping flipped subarrays there are: its simply the number of opening events minus the number of closing events.
Algorithm
When we flip a subarray, let's call the set of indices we flipped an interval. We'll keep track of flip, the number of overlapping intervals in our current position. We only care about the value of flip modulo 2.
When we flip an interval starting at i, we create a hint for a closing event at i+K telling us to flip our writing state back.

  public int minKBitFlips(int[] A, int K) {
    int N = A.length;
    int[] hint = new int[N];
    int ans = 0, flip = 0;

    // When we flip a subarray like A[i], A[i+1], ..., A[i+K-1]
    // we can instead flip our current writing state, and put a hint at
    // position i+K to flip back our writing state.
    for (int i = 0; i < N; ++i) {
      flip ^= hint[i];
      if (A[i] == flip) { // If we must flip the subarray starting here...
        ans++; // We're flipping the subarray from A[i] to A[i+K-1]
        if (i + K > N)
          return -1; // If we can't flip the entire subarray, its impossible
        flip ^= 1;
        if (i + K < N)
          hint[i + K] ^= 1;
      }
    }

    return ans;
  }

X. https://www.acwing.com/solution/LeetCode/content/1033/
(贪心,差分思想) O(n)O(n)
显然我们需要一个策略来翻转数组。
这里不加证明地给出最优的策略,考虑从数组开头开始检查,如果遇到了 0,则累计答案并翻转当前位置及当前位置之后的 K 个元素,使得当前位置变为 1,然后继续检查下一个位置。如果遇到了 1 则不进行任何操作。如果在最后不足 K 个位置的时候遇到了 0,则返回 -1。
但这样操作时间复杂度是 O(nK)O(nK) 的,需要进行优化。我们发现,每个位置的状态和操作次数的奇偶有关系,而每次我们又是操作连续的位置,则考虑差分的思想。
额外建立一个数组 B,初始值都为 0,额外维护一个当前的和 cur。如果 cur + A[i] + B[i] 为 0,则需要进行翻转,则累计答案的同时, cur = cur + 1 + B[i],且 B[i + K] = -1;否则,只需要 cur = cur + B[i]。
时间复杂度
优化后的策略每个位置仅进行常数时间的操作,故时间复杂度为 O(n)O(n)。
空间复杂度
由于使用了额外数组,空间复杂度为 O(n)O(n)。
C++ 代码
class Solution {
public:
    int minKBitFlips(vector<int>& A, int K) {
        int n = A.size();
        int cur = 0, ans = 0;
        vector<int> B(n, 0);
        for (int i = 0; i < n; i++)
            if ((A[i] + B[i] + cur) % 2 == 0) {
                ans++;
                if (i + K < n)
                    B[i + K] = -1;
                else if (i + K > n)
                    return -1;
                cur += B[i] + 1;
            }
            else {
                cur += B[i];
            }
        return ans;
    }

X. Proof
https://leetcode.com/problems/minimum-number-of-k-consecutive-bit-flips/discuss/238683/Proof%3A-Why-greedy-works
  • before and after any flip, any bit in the sequence of 1 starting from the left-most bit should not be flipped anymore.

Proof by contradiction:

The greedy claim gives a solution S. Without loss of generosity, let the i-th bit be the first 0 bit. Suppose the greedy claim above is false, then there must be a better (better means less flips) solution S' in which bits in range [J , J + K - 1] are flipped and J < i. There could be multiple J. Let j be the smallest possible J. Since A[j] now is 1 (why? because j<i), if we flip it, A[j] becomes 0. A[j] finally should be 1, so S' must flips A[j] again sometime later. As j is the smallest of JS' can't flip anything left to A[j], which means only flipping the range [j , j + K - 1] can flip A[j] back to 1. See? we flipped [j , j + K - 1], then again [j , j + K - 1]S' wasts flips. If S' exists, we can find a third solution S'' that is strictly even better than S'. And we can do this induction infinitely and find a solution needs only 0 or even negative number of flips. -- That is of course impossible. Actually, the induction of finding even better solutions will eventually give you SS is strictly better than S? Of course not!
-- So the greedy claim above is NOT false.
So, the greedy claim is true.

OK...I know I shouldn't flip the left-most 1s. What should I flip next?

So everything left to the i-th bit should not be flipped. But A[i] now is 0. S will flip it to 1 sometime. Since from then on S can't flip anything left to A[i], it must flip A[i...i + K - 1] to flip A[i]


https://buptwc.com/2019/02/25/Leetcode-995-Minimum-Number-of-K-Consecutive-Bit-Flips/
我们想一想,对于数组中最左边的0(不妨定义下标为i),我们如果想将其翻转为1的话,那么这k个翻转数该选哪个作为起点呢。如果以某个下标j(j < i)进行翻转,那么又会在更左边产生0,这样下去会一直到左边界,这显然是不合理的。我们应当就以i为起点来进行翻转。
这也就是贪心的思想!
从左至右进行遍历,每遍历到0就进行一次翻转,但是考虑到后面k个数也会进行翻转,我们如何对其进行记录呢
这里使用一个列表,将每次翻转所影响到的最右下标记录。对于当前判断的位置来说,使用二分法找到其到底被多少次翻转所影响,然后计算即可。



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
    def minKBitFlips(self, A, K):
        res = 0
        s = []
        for i in range(len(A)):
            index = bisect.bisect_right(s, i)
            # if influenced, flip it and then judge
            if (len(s) - index) % 2 == 1:
                A[i] = 1 - A[i]
            # only consider it when A[i] == 0
            if A[i] == 1: continue
            if len(A)-i < K: return -1
            res += 1
            s.append(i + K)
        return res



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