Thread-Safe Concurrent Linked List
Problem statement
Implement a singly linked list of integers that many threads can use at the same time. It starts empty and supports insert, delete, and read. Positions start at 0, and repeated values are separate nodes.
For this exercise, the calls arrive as two lists. operations[i] names a call and args[i] holds its arguments. The lists show one legal order of the concurrent calls, so each call must see the complete list left by the call before it, with no partial change showing.
"INSERT"with[index, value]: addvalueso that it sits at positionindex, and return1. Values at that position and later move back by one. Anindexequal to the current size adds to the end. Ifindexis greater than the size, return-1and change nothing."DELETE"with[index]: remove the node at positionindexand return its value. If no node is there, return-1and change nothing."READ"with[index]: return the value at positionindexand leave the list as it is. If no node is there, return-1.
Return an array with one result for each operation, in order.
The interview focused on making these calls safe under real concurrency. Try hand-over-hand locking: take the next node's lock before you release the current one, and keep a sentinel node before the first position. The judge runs your code on one thread, so it checks the results of each call and cannot check your locks or how well they scale.
Function
runConcurrentLinkedList(operations: String[], args: int[][]) → int[]Examples
Example 1
operations = ["INSERT","INSERT","INSERT","READ","DELETE","READ"]args = [[0,10],[1,30],[1,20],[1],[0],[0]]return = [1,1,1,20,10,20]Three inserts build the list. The third insert puts 20 at position 1, so the list is [10, 20, 30]. READ at position 1 returns 20. DELETE at position 0 returns 10 and leaves [20, 30], so the last READ at position 0 returns 20.
Example 2
operations = ["READ","DELETE","INSERT","INSERT","READ"]args = [[0],[0],[1,5],[0,5],[0]]return = [-1,-1,-1,1,5]The list is empty, so READ and DELETE at position 0 both return -1. INSERT at index 1 also returns -1, because the size is 0. INSERT at index 0 works, and READ at position 0 then returns 5.
Example 3
operations = ["INSERT","INSERT","INSERT","DELETE","READ","READ","READ"]args = [[0,7],[0,7],[2,0],[1],[0],[1],[2]]return = [1,1,1,7,7,0,-1]The inserts build [7, 7, 0]. The two 7 values are separate nodes. DELETE at position 1 returns 7 and leaves [7, 0]. READ at position 0 returns 7, and READ at position 1 returns the stored 0. Position 2 is now empty, so its READ returns -1.
Constraints
1 <= operations.length <= 500args.length == operations.lengthoperations[i]is"INSERT","DELETE", or"READ".args[i]is[index, value]for"INSERT"and[index]for"DELETE"and"READ".0 <= index <= 5000 <= value <= 10^9