Graph Algorithm - How to Succeed in Algorithms Interview


Graph Algorithm - How to Succeed in Algorithms Interview

Series: How to Succeed in Algorithms Interview


Graph represent

  • AdjacencyMatrix
  • AdjacencyList: List[]
  • EdgeList: Edge[] edges
  • Map<Integer, Set> map
  • Map indegrees
  • Topological Sort O(V+E)
  • create graph when 2 elements meets some criteria

Approaches

Binary tree to graph

int N;
Map<Integer, List<Integer>> graph;
Integer[][] memo;

public int numSquarefulPerms(int[] A) {
  N = A.length;
  graph = new HashMap();
  memo = new Integer[N][1 << N];

  for (int i = 0; i < N; ++i)
    graph.put(i, new ArrayList());

  for (int i = 0; i < N; ++i)
    for (int j = i + 1; j < N; ++j) {
      int r = (int) (Math.sqrt(A[i] + A[j]) + 0.5);
      if (r * r == A[i] + A[j]) {
        graph.get(i).add(j);
        graph.get(j).add(i);
      }
    }

  int[] factorial = new int[20];
  factorial[0] = 1;
  for (int i = 1; i < 20; ++i)
    factorial[i] = i * factorial[i - 1];

  int ans = 0;
  for (int i = 0; i < N; ++i)
    ans += dfs(i, 1 << i);

  Map<Integer, Integer> count = new HashMap();
  for (int x : A)
    count.put(x, count.getOrDefault(x, 0) + 1);
  for (int v : count.values())
    ans /= factorial[v];

  return ans;
}

public int dfs(int node, int visited) {
  if (visited == (1 << N) - 1)
    return 1;
  if (memo[node][visited] != null)
    return memo[node][visited];

  int ans = 0;
  for (int nei : graph.get(node))
    if (((visited >> nei) & 1) == 0)
      ans += dfs(nei, visited | (1 << nei));
  memo[node][visited] = ans;
  return ans;

}

Detect Cycle in Undirected Graph

Detect Cycle in a Directed Graph

  • dfs
    • Recursion stack[] is used from keep track of visiting vertices during DFS from particular vertex and gets reset once cycle is not found from that vertex and will try DFS from other vertices.
    • isCycleUtil(int vertex, boolean[] visited, boolean[] recursiveArr)
  • dfs + using colors
  • Topological sort

Check if a directed graph is strongly connected

  1. Do a DFS traversal of graph starting from any arbitrary vertex v. If DFS traversal doesn’t visit all vertices, then return false.
  2. Reverse all arcs (or find transpose or reverse of graph) and Do a DFS traversal of reversed graph starting from same vertex , If DFS traversal doesn’t visit all vertices, then return false.
  • The idea is, if every node can be reached from a vertex v, and every node can reach v, then the graph is strongly connected. In step 1, we check if all vertices are reachable from v. In step 2, we check if all vertices can reach v (In reversed graph, if all vertices are reachable from v, then all vertices can reach v in original graph)

Eulerian path

Eulerian Cycle
  • For an undirected graph has Eulerian cycle
    1. All vertices with non-zero degree are connected.
    2. All vertices have even degree.

Eulerian Path

  • For an undirected graph has Eulerian Path
    1. Same as condition (a) for Eulerian Cycle
    2. If two vertices have odd degree and all other vertices have even degree. Note that only one vertex with odd degree is not possible in an undirected graph (sum of all degrees is always even in an undirected graph)

Eulerian Cycle for a directed graph

  • A directed graph has an eulerian cycle if following conditions are true
    1. All vertices with nonzero degree belong to a single strongly connected component.
    2. In degree and out degree of every vertex is same.

Hamiltonian Cycle

Connected Components

Matrix to Graph

Tree to Graph

Color during DFS

Create Reverse Graph

Degree(in-degree, out-degree)

public int findJudge(int N, int[][] trust) {
    int[] count = new int[N+1];
    for (int[] t: trust) {
        count[t[0]]--;
        count[t[1]]++;
    }
    for (int i = 1; i <= N; ++i) {
        if (count[i] == N - 1) return i;
    }
    return -1;
}

Floyd Warshall Algorithm - All Pairs Shortest Path: O(V^3)

  • one by one pick all vertices and updates all shortest paths which include the picked vertex as an intermediate vertex in the shortest path.
  • when we pick vertex number k as an intermediate vertex, we already have considered vertices {0, 1, 2, .. k-1} as intermediate vertices.
void floydWarshall(int graph[][])
{
    int dist[][] = new int[V][V];
    int i, j, k;
    for (i = 0; i < V; i++)
        for (j = 0; j < V; j++)
            dist[i][j] = graph[i][j];
    // Add all vertices one by one to the set of intermediate vertices.
    for (k = 0; k < V; k++)
    {
        // Pick all vertices as source one by one
        for (i = 0; i < V; i++)
        {
            // Pick all vertices as destination for the
            // above picked source
            for (j = 0; j < V; j++)
            {
                // If vertex k is on the shortest path from i to j, then update the value of dist[i][j]
                if (dist[i][k] + dist[k][j] < dist[i][j])
                    dist[i][j] = dist[i][k] + dist[k][j];
            }
        }
    }
}
  • LeetCode 399 - Evaluate Division
    public double[] calcEquation(String[][] equations, double[] values, String[][] queries) {
      HashMap<String, HashMap<String, Double>> graph = new HashMap<>();
      Function<String, HashMap<String, Double>> function = s -> new HashMap<>();
      for (int i = 0; i < equations.length; i++) {
          graph.computeIfAbsent(equations[i][0], function).put(equations[i][0], 1.0);
          graph.computeIfAbsent(equations[i][1], function).put(equations[i][1], 1.0);
          graph.get(equations[i][0]).put(equations[i][1], values[i]);
          graph.get(equations[i][1]).put(equations[i][0], 1 / values[i]);
      }
      for (String mid : graph.keySet()) {
          for (String src : graph.get(mid).keySet()) {
              for (String dst : graph.get(mid).keySet()) {
                  double val = graph.get(src).get(mid) * graph.get(mid).get(dst);
                  graph.get(src).put(dst, val);
              }
          }
      }
      double[] result = new double[queries.length];
      for (int i = 0; i < result.length; i++) {
          if (!graph.containsKey(queries[i][0])) {
              result[i] = -1;
          } else {
              result[i] = graph.get(queries[i][0]).getOrDefault(queries[i][1], -1.0);
          }
      }
      return result;
    }

Examples

Reverse Thinking - How to Succeed in Algorithms Interview


Reverse Thinking - How to Succeed in Algorithms Interview

How to Succeed in Algorithms Interview Series


Scan from right to left

public boolean backspaceCompare(String S, String T) {
    for (int i = S.length() - 1, j = T.length() - 1;; i--, j--) {
        for (int b = 0; i >= 0 && (b > 0 || S.charAt(i) == '#'); --i) b += S.charAt(i) == '#' ? 1 : -1;
        for (int b = 0; j >= 0 && (b > 0 || T.charAt(j) == '#'); --j) b += T.charAt(j) == '#' ? 1 : -1;
        if (i < 0 || j < 0 || S.charAt(i) != T.charAt(j)) return i == -1 && j == -1;
    }
}
public String parseTernary(String expression) {
    if (expression == null || expression.length() == 0) return "";
    Deque<Character> stack = new LinkedList<>();

    for (int i = expression.length() - 1; i >= 0; i--) {
        char c = expression.charAt(i);
        if (!stack.isEmpty() && stack.peek() == '?') {

            stack.pop(); //pop '?'
            char first = stack.pop();
            stack.pop(); //pop ':'
            char second = stack.pop();

            if (c == 'T') stack.push(first);
            else stack.push(second);
        } else {
            stack.push(c);
        }
    }
    return String.valueOf(stack.peek());
}
public String decodeAtIndex(String S, int K) {
  long size = 0;
  int N = S.length();
  for (int i = 0; i < N; ++i) {
    char c = S.charAt(i);
    if (Character.isDigit(c))
      size *= c - '0';
    else
      size++;
  }
  for (int i = N - 1; i >= 0; --i) {
    char c = S.charAt(i);
    K %= size;
    if (K == 0 && Character.isLetter(c))
      return Character.toString(c);
    if (Character.isDigit(c))
      size /= c - '0';
    else
      size--;
  }
  throw null;
}
public String decodeAtIndex(String S, int K) {
  long size = 0;
  int N = S.length();
  // Find size = length of decoded string
  for (int i = 0; i < N; ++i) {
    char c = S.charAt(i);
    if (Character.isDigit(c))
      size *= c - '0';
    else
      size++;
  }
  for (int i = N - 1; i >= 0; --i) {
    char c = S.charAt(i);
    K %= size;
    if (K == 0 && Character.isLetter(c))
      return Character.toString(c);
    if (Character.isDigit(c))
      size /= c - '0';
    else
      size--;
  }
  throw null;
}
  • LeetCode 853 - Car Fleet
    • from closet to furthest
    public int carFleet(int target, int[] position, int[] speed) {
      TreeMap<Integer, Integer> map = new TreeMap<>();
      int n = position.length;
      for(int i=0; i<n; ++i){
          map.put(target - position[i], speed[i]);
      }
      int count = 0;
      double r = -1.0;
      for(Map.Entry<Integer, Integer> entry: map.entrySet()){
          int d = entry.getKey(); // distance
          int s = entry.getValue(); // speed
          double t = 1.0*d/s; // time to target
          if(t>r){ // this car is unable to catch up previous one, form a new group and update the value
              ++count;
              r = t;
          }
      }
      return count;
    }

From (potential) target to source

  • LeetCode 780 - Reaching Points
    • if we start from sx and sy, there is two possibility, but if we start from target, there is only one possibility
    • use modulo to speed minus
bool reachingPoints(int sx, int sy, int tx, int ty) {
    while(tx >= sx && ty >= sy){
        if(tx > ty){
            if(sy == ty) return (tx - sx) % ty == 0;
            tx %= ty;
        }else{
            if(sx == tx) return (ty - sy) % tx == 0;
            ty %= tx;
        }
    }
    return false;
}

public boolean reachingPoints(int sx, int sy, int tx, int ty) {
    if (sx > tx || sy > ty) return false;
    if (sx == tx && (ty - sy) % sx == 0) return true;
    if (sy == ty && (tx - sx) % sy == 0) return true;
    return reachingPoints(sx, sy, tx % ty, ty % tx);
}

Reverse

Reverse - call same function again

Guess

  • [LeetCode 843 - Guess the Word]
    • [minimum our worst outcome]
      • worse case: only 0 match,
      • we guess the word with minimum words of 0 matches
// random
public void findSecretWord(String[] wordlist, Master master) {
  for (int i = 0, x = 0; i < 10 && x < 6; ++i) {
      String guess = wordlist[new Random().nextInt(wordlist.length)];
      x = master.guess(guess);
      List<String> wordlist2 = new ArrayList<>();
      for (String w : wordlist)
          if (match(guess, w) == x)
              wordlist2.add(w);
      wordlist = wordlist2.toArray(new String[wordlist2.size()]);
  }
}

public void findSecretWord(String[] wordlist, Master master) {
  for (int i = 0, x = 0; i < 10 && x < 6; ++i) {
      HashMap<String, Integer> count = new HashMap<>();
      for (String w1 : wordlist)
          for (String w2 : wordlist)
              if (match(w1, w2) == 0)
                  count.put(w1, count.getOrDefault(w1 , 0) + 1);
      Pair<String, Integer> minimax = new Pair<>("", 1000);
      for (String w : wordlist)
          if (count.getOrDefault(w, 0) < minimax.getValue())
              minimax = new Pair<>(w, count.getOrDefault(w, 0));
      x = master.guess(minimax.getKey());
      List<String> wordlist2 = new ArrayList<String>();
      for (String w : wordlist)
          if (match(minimax.getKey(), w) == x)
              wordlist2.add(w);
      wordlist = wordlist2.toArray(new String[0]);
  }
}

Notes on Distributed Systems


Consensus
Paxos
Roles: proposers, acceptors, learners

Practices:
Cassandra lightweight transactions, CAS

Raft
replicated state machine
strong leadership
(append-only) log replication
a term number and an index
randomized election timeout

2 Phase Commit
Vote
Commit/abort
a blocking protocol

3 Phase Commit
Vote
Prepare
Commit/abort
a non-blocking protocol

CAP
LSM

Redis
pub-sub
Only online customers can get message
No customer group, each customer gets all message

Basic
WAL - write-ahead-log
R+W>N

Scalable Stateful Services

Sliding Window - How to Succeed in Algorithms Interview


Sliding window - How to Succeed in Algorithms Interview

How to Succeed in Algorithms Interview Series


Applications of Sliding Window

  • window of size k
  • Shortest/longest Subarray with xxx
  • continuous subarrays or substrings

How to Implement Sliding Window

  • expand (end pointer) the window until it meets the criteria
  • reset value when it violates
  • shrink (start pointer) to make it smallest
  • maintain states when expand and shrink: put in a map/set
  • use together with queue or monotone queue

Implementation Detail

Multiple List

public int lengthOfLongestSubstring(String s) {
     if (s.length()==0) return 0;
     HashMap<Character, Integer> map = new HashMap<Character, Integer>();
     int max=0;
     for (int i=0, j=0; i<s.length(); ++i){
         if (map.containsKey(s.charAt(i))){
             j = Math.max(j,map.get(s.charAt(i))+1);
         }
         map.put(s.charAt(i),i);
         max = Math.max(max,i-j+1);
     }
     return max;
 }
public List<Integer> findAnagrams(String s, String p) {
    Map<Character, Integer> map = counter(p);
    int match = 0;
    for (int i = 0; i < s.length(); i++) {
        char c = s.charAt(i);
        if (map.containsKey(c)) {
            map.put(c, map.get(c) - 1);
            if (map.get(c) == 0) {
                match++;
            }
        }
        if (i >= p.length()) {
            c = s.charAt(i - p.length());
            if (map.containsKey(c)) {
                map.put(c, map.get(c) + 1);
                if (map.get(c) == 1) {
                    match--;
                }
            }
        }
        if (match == map.size()) {
            result.add(i - p.length() + 1);
        }
    }
    return result;
}

Window class

  • LeetCode 992 - Subarrays with K Different Integers
    public int subarraysWithKDistinct(int[] A, int K) {
    Window window1 = new Window();
    Window window2 = new Window();
    int ans = 0, left1 = 0, left2 = 0;
    for (int right = 0; right < A.length; ++right) {
      int x = A[right];
      window1.add(x);
      window2.add(x);
      while (window1.different() > K)
        window1.remove(A[left1++]);
      while (window2.different() >= K)
        window2.remove(A[left2++]);
      ans += left2 - left1;
    }
    return ans;
    }

    Jumping Window + Fixed Size

  • LeetCode 683 - K Empty Slots
    public int kEmptySlots(int[] flowers, int k) {
      int[] days = new int[flowers.length];
      for (int i = 0; i < flowers.length; i++) days[flowers[i] - 1] = i + 1;
      int left = 0, right = k + 1, result = Integer.MAX_VALUE;
      for (int i = 0; right < days.length; i++) {
          if (days[i] < days[left] || days[i] <= days[right]) {
              if (i == right)
                  result = Math.min(result, Math.max(days[left], days[right]));
              left = i;
              right = k + 1 + i;
          }
      }
      return (result == Integer.MAX_VALUE) ? -1 : result;
    }

Using Priority Queue - How to Succeed in Algorithms Interview


Using Priority Queue - How to Succeed in Algorithms Interview

How to Succeed in Algorithms Interview Series


Applications of Priority Queue

  • TopK

Implementation

  • Use poll, peek, offer
  • Don’t use remove (if need update it: just keep the old one and add a new one)
  • Alternation: use TreeSet/Map

Order - How to add elements

for (int i = 0; i + 1 < nums.length; ++i) {
    heap.offer(new Node(i, i+1));
}

Node node = null;
for (; k > 0; --k) {
    node = heap.poll();
    if (node.nei + 1 < nums.length) {
        heap.offer(new Node(node.root, node.nei + 1));
    }
}

Merge k sorted list

  • Element: [outerIndex, innerIndex]
  • Iterator
Examples
public List<Interval> employeeFreeTime(List<List<Interval>> schedule) {
  List<Interval> res = new ArrayList<Interval>();
  PriorityQueue<Node> minHeap = new PriorityQueue<Node>(
      (a, b) -> schedule.get(a.employee).get(a.index).start - schedule.get(b.employee).get(b.index).start);
  int start = Integer.MAX_VALUE;
  for (int i = 0; i < schedule.size(); i++) {
    minHeap.add(new Node(i, 0));
    start = Math.min(start, schedule.get(i).get(0).start);
  }
  while (!minHeap.isEmpty()) {
    Node cur = minHeap.poll();
    if (start < schedule.get(cur.employee).get(cur.index).start) {
      res.add(new Interval(start, schedule.get(cur.employee).get(cur.index).start));
    }
    start = Math.max(start, schedule.get(cur.employee).get(cur.index).end);
    cur.index++;
    if (cur.index < schedule.get(cur.employee).size()) {
      minHeap.add(cur);
    }
  }
  return res;
}
class Node {
  int employee;
  int index;
  public Node(int employee, int index) {
    this.employee = employee;
    this.index = index;
  }
}

Examples

public int nthSuperUglyNumber(int n, int[] primes) {
    int[] ugly = new int[n];
    int[] idx = new int[primes.length];
    int[] val = new int[primes.length];
    Arrays.fill(val, 1);

    int next = 1;
    for (int i = 0; i < n; i++) {
        ugly[i] = next;

        next = Integer.MAX_VALUE;
        for (int j = 0; j < primes.length; j++) {
            //skip duplicate and avoid extra multiplication
            if (val[j] == ugly[i]) val[j] = ugly[idx[j]++] * primes[j];
            //find next ugly number
            next = Math.min(next, val[j]);
        }
    }
    return ugly[n - 1];
}

public int nthSuperUglyNumberHeap(int n, int[] primes) {
    int[] ugly = new int[n];
    PriorityQueue<Num> pq = new PriorityQueue<>();
    for (int i = 0; i < primes.length; i++) pq.add(new Num(primes[i], 1, primes[i]));
    ugly[0] = 1;
    for (int i = 1; i < n; i++) {
        ugly[i] = pq.peek().val;
        while (pq.peek().val == ugly[i]) {
            Num nxt = pq.poll();
            pq.add(new Num(nxt.p * ugly[nxt.idx], nxt.idx + 1, nxt.p));
        }
    }
    return ugly[n - 1];
}
public int minRefuelStops(int target, int startFuel, int[][] stations) {
    int curFarthest = startFuel, refuel = 0;
    PriorityQueue<Integer> pq = new PriorityQueue<>((a, b) -> b - a);
    for (int[] station : stations) {
        // check if we can reach this station
        // if we cannot reach this station, refuel the gas from the previous station with most gas
        // redo the operation until we get enough gas to reach this station
        while (curFarthest < station[0]) {
            if (pq.isEmpty()) return -1; // if we reful in each station but still cannot reach this station, return -1
            curFarthest += pq.poll();
            refuel++;
        }
        pq.offer(station[1]);
    }
    // now we have reached the last station, check if we can reach the target
    while (curFarthest < target) {
        if (pq.isEmpty()) return -1;
        curFarthest += pq.poll();
        refuel++;
    }
    return refuel;
}

public int minRefuelStops(int target, int cur, int[][] s) {
    Queue<Integer> pq = new PriorityQueue<>();
    int i = 0, res;
    for (res = 0; cur < target; res++) {
        while (i < s.length && s[i][0] <= cur)
            pq.offer(-s[i++][1]);
        if (pq.isEmpty()) return -1;
        cur += -pq.poll();
    }
    return res;
}

Poll multiple elements - slots

public String rearrangeString(String str, int k) {
    if(k<=1){ return str; }
    int[] count = new int[26];
    for(int i=0; i<str.length(); i++){
        count[str.charAt(i)-'a']++;
    }
    PriorityQueue<int[]> pq = new PriorityQueue<>((a,b)->b[0]-a[0]);
    for(int i=0; i<count.length; i++){ pq.add(new int[]{ count[i], i}); }   
    char[] result = new char[str.length()];
    int idx = 0;
    int start = 0;
    while(!pq.isEmpty()){
        int[] num = pq.remove();
        for(int i=0; i<num[0]; i++){
            result[idx] = (char)(num[1]+'a');
            if(idx>0 && result[idx-1]==result[idx]){ return ""; }
            idx+=k;
            if(idx>=str.length()){ idx=++start; }
        }
    }
    return new String(result);
}
public String rearrangeString(String str, int k) {
    for(char c: map.keySet())
        queue.offer(c);
    StringBuilder sb = new StringBuilder();
    int len = str.length();
    while(!queue.isEmpty()){
        int cnt = Math.min(k, len);
        ArrayList<Character> temp = new ArrayList<Character>();
        for(int i=0; i<cnt; i++){
            if(queue.isEmpty())//\\
                return "";
            char c = queue.poll();
            sb.append(String.valueOf(c));
            map.put(c, map.get(c)-1);
            if(map.get(c)>0){
                temp.add(c);
            }
            len--;
        }
        for(char c: temp)
            queue.offer(c);
    }
    return sb.toString();
}
public int leastInterval(char[] tasks, int n) {
    Map<Character, Integer> counts = new HashMap<Character, Integer>();
    for (char t : tasks) {
        counts.put(t, counts.getOrDefault(t, 0) + 1);
    }
    PriorityQueue<Integer> pq = new PriorityQueue<Integer>((a, b) -> b - a);
    pq.addAll(counts.values());
    int alltime = 0;
    int cycle = n + 1;
    while (!pq.isEmpty()) {
        int worktime = 0;
        List<Integer> tmp = new ArrayList<Integer>();
        for (int i = 0; i < cycle; i++) {
            if (!pq.isEmpty()) {
                tmp.add(pq.poll());
                worktime++;
            }
        }
        for (int cnt : tmp) {
            if (--cnt > 0) {
                pq.offer(cnt);
            }
        }
        alltime += !pq.isEmpty() ? cycle : worktime;
    }    
    return alltime;
}

Min/MaxHeap(TreeSet)

BFS + PriorityQueue

Dijkstra

Examples

public int kthSmallest(final int[][] matrix, int k) {
    int c = 0;
    PriorityQueue<int[]> queue = new PriorityQueue<>(
        k, (o1, o2) -> matrix[o1[0]][o1[1]] - matrix[o2[0]][o2[1]]);
    queue.offer(new int[] {0, 0});
    while (true) {
        int[] pair = queue.poll();
        if (++c == k) {
            return matrix[pair[0]][pair[1]];
        }
        if (pair[0] == 0 && pair[1] + 1 < matrix[0].length) {
            queue.offer(new int[] {0, pair[1] + 1});
        }
        if (pair[0] + 1 < matrix.length) {
            queue.offer(new int[] {pair[0] + 1, pair[1]});
        }
    }
}
// O(KlogK)
public List<int[]> kSmallestPairs(int[] nums1, int[] nums2, int k) {
    PriorityQueue<int[]> que = new PriorityQueue<>((a,b)->a[0]+a[1]-b[0]-b[1]);
    List<int[]> res = new ArrayList<>();
    if(nums1.length==0 || nums2.length==0 || k==0) return res;
    for(int i=0; i<nums1.length && i<k; i++) que.offer(new int[]{nums1[i], nums2[0], 0});
    while(k-- > 0 && !que.isEmpty()){
        int[] cur = que.poll();
        res.add(new int[]{cur[0], cur[1]});
        if(cur[2] == nums2.length-1) continue;
        que.offer(new int[]{cur[0],nums2[cur[2]+1], cur[2]+1});
    }
    return res;
}

public List<int[]> kSmallestPairs(int[] nums1, int[] nums2, int k) {
    List<int[]> res = new LinkedList<>();
    if(nums1==null || nums1.length==0 || nums2==null || nums2.length==0) {
        return res;
    }
    PriorityQueue<int[]> minQ = new PriorityQueue<>(new Comparator<int[]>(){
        public int compare(int[] pair1, int[] pair2) {
            return (nums1[pair1[0]]+nums2[pair1[1]])-(nums1[pair2[0]]+nums2[pair2[1]]);
        }
    });
    minQ.offer(new int[]{0, 0});
    while (k>0 && !minQ.isEmpty()) {
        int[] pair=minQ.poll();
        int i = pair[0];
        int j = pair[1];
        res.add(new int[]{nums1[i], nums2[j]});
        k--;
        if(j+1<nums2.length) {
            minQ.offer(new int[]{i, j+1});
        }
        if(j==0 && i+1<nums1.length){
            minQ.offer(new int[] {i+1, 0});
        }
    }
    return res;
}

Labels

adsense (5) Algorithm (69) Algorithm Series (35) Android (7) ANT (6) bat (8) Big Data (7) Blogger (14) Bugs (6) Cache (5) Chrome (19) Code Example (29) Code Quality (7) Coding Skills (5) Database (7) Debug (16) Design (5) Dev Tips (63) Eclipse (32) Git (5) Google (33) Guava (7) How to (9) Http Client (8) IDE (7) Interview (88) J2EE (13) J2SE (49) Java (186) JavaScript (27) JSON (7) Learning code (9) Lesson Learned (6) Linux (26) Lucene-Solr (112) Mac (10) Maven (8) Network (9) Nutch2 (18) Performance (9) PowerShell (11) Problem Solving (11) Programmer Skills (6) regex (5) Scala (6) Security (9) Soft Skills (38) Spring (22) System Design (11) Testing (7) Text Mining (14) Tips (17) Tools (24) Troubleshooting (29) UIMA (9) Web Development (19) Windows (21) xml (5)