Showing posts with label Company - LinkedIn. Show all posts
Showing posts with label Company - LinkedIn. Show all posts

String Replace - Linkedin


Implement 28 - Implement strStr()
http://wxx5433.github.io/replace.html
function replace(string orig, string find, string repl)
-- replaces every instances of string find with string repl
-- returned the modified string
  1. After one replacing, if the suffix of replaced string is the prefix of the find string, should we replace again? For instance, replace("babcc", "abc", "cab"). We first change it to "bcabc", should we change it to "bccab" or not?

Analysis

We need to first count how many times the pattern have appeared in the original string. Otherwise, we need to copy the char array many times each time we replace a string. (Since len(find) can be different from len(repl)).

Complexity

Time: Suppose len(orig) = m, len(find) = n, then we need O(mn) time to count and O(m + count*n) time to replace.
Space: O(m), we need extra space to store the start index of a found pattern in the original string.
    public static String replace(String orig, String find, String repl) {
        List<Integer> index = findPattern(orig, find);
        int count = index.size();
        // compute length after replacement
        int newLen = orig.length() + count * (repl.length() - find.length());
        char[] result = new char[newLen];
        // replace
        int i = 0, k = 0;
        int resultIndex = 0;
        while( i < orig.length()) {
            if (k < count && i == index.get(k)) {
                for (int j = 0; j < repl.length(); ++j) {
                    result[resultIndex++] = repl.charAt(j);
                }
                ++k;
                i += find.length();
            } else {
                result[resultIndex++] = orig.charAt(i++);
            }
        }
        return new String(result);
    }

    /**
     * find how many times the pattern string have appeared in the orig string
     * @param orig original string
     * @param find pattern string to find
     * @return a list of the start index of a fuond pattern in the original string
     */
    private static List<Integer> findPattern(String orig, String find) {
        List<Integer> index = new ArrayList<Integer>();
        int i = 0, j = 0;
        // count how many times "find" have appeared
        while (i + find.length() <= orig.length()) {
            int k = i;
            j = 0;
            while (j < find.length()) {
                if (orig.charAt(k) != find.charAt(j)) {
                    break;
                }
                ++k;
                ++j;
            }
            if (j == find.length()) {
                index.add(i);
                i += find.length();
            } else {
                ++i;
            }
        }
        return index;
    }





Find Depth - Linkedin


http://wxx5433.github.io/find-depth.html
Consider this string representation for binary trees. Each node is of the form (lr), where l represents the left child and r represents the right child. If l is the character 0, then there is no left child. Similarly, if r is the character 0, then there is no right child. Otherwise, the child can be a node of the form (lr), and the representation continues recursively. For example: (00) is a tree that consists of one node. ((00)0) is a two-node tree in which the root has a left child, and the left child is a leaf. And ((00)(00)) is a three-node tree, with a root, a left and a right child.
Write a function that takes as input such a string, and returns -1 if the string is malformed, and the depth of the tree if the string is well-formed.
For instance:
  find_depth('(00)') -> 0 
  find_depth('((00)0)') -> 1 
  find_depth('((00)(00))') -> 1 //2?
  find_depth('((00)(0(00)))') -> 2 
  find_depth('((00)(0(0(00))))') -> 3 
  find_depth('x') -> -1 
  find_depth('0') -> -1 
  find_depth('()') -> -1 
  find_depth('(0)') -> -1 
  find_depth('(00)x') -> -1 
  find_depth('(0p)') -> -1

Analysis

We can substitute all occurence "(00)" to "0" in the string, this decrease the tree height by one. We repeatedly do this unitl no change during two iteration.
If the final result is "0", then it is a valid tree, otherwise, invalid.

Complexity

Time: O(n * depth)
Space: O(n)

public static int getLength(String str) {
    int depth = -1;
    while (!str.equals("0")) {
        String newStr = str.replace("(00)", "0");
        if (newStr.equals(str)) {
            return -1;
        }
        str = newStr;
        ++depth;
    }
    return depth;
}

public static int getLength2(String str) {
    int depth = -1;
    char[] pattern = {'(', '0', '0', ')'};
    char[] strArr = str.toCharArray();
    while (strArr.length != 1) {
        List<Integer> points = new ArrayList<Integer>();
        int start = 0;
        while (start + 3 < strArr.length) { // find all pattern
            int i = start;
            while (i < start + 4) {
                if (strArr[i] != pattern[i - start]) {
                    break;
                }
                ++i;
            }
            if (i - start == 4) {
                points.add(start);
                start += 4;
            } else {
                ++start;
            }
        }
        if (points.size() == 0) {  // cannot change anymore
            break;
        }
        // substitute all pattern
        char[] newArr = new char[strArr.length - points.size()*3];
        int j = 0;
        int k = 0;
        while (j < strArr.length) {
            if (k == points.size()) {
                newArr[j - k * 3] = strArr[j++];
            } else if (j == points.get(k)) {
                newArr[j - k * 3] = '0';
                ++k;
                j += 4;
            } else {
                newArr[j - k * 3] = strArr[j++];
            }
        }
        strArr = newArr;
        ++depth;
    }
    if (depth == -1 || strArr.length != 1 || strArr[0] != '0') {
        return -1;
    }
    return depth;
}
https://github.com/prasanthj/algorithms/blob/master/src/main/java/edu/osu/cse/StringBinaryTreeDepth.java
public static int getTreeDepth(String inp) {
  if(inp == null) {
    return -1;
  }
 
  if(inp.length() < 4) {
    return -1;
  }
 
  if(inp.charAt(0) != '(' || inp.charAt(inp.length() -1) != ')') {
    return -1;
  }
 
  int depth = -1;
  int zeroCount = 0;
  Stack<Character> stack = new Stack<Character>();
  for(int i=0; i<inp.length(); i++) {
    char c = inp.charAt(i);
    if(c == '(') {
      stack.push(c);
      if(stack.size() > depth) {
        depth = stack.size();
      }
      zeroCount = 0;
    } else if(c == ')') {
      stack.pop();
      zeroCount = 0;
    } else {
      if( c != '0') {
        return -1;
      } else {
        zeroCount += 1;
        if(zeroCount > 2) {
          return -1;
        }
      }
    }
  }
 
  // invalid pattern
  if(stack.size() > 0) {
    return -1;
  }
 
  return depth-1;
}

Generate number - Linkedin


http://wxx5433.github.io/generate-number.html
There is a particular sequence that only uses numbers 1, 2, 3, 4 and no two adjacent numbers are the same.
Write a program that given n1 1s, n2 2s, n3 3s, n4 4s will output the number of such sequences using all these numbers.
Output your answer modulo 1000000007 (10^9 + 7).

Analysis

We can use DFS to find the result. Each time we try to append a number, we check if it is the same as previous number. If it is, then it's invalid.

Complexity

Time: O(4^len), len is the totally lengt
Space: O(len), the length of the path DFS will search.
There is a particular sequence only uses the numbers 1, 2, 3, 4 and no two adjacent numbers are the same.
Write a program that given n1 1s, n2 2s, n3 3s, n4 4s will output the number of such sequences using all these numbers.
Output your answer modulo 1000000007 (10^9 + 7).
Solution 1: the easy way to do it would be using recursion and back trace.  if count of 1 is greater than 0 and the string’s end is not 1, try 1 and back trace, so do 2, 3, 4.
- DP + cache? Map: key is string: "n1-n2-n3-n4"
        private int count = 0;
        public int Sequence(int n1, int n2, int n3, int n4)
        {
            this.SequenceRecursion(n1, n2, n3, n4, string.Empty);

            return count;
        }

        private bool SequenceRecursion(int n1, int n2, int n3, int n4, string str)
        {
            if (n1 == 0 && n2 == 0 && n3 == 0 && n4 == 0)
            {
                count++;
                return true;
            }

            if (str.Length == 0 || (str.Length > 0 && n1 > 0 && !str[str.Length - 1].Equals('1')))
            {
                str += "1";
                this.SequenceRecursion(n1 - 1, n2, n3, n4, str);
                str = str.Substring(0, str.Length - 1);
            }

            if (str.Length == 0 || (str.Length > 0 && n2 > 0 && !str[str.Length - 1].Equals('2')))
            {
                str += "2";
                this.SequenceRecursion(n1, n2 - 1, n3, n4, str);
                str = str.Substring(0, str.Length - 1);
            }

            if (str.Length == 0 || (str.Length > 0 && n3 > 0 && !str[str.Length - 1].Equals('3')))
            {
                str += "3";
                this.SequenceRecursion(n1, n2, n3 - 1, n4, str);
                str = str.Substring(0, str.Length - 1);
            }

            if (str.Length == 0 || (str.Length > 0 && n4 > 0 && !str[str.Length - 1].Equals('4')))
            {
                str += "4";
                this.SequenceRecursion(n1, n2, n3, n4 - 1, str);
                str = str.Substring(0, str.Length - 1);
            }

            return false;
        }
Solution 2: if we use 4 dimension arrays to store how many number of particular sequence without adjacent. It would save a lot of time.
dp1[i][j][k][l] : how many number of particular sequence without adjacent end with 1 and has i 1s, j 2s, k 3s, l 4s.
dp2[i][j][k][l] : how many number of particular sequence without adjacent end with 2 and has i 1s, j 2s, k 3s, l 4s.
So dp1[i][j][k][l] = dp2[i – 1][j][k][l] + dp3[i – 1][j][k][l] +dp4[i – 1][j][k][l]; dp1 would be the sum of i – 1 1s end with 2(dp2), 3(dp3), 4(dp4);
        public int Sequence2(int n1, int n2, int n3, int n4)
        {
            var dp1 = new int[n1 + 1, n2 + 1, n3 + 1, n4 + 1];
            var dp2 = new int[n1 + 1, n2 + 1, n3 + 1, n4 + 1];
            var dp3 = new int[n1 + 1, n2 + 1, n3 + 1, n4 + 1];
            var dp4 = new int[n1 + 1, n2 + 1, n3 + 1, n4 + 1];

            const int MOD = 1000000007;
            dp1[1, 0, 0, 0] = 1;
            dp2[0, 1, 0, 0] = 1;
            dp3[0, 0, 1, 0] = 1;
            dp4[0, 0, 0, 1] = 1;

            for (int i = 0; i <= n1; i++)
            {
                for (int j = 0; j <= n2; j++)
                {
                    for (int k = 0; k <= n3; k++)
                    {
                        for (int l = 0; l <= n4; l++)                                        {                             
                            if (i + j + k + l > 1)
                            {
                                if (i > 0) dp1[i, j, k, l] = dp2[i - 1, j, k, l] + dp3[i - 1, j, k, l] + dp4[i - 1, j, k, l] % MOD;
                                if (j > 0) dp2[i, j, k, l] = dp1[i, j - 1, k, l] + dp3[i, j - 1, k, l] + dp4[i, j - 1, k, l] % MOD;
                                if (k > 0) dp3[i, j, k, l] = dp2[i, j, k - 1, l] + dp1[i, j, k - 1, l] + dp4[i, j, k - 1, l] % MOD;
                                if (l > 0) dp4[i, j, k, l] = dp2[i, j, k, l - 1] + dp3[i, j, k, l - 1] + dp1[i, j, k, l - 1] % MOD;
                            }
                        }
                    }

                }
            }
            return dp1[n1, n2, n3, n4] + dp2[n1, n2, n3, n4] + dp3[n1, n2, n3, n4] + dp4[n1, n2, n3, n4] % MOD;
        }

public static void generateNumber(List<Integer> result, String number, int[] count, int len) {
    if (number.length() == len) {
        BigInteger num = new BigInteger(number).mod(new BigInteger("1000000007"));
        result.add(new Integer(num.toString()));
        return ;
    }

    for (int i = 0; i < 4; ++i) {
        int num = i + 1;
        if (count[i] > 0 && (number.length() == 0 
                || number.charAt(number.length() - 1) - '0' != num)) {
            --count[i];
            generateNumber(result, number + num, count, len);
            ++count[i];
        }
    }
}
https://www.careercup.com/question?id=5653460783464448

Linkedin Interview Part 3


reverse版本的nested integer
word distance

isomorphic str,没有followup。 想起地里之前有帖子说面试官说要twoway mapping, 说了两个map的解法,被吐槽空间复杂度太高。。。
search range.
http://www.1point3acres.com/bbs/thread-135904-1-1.html
1. Two sum III(leetcode)
2. bounded queue(consumer, producer )
还问了一些基本概念,virtual memeory, thread, process 区别等。

Phone interview2 :
1. merge two sorted inked list(从大到小)
2. 一个文件,有很多行string, 从里面提取所以valid的Ip address.
 (我当时用C++写的,有点麻烦,面试官最后给我看了,python代码,就两行,哎!)


Onsite Interview:
1. Talk with director.-
2. coding:
1. 给一个string, app[1,2].corp[3,4].com 要求返回:
app1.corp3.com, app2.corp3.com, app1.corp4.com, app2.corp4.com. 组合题变种。
2。给一个map, 里面是所有文件的dependency, 找出给定一个文件的所有dependency. 图的dfs遍历,
注意cycle的处理。没啥难的。

3. Lunch with Manager
4. Design: monitor systesm. 后半部分答的不好,和面试官不再一个频道上,估计挂了。
5. Technical communication.
6. coding: 1. print all factors of n(老题), 2.  Is valid BST(讨论了几种方法) (这轮也没啥难度)
http://www.1point3acres.com/bbs/thread-167542-1-1.html
1. implement singleton pattern,要注意constrctor是private
2. binary tree level order print,我用queue bfs做的,follow up是还有其他解法么,我说了可以用dfs
1. search a number in a 2-d array,行都是sorted的,每行第一个比前一行最后一个要大,转换成一维的array做 search就行了。面试官说size=row*column-1如果overflow怎么办,我说把int改成long就好了。

楼主遇到的是https://leetcode.com/problems/search-a-2d-matrix/,就按照一维数组做就好,坐标转换一下,就OK, O(1) Extra Space O(log(mn)) time

从右上角那个方法是对于https://leetcode.com/problems/search-a-2d-matrix-ii/
2. implement stack with pop(), push() and findmiddle() with O(1) time, 一开始我想用array做,面试官提醒resize的时候会有额外操作,就改用double linked list了。维护两个pointer,top和middle。follow up就是test case。
第二题用一个叫middle的pointer,findmiddle的时候就返回pointer,pop和push的时候要update middle的位置。
http://www.1point3acres.com/bbs/thread-166399-1-1.html
Blocking Bounded Queue
实现一个线程安全的put和get,这个之前看面经的时候练习过,不管怎么样写出来了 - - 
Follow up是 multi-put,这个没写出来,之后的30分钟都是在纠结Mutex和condition variable,因为不是非常理解C++多线程,所以应该会挂在这儿

http://www.1point3acres.com/bbs/thread-166389-1-1.html
然后问题是isomorphic string,先判断两个string,follow up是给一堆string, 按组输出isomorphic strings, 输出格式是List<List<String>>。小哥可能比较忙,中途离开了两次。。。
对,判断两个string的时候是true or false. Follow up是给一堆string,让分组输出

http://www.1point3acres.com/bbs/thread-145037-1-1.html
1. 两个华人。Design tiny URL 问了很多细节,最后居然问到了怎么配置memcache, 估计是不揭穿lz的画皮不甘心,不过相信他们是为了找我的亮点吧
2 两个华人
2.1 find range of a number in an array with possible duplicates, 我写的其实有bug, 但是小哥欣然放过,感谢。. from: 1point3acres.com/bbs 
2.2 find all palidrome string by deleting any letter from the given string. 这题比较难,我只做了dfs的bf解, 稍微加了个map trim branch一下。最优解在mitbbs有讨论,大家自己坐电梯去看
http://www.mitbbs.com/article/JobHunting/33053715_3.html-google 1point3acres
3. tech communication. 一华一印,被强烈bs. visit 1point3acres.com for more.
4. 一中一印 leetcode原题 most points on same line. 但是leetcode的斜率用float直接表示,这里被要求用更好方式表示,搞了个 横纵坐标的类,写gcd, 改hashcode, equals等吭哧半天。小中是一脸恨铁不成钢,不停提示我,恨不得上来帮我写,烙印是到处找茬,说你说lcd(lz没接受过正规cs教育, gcd说成lcd), 是不是还有led呢,blahblah。
http://www.1point3acres.com/bbs/thread-148200-1-1.html
1. Maximum Subarray,leetcode原题,基本的dp,应该很好写吧,也练过至少1次了。。然而lz我第一次真正意义上的技术电面,有点紧张,于是没有考虑数组为空的情况,被指出来,遂加上。。. 鐣欏鐢宠璁哄潧-涓€浜╀笁鍒嗗湴
2. Maximum product Subarray,leetcode原题,又是基本的dp,也应该很好写吧,也练过至少1次了。。然而。。。我一开始说思路的时候又没100%对上点,大哥遂说,算了算了,你先写吧。。。一开始写发现之前说的哪有漏洞了,改之。。。惊心胆战中好歹完成了。。

ml:
问的非常多且杂但是都不精,先从binary classifier是啥到举例,到你最喜欢哪个算法,我说logistic regression,于是开始问你介绍一下呀,我扯到了logistic function,具体他怎么问的我忘记了,只记得我一直在说指数函数、0、1、0.5边界值之类的。。。再后来他说怎么训练参数,就扯到了MLE,cost funtion,gradient descent,他问梯度下降是什么呀,学习率什么含义啊,还有regularization,问regularization是啥,我因此扯到了防止overfitting,他借此又问overfitting是啥,怎么解决,我说完后,他借由这几种解决方法拓展到了cross validation和pca(feature selection),于是我又扯扯扯到了pca的定义,他顺便问了一句pca怎么知道取几个component,这个问题我不确定,回答说这是个“pecentage problem"吧?如果想要80%或90%,就取到这个程度好了。。。英文表达真心捉急。。

我面了树的level order和zigzag遍历,ml方面是问了决策树,entropy之类的,还有l1, l2 regularisation,还有简历上的一点东西

http://www.1point3acres.com/bbs/thread-157908-1-1.html
我根本没准备system的东西结果问了一堆问题看来是要跪。。我记得有虚拟内存,事务,进程和线程的区别,进程通信线程通信,答得很差
然后一道design的题。。。。实现一个容器能够randomremove和正常加和删。。。我傻傻用了三个hashmap小哥一步一步引导我走向正确答案不过前面答得太差了估计没戏了
。。。。我真的以为一面是水leetcode的节奏结果就这么跪了。。。。

http://www.1point3acres.com/bbs/thread-159875-1-1.html
一共两轮。。。第一轮是三哥三姐,很和蔼,出的题也不难,一个是带字符的valid 括号,另一个是isomofic string,follow up 是3 个的情况。感觉他们都还蛮开心的,最后问问题,他们也很开心的回答了。。题目都是秒过,然后针对test case 解释了挺长时间。。英语渣~没办法。
第二轮 下午刚面完,一个是merge array,intersecion of two array, 果断秒过,小插曲:以为说的linkedlist,所以把merge linkedlist也写了一遍。。第二题是longest palindromic string (题目说的 subsequence),但是我想成substring了。。 不过事实证明面试官不在乎,你做出来了,并且表达清楚应该就没问题。

[LinkedIn面试]implement the take() and put() of blocking queue


http://www.cnblogs.com/jxlgetter/p/4395115.html
http://tutorials.jenkov.com/java-concurrency/blocking-queues.html
Use two conditions: fullCondition, emptyCondition.
http://tutorials.jenkov.com/java-concurrency/blocking-queues.html
public class BlockingQueue {

  private List queue = new LinkedList();
  private int  limit = 10;

  public BlockingQueue(int limit){
    this.limit = limit;
  }


  public synchronized void enqueue(Object item)
  throws InterruptedException  {
    while(this.queue.size() == this.limit) {
      wait();
    }
    /** This is what comes from the post, but if you notify here, say a 'dequeue()' is waiting, the size would remain at 0 doesn't it? So I would call notify at the end
    if(this.queue.size() == 0) {
      notifyAll();
    }
    **/
    this.queue.add(item);
    notifyAll();
  }


  public synchronized Object dequeue()
  throws InterruptedException{
    while(this.queue.size() == 0){
      wait();
    }
    /** This is what comes from the post, but if you notify here, say a 'enqueue()' is waiting, the size would remain at the limit doesn't it? So I would call notify at the end

    if(this.queue.size() == this.limit){
      notifyAll();
    }
    **/

    Object ret = this.queue.remove(0);
    notifyAll();
    return ret;

  }

}
http://n00tc0d3r.blogspot.com/2013/08/implement-bounded-blocking-queue.html
We use two Reentrant Locks to replace the use of synchronized methods. With separate locks for put and take, a consumer and a producer can access the queue at the same time (if it is neither empty nor full). A reentrant lock provides the same basic behaviors as a Lock does by using synchronized methods and statements. Beyond that, it is owned by the thread last successfully locking and thus when the same thread invokes lock() again, it will return immediately without lock it again.

Together with lock, we use Condition to replace the object monitor (wait and notifyAll). A Condition instance is intrinsically bound to a lock. Thus, we can use it to signal threads that are waiting for the associated lock. Even better, multiple condition instances can be associated with one single lock and each instance will have its own wait-thread-set, which means instead of waking up all threads waiting for a lock, we can wake up a predefined subset of such threads. Similar to wait()Condition.await() can atomically release the associated lock and suspend the current thread.

We use Atomic Integer for the count of elements in the queue to ensure that the count will be updated atomically.
public class BoundedBlockingQueue<E> {  
   private final Queue<E> queue = new LinkedList<E>();  
   private final int capacity;  
   private final AtomicInteger count = new AtomicInteger(0);  
   
   private final ReentrantLock putLock = new ReentrantLock();  
   private final ReentrantLock takeLock = new ReentrantLock();  

   private final Condition notFull = putLock.newCondition();
   private final Condition notEmpty = takeLock.newCondition();

   public BoundedBlockingQueue(int capacity) {  
     if (capacity <= 0)  throw new InvalidArgumentException("The capacity of the queue must be > 0.");
     this.capacity = capacity;  
   }  
   
   public int size() {  
     return count.get();  
   }  
   
   public void add(E e) throws RuntimeException {  
     if (e == null) throw new NullPointerException("Null element is not allowed.");  
   
     int oldCount = -1;
     putLock.lock();  
     try {  
       // we use count as a wait condition although count isn't protected by a lock
       // since at this point all other put threads are blocked, count can only
       // decrease (via some take thread).
       while (count.get() == capacity) notFull.await();  
   
       queue.add(e);  
       oldCount = count.getAndIncrement();  
       if (oldCount + 1 < capacity) {
         notFull.signal(); // notify other producers for count change 
       }
     } finally {  
       putLock.unlock();  
     }  

     // notify other waiting consumers
     if (oldCount == 0) {
       takeLock.lock();
       try {
         notEmpty.signal();
       } finally {
         takeLock.unlock();
       }
     }
   }  
   
   public E remove() throws NoSuchElementException {  
     E e;  
   
     int oldCount = -1;
     takeLock.lock();  
     try {  
       while (count.get() == 0) notEmpty.await();  
   
       e = queue.remove();  
       oldCount = count.getAndDecrement();  
       if (oldCount > 1) { //??? ==1
         notEmpty.signal(); // notify other consumers for count change 
       }
     } finally {  
       takeLock.unlock();  
     }  

     // notify other waiting producers
     if (oldCount == capacity) {
       putLock.lock();
       try {
         notFull.signal();
       } finally {
         putLock.unlock();
       }
     }

     return e;
   } 
 
   /* Retrieves, but does not remove, the head of this queue, or returns null if this queue is empty. */
   public E peek() {  
     if (count.get() == 0) return null;  
   
     takeLock.lock();  
     try {  
       return queue.peek();  
     } finally {  
       takeLock.unlock();  
     }  
   }  
 }  


One shortcoming of using synchronization is that it only allow one thread access the queue at the same time, either consumer or producer.)

Plus, we need to use notifyAll instead of notify since there could be multiple waiting producers and consumers and notify can wake up any thread which could be a producer or a consumer. This stackoverflow post gives a detailed example to explainnotify vs. notifyAll.

Notice that if the queue was empty before add or full before remove, we need to notify other waiting threads to unblock them.
We only need to emit such notifications in the above two cases since otherwise there cannot be any waiting threads.
public class BoundedBlockingQueue<E> {  
   private final Queue<E> queue = new LinkedList<E>();  
   private final int capacity;  
   private final AtomicInteger count = new AtomicInteger(0);  

   public BoundedBlockingQueue(int capacity) {  
     if (capacity <= 0)  throw new InvalidArgumentException("The capacity of the queue must be > 0.");
     this.capacity = capacity;  
   }  
   
   public int size() {  
     return count.get();  
   }  
   
   public synchronized void add(E e) throws RuntimeException {  
     if (e == null) throw new NullPointerException("Null element is not allowed.");  
   
     int oldCount = -1;
     while (count.get() == capacity) wait();  
   
     queue.add(e);  
     oldCount = count.getAndIncrement();  
     if (oldCount == 0) {
       notifyAll(); // notify other waiting threads (could be producers or consumers)  
     }
   }  
   
   public synchronized E remove() throws NoSuchElementException {  
     E e;  
   
     int oldCount = -1;
     while (count.get() == 0) wait();  
  
     e = queue.remove();  
     oldCount = count.getAndDecrement();  
     if (oldCount == this.capacity) {
       notifyAll(); // notify other waiting threads (could be producers or consumers)  
     }
     return e;
   } 
 
   /* Retrieves, but does not remove, the head of this queue, or returns null if this queue is empty. */
   public E peek() {  
     if (count.get() == 0) return null;  
     synchronized(this) {
       return queue.peek();  
     }
   }  
 }  
http://baozitraining.org/blog/design-and-implement-a-blocking-queue/
Condition “Condition factors out the Object monitor methods (wait, notify and notifyAll) into distinct objects to give the effect of having multiple wait-sets per object, by combining them with the use of arbitrary Lock implementations. Where a Lock replaces the use of synchronized methods and statements, a Condition replaces the use of the Object monitor methods. Conditions (also known as condition queues or condition variables) provide a means for one thread to suspend execution (to "wait") until notified by another thread that some state condition may now be true. Because access to this shared state information occurs in different threads, it must be protected, so a lock of some form is associated with the condition. The key property that waiting for a condition provides is that it atomically releases the associated lock and suspends the current thread, just like Object.wait. A Condition instance is intrinsically bound to a lock. To obtain a Condition instance for a particular Lock instance use its newCondition() method.”
We use two condition as two waiting queues where we put the suspended thread. One is notFull queue which contains all producer thread wait for the not full signal. notEmpty queue contains all consumer threads wait for the not empty signal. I am using another Lock to assure pushList can be finished atomically.
public class BoundedBlockingQueue<E> {

 private int capacity;
 private Queue<E> queue;
 private Lock lock = new ReentrantLock();
 private Lock pushLock = new ReentrantLock();
 private Condition notFull = this.lock.newCondition();
 private Condition notEmpty = this.lock.newCondition();
    
 // only initialize this queue once and throws Exception if the user is
 // trying to initialize it multiple t times.
 public void init(int capacity) throws Exception {
     this.lock.lock();
     try{
         if(this.queue == null){
             this.queue = new LinkedList<>();
             this.capacity = capacity;
         } else {
             throw new Exception();
         }
     }finally{
         this.lock.unlock();
     }
 }

 // throws Exception if the queue is not initialized
 public void push(E obj) throws Exception {
     this.pushLock.lock();
      this.lock.lock();
     try{
         while(this.capacity == this.queue.size())
             this.notFull.wait();
         this.queue.add(obj);
         this.notEmpty.notifyAll();
     }finally{
         this.lock.unlock();
         this.pushLock.lock();
     }
 }

 // throws Exception if the queue is not initialized
 public E pop() throws Exception {
     this.lock.lock();
     try{
         while(this.capacity==0)
             this.notEmpty.wait();
         E result = this.queue.poll();
         notFull.notifyAll();
         return result;
     }finally{
         this.lock.unlock();
     }
 }

 // implement a atomic putList function which can put a list of object
 // atomically. By atomically i mean the objs in the list should next to each
 // other in the queue. The size of the list could be larger than the queue
 // capacity.
 // throws Exception if the queue is not initialized
 public void pushList(List<E> objs) throws Exception {
     this.pushLock.lock();
     this.lock.lock();
     try{
         for(E obj : objs){
             while(this.queue.size() == this.capacity)
                 this.notFull.wait();
             this.queue.add(obj);
             this.notEmpty.notifyAll();
         }
     }finally{
         this.lock.unlock();
         this.pushLock.unlock();
     }
 }
}
http://baptiste-wicht.com/posts/2010/09/java-concurrency-part-5-monitors-locks-and-conditions.html
  1. The two methods are protected with the lock to ensure mutual exclusion
  2. Then we use two conditions variables. One to wait for the buffer to be not empty and an other one to wait for the buffer to be not full.
  3. You can see that I have wrapped the await operation on a while loop. This is to avoid signal stealers problem that can occurs when using Signal & Continue
public class BoundedBuffer {
    private final String[] buffer;
    private final int capacity;

    private int front;
    private int rear;
    private int count;

    private final Lock lock = new ReentrantLock();

    private final Condition notFull = lock.newCondition();
    private final Condition notEmpty = lock.newCondition();

    public BoundedBuffer(int capacity) {
        super();

        this.capacity = capacity;

        buffer = new String[capacity];
    }

    public void deposit(String data) throws InterruptedException {
        lock.lock();

        try {
            while (count == capacity) {
                notFull.await();
            }

            buffer[rear] = data;
            rear = (rear + 1) % capacity;
            count++;

            notEmpty.signal();
        } finally {
            lock.unlock();
        }
    }

    public String fetch() throws InterruptedException {
        lock.lock();

        try {
            while (count == 0) {
                notEmpty.await();
            }

            String result = buffer[front];
            front = (front + 1) % capacity;
            count--;

            notFull.signal();

            return result;
        } finally {
            lock.unlock();
        }
    }
}
http://stackoverflow.com/questions/20110013/implement-your-own-blocking-queue-in-java

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