Using hashmap is much easier to implement the code.
O(n) time complexity and O(n) space
First, get the regular linked list and put the node pair in the hashmap
Second, set each node with correct random pointer.
public RandomListNode copyRandomList(RandomListNode head) {
Map<RandomListNode, RandomListNode> map = new HashMap<>();
RandomListNode p = head;
RandomListNode dummy = new RandomListNode(0);
RandomListNode q = dummy;
while (p!=null) {
q.next = new RandomListNode(p.label);
map.put(p, q.next);
p = p.next;
q = q.next;
}
p = head;
q = dummy;
while (p != null) {
q.next.random = map.get(p.random);
p = p.next;
q = q.next;
}
return dummy.next;
}
Better solution with O(n) time complexity and O(1) space.
public RandomListNode copyRandomList(RandomListNode head) {
RandomListNode p = head;
//copy the node in the list
while (p != null) {
RandomListNode next = p.next;
RandomListNode copy = new RandomListNode(p.label);
p.next = copy;
copy.next = next;
p = next;
}
//Set the random pointer correctly
p = head;
while (p != null) {
p.next.random = (p.random != null) ? p.random.next : null;
p = p.next.next;
}
//Reset the list to the original one
p = head;
RandomListNode headCopy = (p!=null) ? p.next : null;
while (p != null) {
RandomListNode copy = p.next;
p.next = copy.next;
p = p.next;
copy.next = (p != null) ? p.next : null;
}
return headCopy;
}
Tuesday, December 30, 2014
Monday, December 22, 2014
Compare Version Number LeetCode
Integer.valueOf("01") can handle conversion from string to integer.
public int compareVersion(String version1, String version2) {
String[] version1Res = version1.split("\\.");
String[] version2Res = version2.split("\\.");
int idx = Math.max(version1Res.length, version2Res.length);
int i=0;
while (i < idx) {
int c1 = i < version1Res.length ? Integer.valueOf(version1Res[i]):0;
int c2 = i < version2Res.length ? Integer.valueOf(version2Res[i]):0;
if (c1>c2) {
return 1;
} else if (c1<c2) {
return -1;
}
i++;
}
return 0;
}
public int compareVersion(String version1, String version2) {
String[] version1Res = version1.split("\\.");
String[] version2Res = version2.split("\\.");
int idx = Math.max(version1Res.length, version2Res.length);
int i=0;
while (i < idx) {
int c1 = i < version1Res.length ? Integer.valueOf(version1Res[i]):0;
int c2 = i < version2Res.length ? Integer.valueOf(version2Res[i]):0;
if (c1>c2) {
return 1;
} else if (c1<c2) {
return -1;
}
i++;
}
return 0;
}
Majority Element
Method 1: HashMap is always a quick solution for this kind of problems.
public int majorityElement(int[] num) {
Map<Integer,Integer> hm = new HashMap<Integer, Integer>();
for (int i=0; i<num.length; i++) {
if (!hm.containsKey(num[i])) {
hm.put(num[i], 1);
} else {
hm.put(num[i],hm.get(num[i])+1);
if (hm.get(num[i]) > num.length/2) {
return num[i];
}
}
}
return num[0];
}
Method 2: Bit Manipulation
It is similar to Single Number.
public int majorityElement(int[] num) {
//Bit manipulation
int[] countsPerBit = new int[32];
int result = 0;
for (int i=0; i<32; i++) {
int count = 0;
for (int j=0; j<num.length; j++) {
if((num[j]>>i&1) ==1) {
count++;
}
}
if (count > num.length/2) {
result |= (1<<i);
}
}
return result;
}
Method 3: Moore Voting Algorithm
This is super cool.
public int majorityElement(int[] num) {
//Moore voting algorithm
int elem = 0;
int count = 0;
for (int i=0; i<num.length; i++) {
if (count == 0) {
elem = num[i];
count = 1;
} else {
if (elem == num[i]) {
count++;
} else {
count--;
}
}
}
return elem;
}
Thursday, December 11, 2014
Evaluate Reverse Polish Notation LeetCode
Use stack to contain all the values. When we get the operators, we pop up two values for operation.
It's easy. It has lots of follow up question.
public int evalRPN(String[] tokens) {
if (tokens==null || tokens.length == 0) return 0;
if (tokens.length == 1) return Integer.valueOf(tokens[0]);
Stack<String> stack = new Stack<String>();
String operators = "+-*/";
for (int i=0; i<tokens.length; i++) {
if (!operators.contains(tokens[i])) {
stack.push(tokens[i]);
} else {
int a = Integer.valueOf(stack.pop());
int b = Integer.valueOf(stack.pop());
switch(tokens[i]) {
case "+" : stack.push(String.valueOf(a+b)); break;
case "-" : stack.push(String.valueOf(b-a)); break;
case "*" : stack.push(String.valueOf(a*b)); break;
case "/" : stack.push(String.valueOf(b/a)); break;
}
}
}
return Integer.valueOf(stack.pop());
}
It's easy. It has lots of follow up question.
public int evalRPN(String[] tokens) {
if (tokens==null || tokens.length == 0) return 0;
if (tokens.length == 1) return Integer.valueOf(tokens[0]);
Stack<String> stack = new Stack<String>();
String operators = "+-*/";
for (int i=0; i<tokens.length; i++) {
if (!operators.contains(tokens[i])) {
stack.push(tokens[i]);
} else {
int a = Integer.valueOf(stack.pop());
int b = Integer.valueOf(stack.pop());
switch(tokens[i]) {
case "+" : stack.push(String.valueOf(a+b)); break;
case "-" : stack.push(String.valueOf(b-a)); break;
case "*" : stack.push(String.valueOf(a*b)); break;
case "/" : stack.push(String.valueOf(b/a)); break;
}
}
}
return Integer.valueOf(stack.pop());
}
Intersection of Two LinkedList LeetCode (Important)
1. Find the length of each list
2. Scan from the same length of the short list in the longer list.
It should be O(n) time and O(1) space.
It is not easy for me :(
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
if (headA == null || headB == null) return null;
//Get the length 0f List A
int indexA = 0;
ListNode tempA = headA;
while (tempA != null) {
tempA = tempA.next;
indexA++;
}
//Get the length of List B
int indexB = 0;
ListNode tempB = headB;
while (tempB != null) {
tempB = tempB.next;
indexB++;
}
//Two pointers
ListNode longNode = (indexA > indexB) ? headA : headB;
ListNode shortNode = (longNode == headA) ? headB : headA;
int diff = Math.abs(indexA - indexB);
while (diff > 0) {
longNode = longNode.next;
diff--;
}
while (longNode != null) {
if (longNode.val == shortNode.val) {
return longNode;
}
longNode = longNode.next;
shortNode = shortNode.next;
}
return null;
}
Search 2D Matrix LeetCode (Important)
Very good question.
It can come with lots of follow up.
Step Wise method. I prefer this method. Easy to implement and very good for a quick solution during the interview.
public boolean searchMatrix(int[][] matrix, int target) {
int rowLen = matrix.length;
int colLen = matrix[0].length;
int row = 0;
int col = matrix[0].length-1;
if (matrix[0][0] > target || matrix[rowLen-1][colLen-1] < target) return false;
while (row < rowLen && col >= 0) {
if (matrix[row][col] > target) {
col--;
} else if (matrix[row][col] < target) {
row++;
} else {
return true;
}
}
return false;
}
Binary Search on row and column.
public boolean searchMatrix(int[][] matrix, int target) {
// Note: The Solution object is instantiated only once and is reused by each test case.
int row = searchRow(matrix, 0, matrix.length, target);
int result = Arrays.binarySearch(matrix[row], target);
return result >= 0 ? true : false;
}
private int searchRow(int[][] matrix, int start, int end, int target) {
int mid = (start + end)/2;
if (start == mid) {
return mid;
}
if (matrix[mid][0] <= target) {
return searchRow(matrix, mid, end, target);
} else {
return searchRow(matrix, start, mid, target);
}
}
public boolean searchMatrix(int[][] matrix, int target) {
if (matrix==null || matrix.length==0 || matrix[0].length==0) return false;
//Search the col
int l=0;
int r=matrix.length-1;
while (l<=r) {
int mid = (l+r)/2;
if (matrix[mid][0] == target) return true;
if (matrix[mid][0] > target) {
r = mid - 1;
} else {
l = mid + 1;
}
}
int row = r;
if (row < 0) return false;
//Search the row
l=0;
r=matrix[0].length-1;
while (l<=r) {
int mid = (l+r)/2;
if (matrix[row][mid] == target) return true;
if (matrix[row][mid] > target) {
r = mid - 1;
} else {
l = mid + 1;
}
}
return false;
}
It can come with lots of follow up.
Step Wise method. I prefer this method. Easy to implement and very good for a quick solution during the interview.
public boolean searchMatrix(int[][] matrix, int target) {
int rowLen = matrix.length;
int colLen = matrix[0].length;
int row = 0;
int col = matrix[0].length-1;
if (matrix[0][0] > target || matrix[rowLen-1][colLen-1] < target) return false;
while (row < rowLen && col >= 0) {
if (matrix[row][col] > target) {
col--;
} else if (matrix[row][col] < target) {
row++;
} else {
return true;
}
}
return false;
}
Binary Search on row and column.
public boolean searchMatrix(int[][] matrix, int target) {
// Note: The Solution object is instantiated only once and is reused by each test case.
int row = searchRow(matrix, 0, matrix.length, target);
int result = Arrays.binarySearch(matrix[row], target);
return result >= 0 ? true : false;
}
private int searchRow(int[][] matrix, int start, int end, int target) {
int mid = (start + end)/2;
if (start == mid) {
return mid;
}
if (matrix[mid][0] <= target) {
return searchRow(matrix, mid, end, target);
} else {
return searchRow(matrix, start, mid, target);
}
}
public boolean searchMatrix(int[][] matrix, int target) {
if (matrix==null || matrix.length==0 || matrix[0].length==0) return false;
//Search the col
int l=0;
int r=matrix.length-1;
while (l<=r) {
int mid = (l+r)/2;
if (matrix[mid][0] == target) return true;
if (matrix[mid][0] > target) {
r = mid - 1;
} else {
l = mid + 1;
}
}
int row = r;
if (row < 0) return false;
//Search the row
l=0;
r=matrix[0].length-1;
while (l<=r) {
int mid = (l+r)/2;
if (matrix[row][mid] == target) return true;
if (matrix[row][mid] > target) {
r = mid - 1;
} else {
l = mid + 1;
}
}
return false;
}
Sort Colors LeetCode
Two passes are easy to understand. Count and put all the numbers in.
public void sortColors(int[] A) {
// Note: The Solution object is instantiated only once and is reused by each test case.
if (A == null || A.length == 0) return;
int[] helper = new int[3];
for (int i=0; i<A.length; i++) {
helper[A[i]] ++;
}
int index = 0;
for (int j=0; j<3; j++) {
while (helper[j]-- > 0) {
A[index++] = j;
}
}
}
OK. Let's make it better.
ONE Pass.
index0 and index1 are two pointer for the current location of 0 and 1.
public void sortColors(int[] A) {
// Note: The Solution object is instantiated only once and is reused by each test case.
if (A==null||A.length==0) return;
int ind0 = 0;
int ind1 = 0;
for (int i=0; i<A.length; i++) {
if (A[i] == 0) {
A[i] = 2;
A[ind1++] = 1;
A[ind0++] = 0;
} else if (A[i] == 1) {
A[i] = 2;
A[ind1++] = 1;
}
}
}
public void sortColors(int[] A) {
// Note: The Solution object is instantiated only once and is reused by each test case.
if (A == null || A.length == 0) return;
int[] helper = new int[3];
for (int i=0; i<A.length; i++) {
helper[A[i]] ++;
}
int index = 0;
for (int j=0; j<3; j++) {
while (helper[j]-- > 0) {
A[index++] = j;
}
}
}
OK. Let's make it better.
ONE Pass.
index0 and index1 are two pointer for the current location of 0 and 1.
public void sortColors(int[] A) {
// Note: The Solution object is instantiated only once and is reused by each test case.
if (A==null||A.length==0) return;
int ind0 = 0;
int ind1 = 0;
for (int i=0; i<A.length; i++) {
if (A[i] == 0) {
A[i] = 2;
A[ind1++] = 1;
A[ind0++] = 0;
} else if (A[i] == 1) {
A[i] = 2;
A[ind1++] = 1;
}
}
}
Wednesday, December 10, 2014
Find Minimum in Rotated Sorted Array II LeetCode
Always separate the array for three conditions.
Put equal condition individually.
public int findMin(int[] num) {
int l = 0;
int r = num.length - 1;
int min = num[0];
while (l < r) {
int m = (l+r)/2;
if (num[l] < num[m]) {
min = Math.min(num[l], min);
l = m + 1;
} else if (num[l] > num[m]) {
min = Math.min(num[m], min);
r = m - 1;
} else {
min = Math.min(num[m], min);
l++;
}
}
min = Math.min(num[r], min);
min = Math.min(num[l], min);
return min;
}
Put equal condition individually.
public int findMin(int[] num) {
int l = 0;
int r = num.length - 1;
int min = num[0];
while (l < r) {
int m = (l+r)/2;
if (num[l] < num[m]) {
min = Math.min(num[l], min);
l = m + 1;
} else if (num[l] > num[m]) {
min = Math.min(num[m], min);
r = m - 1;
} else {
min = Math.min(num[m], min);
l++;
}
}
min = Math.min(num[r], min);
min = Math.min(num[l], min);
return min;
}
Search in Rotated Sorted Array LeetCode II
Only One situation need to be done.
When A[L] == A[mid].
public boolean search(int[] A, int target) {
// Note: The Solution object is instantiated only once and is reused by each test case.
int L = 0;
int R = A.length-1;
while (L<=R) {
int mid = (L+R)/2;
if (A[mid] == target) return true;
// Example: 4 5 6 7 8 9 1 2 3
if (A[L] < A[mid]) {
if (A[L]<=target && target < A[mid]) {
R = mid - 1;
} else {
L = mid + 1;
}
}
// Example: 8 9 1 2 3 4 5 6 7
else if (A[L] > A[mid]) {
if (A[mid] < target && target <= A[R]) {
L = mid + 1;
} else {
R = mid - 1;
}
} else {
L++;
}
}
return false;
}
When A[L] == A[mid].
public boolean search(int[] A, int target) {
// Note: The Solution object is instantiated only once and is reused by each test case.
int L = 0;
int R = A.length-1;
while (L<=R) {
int mid = (L+R)/2;
if (A[mid] == target) return true;
// Example: 4 5 6 7 8 9 1 2 3
if (A[L] < A[mid]) {
if (A[L]<=target && target < A[mid]) {
R = mid - 1;
} else {
L = mid + 1;
}
}
// Example: 8 9 1 2 3 4 5 6 7
else if (A[L] > A[mid]) {
if (A[mid] < target && target <= A[R]) {
L = mid + 1;
} else {
R = mid - 1;
}
} else {
L++;
}
}
return false;
}
Find Minimum in Rotate Array LeetCode
Search in Rotated sorted Array
中间值大于起始值,且起始值大于终止值
public int findMin(int[] num) {
int l = 0;
int r = num.length - 1;
int min = num[0];
while (l < r) {
int m = (l+r)/2;
if (num[l] < num[m]) {
min = Math.min(num[l], min);
l = m + 1;
} else if (num[l] > num[m]) {
min = Math.min(num[m], min);
r = m - 1;
} else {
min = Math.min(num[m], min);
l++;
}
}
min = Math.min(num[r], min);
min = Math.min(num[l], min);
return min;
}
Better solution:
public int findMin(int[] num) {
int l = 0;
int r = num.length - 1;
while (l < r) {
int m = (l+r)/2;
//中间值大于起始值,且起始值大于终止值
if (num[m] >= num[l] && num[l] > num[r]) {
l = m + 1;
} else {
r = m;
}
}
return num[l];
}
中间值大于起始值,且起始值大于终止值
public int findMin(int[] num) {
int l = 0;
int r = num.length - 1;
int min = num[0];
while (l < r) {
int m = (l+r)/2;
if (num[l] < num[m]) {
min = Math.min(num[l], min);
l = m + 1;
} else if (num[l] > num[m]) {
min = Math.min(num[m], min);
r = m - 1;
} else {
min = Math.min(num[m], min);
l++;
}
}
min = Math.min(num[r], min);
min = Math.min(num[l], min);
return min;
}
Better solution:
public int findMin(int[] num) {
int l = 0;
int r = num.length - 1;
while (l < r) {
int m = (l+r)/2;
//中间值大于起始值,且起始值大于终止值
if (num[m] >= num[l] && num[l] > num[r]) {
l = m + 1;
} else {
r = m;
}
}
return num[l];
}
Search in Rotated Sorted Array LeetCode
Binary search.
Two different cases:
3 4 5 6 7 8 9 1 2
8 9 1 2 3 4 5 6 7
Here is the solution:
public int search(int[] A, int target) {
// Note: The Solution object is instantiated only once and is reused by each test case.
int L = 0;
int R = A.length-1;
while (L<=R) {
int mid = (L+R)/2;
if (A[mid] == target) return mid;
// Example: 4 5 6 7 8 9 1 2 3
if (A[L] <= A[mid]) {
if (A[L]<=target && target < A[mid]) {
R = mid - 1;
} else {
L = mid + 1;
}
}
// Example: 8 9 1 2 3 4 5 6 7
else {
if (A[mid] < target && target <= A[R]) {
L = mid + 1;
} else {
R = mid - 1;
}
}
}
return -1;
}
Two different cases:
3 4 5 6 7 8 9 1 2
8 9 1 2 3 4 5 6 7
Here is the solution:
public int search(int[] A, int target) {
// Note: The Solution object is instantiated only once and is reused by each test case.
int L = 0;
int R = A.length-1;
while (L<=R) {
int mid = (L+R)/2;
if (A[mid] == target) return mid;
// Example: 4 5 6 7 8 9 1 2 3
if (A[L] <= A[mid]) {
if (A[L]<=target && target < A[mid]) {
R = mid - 1;
} else {
L = mid + 1;
}
}
// Example: 8 9 1 2 3 4 5 6 7
else {
if (A[mid] < target && target <= A[R]) {
L = mid + 1;
} else {
R = mid - 1;
}
}
}
return -1;
}
Monday, December 8, 2014
Container with most water LeetCode
Two pointer. Same idea with TwoSum.
public int maxArea(int[] height) {
int start = 0;
int end = height.length - 1;
int maxArea = 0;
while (start < end) {
maxArea = Math.max(maxArea, (end - start) * Math.min(height[start], height[end]));
if (height[start] > height[end]) {
end--;
} else {
start++;
}
}
return maxArea;
}
public int maxArea(int[] height) {
int start = 0;
int end = height.length - 1;
int maxArea = 0;
while (start < end) {
maxArea = Math.max(maxArea, (end - start) * Math.min(height[start], height[end]));
if (height[start] > height[end]) {
end--;
} else {
start++;
}
}
return maxArea;
}
Clone Graph LeetCode
- A queue is used to do breath first traversal.
- a map is used to store the visited nodes. It is the map between original node and copied node.
It would be helpful if you draw a diagram and visualize the problem.
public UndirectedGraphNode cloneGraph(UndirectedGraphNode node) {
if(node == null)
return null;
LinkedList<UndirectedGraphNode> queue = new LinkedList<UndirectedGraphNode>();
HashMap<UndirectedGraphNode, UndirectedGraphNode> map =
new HashMap<UndirectedGraphNode,UndirectedGraphNode>();
UndirectedGraphNode newNode = new UndirectedGraphNode(node.label);
queue.add(node);
map.put(node, newNode);
while (!queue.isEmpty()) {
UndirectedGraphNode curr = queue.pop();
List<UndirectedGraphNode> currNeighbors = curr.neighbors;
for (UndirectedGraphNode ngn : currNeighbors) {
if (!map.containsKey(ngn)) {
UndirectedGraphNode copy = new UndirectedGraphNode(ngn.label);
map.put(ngn, copy); //updating the mapping
map.get(curr).neighbors.add(copy); //updating the curr neighbors
queue.add(ngn); //updating the queue
} else {
map.get(curr).neighbors.add(map.get(ngn)); //adding the node from clone graph to the curr's neighbor
}
}
}
return newNode;
}
Remove duplicate from sorted list LeetCode
Check whether the duplicate is existing or not.
If so, prev.next = curr.next. If not, prev.next = curr;
public ListNode deleteDuplicates(ListNode head) {
// Note: The Solution object is instantiated only once and is reused by each test case.
if (head == null) return null;
ListNode dummy = new ListNode(-1);
dummy.next =head;
ListNode prev = dummy;
ListNode curr = head;
while (null != curr) {
while (curr.next != null && prev.next.val == curr.next.val) {
curr = curr.next;
}
if (prev.next == curr) {
prev = curr;
} else {
prev.next = curr.next;
}
curr = curr.next;
}
return dummy.next;
}
If so, prev.next = curr.next. If not, prev.next = curr;
public ListNode deleteDuplicates(ListNode head) {
// Note: The Solution object is instantiated only once and is reused by each test case.
if (head == null) return null;
ListNode dummy = new ListNode(-1);
dummy.next =head;
ListNode prev = dummy;
ListNode curr = head;
while (null != curr) {
while (curr.next != null && prev.next.val == curr.next.val) {
curr = curr.next;
}
if (prev.next == curr) {
prev = curr;
} else {
prev.next = curr.next;
}
curr = curr.next;
}
return dummy.next;
}
Gas Station LeetCode
Use two variables to get the index.
diff is checking whether the entire loop has enough gas for the cost.
remain is trying to find the best start location. If it is negative which means we could not start at any previously point. So we count it again from the next point.
public int canCompleteCircuit(int[] gas, int[] cost) {
int index = -1;
int diff = 0;
int remain = 0;
for (int i=0; i<gas.length; i++) {
diff += gas[i] - cost[i];
remain += gas[i] - cost[i];
if (remain < 0) {
index = i;
remain = 0;
}
}
return diff >= 0 ? index + 1: -1;
}
diff is checking whether the entire loop has enough gas for the cost.
remain is trying to find the best start location. If it is negative which means we could not start at any previously point. So we count it again from the next point.
public int canCompleteCircuit(int[] gas, int[] cost) {
int index = -1;
int diff = 0;
int remain = 0;
for (int i=0; i<gas.length; i++) {
diff += gas[i] - cost[i];
remain += gas[i] - cost[i];
if (remain < 0) {
index = i;
remain = 0;
}
}
return diff >= 0 ? index + 1: -1;
}
Partition List LeetCode
Create two listnodes for each list.
public ListNode partition(ListNode head, int x) {
ListNode root = new ListNode(-1);
ListNode pivot = new ListNode(x);
ListNode before = root;
ListNode after = pivot;
ListNode curr = head;
while (curr != null) {
ListNode next = curr.next;
if (curr.val < x) {
before.next = curr;
before = curr;
} else {
after.next = curr;
after = curr;
after.next = null;
}
curr = next;
}
before.next = pivot.next;
return root.next;
}
public ListNode partition(ListNode head, int x) {
ListNode root = new ListNode(-1);
ListNode pivot = new ListNode(x);
ListNode before = root;
ListNode after = pivot;
ListNode curr = head;
while (curr != null) {
ListNode next = curr.next;
if (curr.val < x) {
before.next = curr;
before = curr;
} else {
after.next = curr;
after = curr;
after.next = null;
}
curr = next;
}
before.next = pivot.next;
return root.next;
}
LeetCode Reverse Words in a String
After splitting, there may be some " " string in the string array.
For example "a b", the splitting result is "a", " ", "b".
public String reverseWords(String s) {
if (s==null ||s.length()==0) return "";
//split to words by space
String[] arr = s.trim().split(" ");
StringBuilder sb = new StringBuilder();
for (int i=arr.length-1; i >=0; i--) {
if (!"".equals(arr[i])) {
sb.append(arr[i]).append(" ");
}
}
return sb.length() == 0 ? "" : sb.substring(0, sb.length() - 1);
}
Also there is a alternative solution for two passes and O(1) space.
The condition is there no spaces at the beginning and the tail. Every word is separated by single space.
Algorithm.
Reverse entire sentence.
Reverse every word.
For example "a b", the splitting result is "a", " ", "b".
public String reverseWords(String s) {
if (s==null ||s.length()==0) return "";
//split to words by space
String[] arr = s.trim().split(" ");
StringBuilder sb = new StringBuilder();
for (int i=arr.length-1; i >=0; i--) {
if (!"".equals(arr[i])) {
sb.append(arr[i]).append(" ");
}
}
return sb.length() == 0 ? "" : sb.substring(0, sb.length() - 1);
}
Also there is a alternative solution for two passes and O(1) space.
The condition is there no spaces at the beginning and the tail. Every word is separated by single space.
Algorithm.
Reverse entire sentence.
Reverse every word.
LeetCode Gray Code
第n位的格雷码由两部分构成,一部分是n-1位格雷码,再加上 1<<(n-1)和n-1位格雷码的逆序的和
public List<Integer> grayCode(int n) {
if (n==0) {
List<Integer> result = new ArrayList<Integer>();
result.add(0);
return result;
}
List<Integer> prevList = grayCode(n-1);
int highestBit = 1 << (n-1);
List<Integer> result = new ArrayList<Integer>(prevList);
for (int i=prevList.size() - 1; i>=0; i--) {
result.add(highestBit + prevList.get(i));
}
return result;
}
public List<Integer> grayCode(int n) {
if (n==0) {
List<Integer> result = new ArrayList<Integer>();
result.add(0);
return result;
}
List<Integer> prevList = grayCode(n-1);
int highestBit = 1 << (n-1);
List<Integer> result = new ArrayList<Integer>(prevList);
for (int i=prevList.size() - 1; i>=0; i--) {
result.add(highestBit + prevList.get(i));
}
return result;
}
Friday, December 5, 2014
LeetCode SubSetsII
Add one variable to add duplicate number in the lists.
public List<List<Integer>> subsetsWithDup(int[] num) {
List<List<Integer>> result = new ArrayList<List<Integer>>();
result.add(new ArrayList<Integer>());
Arrays.sort(num);
int startIndex = 0;
for (int i=0; i<num.length; i++) {
int size = result.size();
for (int j = startIndex; j < size; j++) {
List<Integer> sub = new ArrayList<Integer>();
sub.addAll(result.get(j));
sub.add(num[i]);
result.add(sub);
}
if (i<num.length-1 && num[i+1] == num[i]) {
startIndex = size;
} else {
startIndex = 0;
}
}
return result;
}
Tuesday, November 25, 2014
Reverse Linked List II LeetCode
Find the start and end node for reversing.
public ListNode reverseBetween(ListNode head, int m, int n) {
ListNode dummy = new ListNode(-1);
dummy.next = head;
ListNode temp = dummy;
int index = 1;
while (index < m) {
temp = temp.next;
index++;
}
ListNode prev = temp;
ListNode newHead = temp.next;
while (index <= n) {
temp = temp.next;
index++;
}
ListNode end = temp.next;
prev.next = reverse(newHead, end);
return dummy.next;
}
private ListNode reverse(ListNode head, ListNode end) {
if (head == null || head.next == null) return head;
ListNode prev = new ListNode(-1);
prev.next = head;
ListNode curr = head;
while (curr.next != end) {
ListNode temp = curr.next;
curr.next = temp.next;
temp.next = prev.next;
prev.next = temp;
}
return prev.next;
}
public ListNode reverseBetween(ListNode head, int m, int n) {
ListNode dummy = new ListNode(-1);
dummy.next = head;
ListNode temp = dummy;
int index = 1;
while (index < m) {
temp = temp.next;
index++;
}
ListNode prev = temp;
ListNode newHead = temp.next;
while (index <= n) {
temp = temp.next;
index++;
}
ListNode end = temp.next;
prev.next = reverse(newHead, end);
return dummy.next;
}
private ListNode reverse(ListNode head, ListNode end) {
if (head == null || head.next == null) return head;
ListNode prev = new ListNode(-1);
prev.next = head;
ListNode curr = head;
while (curr.next != end) {
ListNode temp = curr.next;
curr.next = temp.next;
temp.next = prev.next;
prev.next = temp;
}
return prev.next;
}
Friday, November 21, 2014
Unique Binary Search Trees II LeetCode
Recursion could simplify the code significantly.
The returning result is all the root node of each Tree.
public List<TreeNode> generateTrees(int n) {
return generateTrees(1,n);
}
private List<TreeNode> generateTrees(int start, int end) {
List<TreeNode> result = new ArrayList<TreeNode>();
if (start > end) {
result.add(null);
return result;
}
for (int i=start; i<=end; i++) {
for (TreeNode left : generateTrees(start, i-1)) {
for (TreeNode right : generateTrees(i+1, end)) {
TreeNode curr = new TreeNode(i);
curr.left = left;
curr.right = right;
result.add(curr);
}
}
}
return result;
}
The returning result is all the root node of each Tree.
public List<TreeNode> generateTrees(int n) {
return generateTrees(1,n);
}
private List<TreeNode> generateTrees(int start, int end) {
List<TreeNode> result = new ArrayList<TreeNode>();
if (start > end) {
result.add(null);
return result;
}
for (int i=start; i<=end; i++) {
for (TreeNode left : generateTrees(start, i-1)) {
for (TreeNode right : generateTrees(i+1, end)) {
TreeNode curr = new TreeNode(i);
curr.left = left;
curr.right = right;
result.add(curr);
}
}
}
return result;
}
Thursday, November 20, 2014
Maximum
DP
but we only need two variables to store the maxvalue and minvalue
public int maxProduct(int[] A) {
if (A.length == 1) return A[0];
int maxProduct = A[0];
int currMax = A[0];
int currMin = A[0];
for (int i=1; i<A.length; i++) {
int temp = currMax;
currMax = Math.max(Math.max(temp*A[i], A[i]), currMin*A[i]);
currMin = Math.min(Math.min(currMin*A[i], A[i]), temp*A[i]);
maxProduct = Math.max(maxProduct, currMax);
}
return maxProduct;
}
but we only need two variables to store the maxvalue and minvalue
public int maxProduct(int[] A) {
if (A.length == 1) return A[0];
int maxProduct = A[0];
int currMax = A[0];
int currMin = A[0];
for (int i=1; i<A.length; i++) {
int temp = currMax;
currMax = Math.max(Math.max(temp*A[i], A[i]), currMin*A[i]);
currMin = Math.min(Math.min(currMin*A[i], A[i]), temp*A[i]);
maxProduct = Math.max(maxProduct, currMax);
}
return maxProduct;
}
Word Break LeetCode
dp
dp[j] = dp[i] && dict.contains(s.substring(j,i))
public boolean wordBreak(String s, Set<String> dict) {
boolean[] dp = new boolean[s.length()+1];
dp[0] = true;
for (int i=1; i<=s.length();i++) {
for (int j=0; j<i; j++) {
if (dp[j] && dict.contains(s.substring(j,i))) {
dp[i] = true;
break;
}
}
}
return dp[s.length()];
}
Construct Binary Tree from preOrder and inOrder Leetcode
Similarly, copy the solution from postOrder and inOrder.
public TreeNode buildTree(int[] preorder, int[] inorder) {
// Note: The Solution object is instantiated only once and is reused by each test case.
if(preorder == null || inorder == null) return null;
if(preorder.length == 0 || inorder.length == 0) return null;
return build (preorder, 0, preorder.length - 1, inorder, 0, inorder.length - 1);
}
public TreeNode build(int[] preorder, int start1, int end1, int[] inorder, int start2,
int end2) {
if(start1 > end1 || start2 > end2) return null;
int current = preorder[start1];
TreeNode currRoot = new TreeNode(current);
int k = start2;
for(; k < inorder.length; k++)
if(inorder[k] == current) break;
currRoot.left = build(preorder, start1+1, start1-start2+k, inorder, start2, k-1);
currRoot.right = build(preorder, start1-start2+k+1,end1, inorder, k+1, end2);
return currRoot;
}
public TreeNode buildTree(int[] preorder, int[] inorder) {
// Note: The Solution object is instantiated only once and is reused by each test case.
if(preorder == null || inorder == null) return null;
if(preorder.length == 0 || inorder.length == 0) return null;
return build (preorder, 0, preorder.length - 1, inorder, 0, inorder.length - 1);
}
public TreeNode build(int[] preorder, int start1, int end1, int[] inorder, int start2,
int end2) {
if(start1 > end1 || start2 > end2) return null;
int current = preorder[start1];
TreeNode currRoot = new TreeNode(current);
int k = start2;
for(; k < inorder.length; k++)
if(inorder[k] == current) break;
currRoot.left = build(preorder, start1+1, start1-start2+k, inorder, start2, k-1);
currRoot.right = build(preorder, start1-start2+k+1,end1, inorder, k+1, end2);
return currRoot;
}
Construct Binary Tree from Inorder and PostOrder LeetCode
The last element from postOrder is the root value.
Find the last element from inOrder, Will get the length of subTrees.
public TreeNode buildTree(int[] inorder, int[] postorder) {
if (inorder == null || postorder == null) return null;
if (inorder.length == 0 || postorder.length == 0) return null;
return buildTree(inorder, 0, inorder.length-1, postorder, 0, postorder.length-1);
}
private TreeNode buildTree(int[] inorder, int start1, int end1, int[] postorder, int start2, int end2) {
if (start1 > end1 || start2 > end2) return null;
int currentValue = postorder[end2];
TreeNode currRoot = new TreeNode(currentValue);
int k = start1;
for (; k < inorder.length; k++) {
if (inorder[k] == currentValue) break;
}
currRoot.left = buildTree(inorder, start1, k-1, postorder, start2, end2-end1+k-1);
currRoot.right = buildTree(inorder, k+1, end1, postorder, end2-end1+k, end2-1);
return currRoot;
}
Convert Sort List to Binary Search Tree LeetCode
The start position for fast and slow should be set carefully.
public TreeNode sortedListToBST(ListNode head) {
if (head == null) return null;
if (head.next == null) return new TreeNode(head.val);
ListNode fast = head.next.next;
ListNode slow = head;
while (fast != null && fast.next != null) {
fast = fast.next.next;
slow = slow.next;
}
ListNode parent = slow.next;
slow.next = null;
TreeNode root = new TreeNode(parent.val);
root.left = sortedListToBST(head);
root.right = sortedListToBST(parent.next);
return root;
}
Here is a better solution. (Bottom-up)
From the CleanCodeHandbook of LeetCode.
public class Solution {
private ListNode list;
public TreeNode sortedListToBST(ListNode head) {
int n = 0;
ListNode p = head;
while (p!=null) {
p = p.next;
n++;
}
list = head;
return sortedListToBST(0, n-1);
}
private TreeNode sortedListToBST(int start, int end) {
if (start > end) return null;
int mid = (start + end)/2;
TreeNode leftChild = sortedListToBST(start, mid-1);
TreeNode parent = new TreeNode(list.val);
parent.left = leftChild;
list = list.next;
TreeNode rightChild= sortedListToBST(mid+1, end);
parent.right = rightChild;
return parent;
}
}
Here is a better solution. (Bottom-up)
From the CleanCodeHandbook of LeetCode.
public class Solution {
private ListNode list;
public TreeNode sortedListToBST(ListNode head) {
int n = 0;
ListNode p = head;
while (p!=null) {
p = p.next;
n++;
}
list = head;
return sortedListToBST(0, n-1);
}
private TreeNode sortedListToBST(int start, int end) {
if (start > end) return null;
int mid = (start + end)/2;
TreeNode leftChild = sortedListToBST(start, mid-1);
TreeNode parent = new TreeNode(list.val);
parent.left = leftChild;
list = list.next;
TreeNode rightChild= sortedListToBST(mid+1, end);
parent.right = rightChild;
return parent;
}
}
ReOrder List LeetCode
Good implementing question for LinkedList.
public void reorderList(ListNode head) {
if (head == null || head.next == null) return;
ListNode fast = head;
ListNode slow = head;
while (fast != null && fast.next != null) {
fast = fast.next.next;
slow = slow.next;
}
ListNode reverseHead = slow.next;
slow.next = null;
reverseHead = reverse(reverseHead);
ListNode curr = head;
while (reverseHead != null) {
ListNode temp = reverseHead.next;
reverseHead.next = curr.next;
curr.next = reverseHead;
curr = reverseHead.next;
reverseHead = temp;
}
}
private ListNode reverse(ListNode head) {
if (head == null || head.next == null) return head;
ListNode prev = new ListNode(-1);
prev.next = head;
ListNode curr = head;
while (curr.next != null) {
ListNode temp = curr.next;
curr.next = temp.next;
temp.next = prev.next;
prev.next = temp;
}
return prev.next;
}
public void reorderList(ListNode head) {
if (head == null || head.next == null) return;
ListNode fast = head;
ListNode slow = head;
while (fast != null && fast.next != null) {
fast = fast.next.next;
slow = slow.next;
}
ListNode reverseHead = slow.next;
slow.next = null;
reverseHead = reverse(reverseHead);
ListNode curr = head;
while (reverseHead != null) {
ListNode temp = reverseHead.next;
reverseHead.next = curr.next;
curr.next = reverseHead;
curr = reverseHead.next;
reverseHead = temp;
}
}
private ListNode reverse(ListNode head) {
if (head == null || head.next == null) return head;
ListNode prev = new ListNode(-1);
prev.next = head;
ListNode curr = head;
while (curr.next != null) {
ListNode temp = curr.next;
curr.next = temp.next;
temp.next = prev.next;
prev.next = temp;
}
return prev.next;
}
Wednesday, November 19, 2014
Binary Tree Zigzag Level Order Traversal LeetCode
Use two stacks to store the node for different directions.
public List<List<Integer>> zigzagLevelOrder(TreeNode root) {
List<List<Integer>> result = new ArrayList<List<Integer>>();
Stack<TreeNode> s1 = new Stack<TreeNode>();
Stack<TreeNode> s2 = new Stack<TreeNode>();
if (root == null) return result;
else {
List<Integer> curr = new ArrayList<Integer>();
curr.add(root.val);
result.add(curr);
if (root.left != null)
s1.push(root.left);
if (root.right != null)
s1.push(root.right);
helper(result, s1, s2);
return result;
}
}
private void helper(List<List<Integer>> result, Stack<TreeNode> s1, Stack<TreeNode> s2) {
if (s1.empty() && s2.empty()) return;
List<Integer> tempList = new ArrayList<Integer>();
TreeNode tempNode = null;
if (!s1.empty()) {
while (!s1.empty()) {
tempNode = s1.pop();
tempList.add(tempNode.val);
if (tempNode.right != null) {
s2.push(tempNode.right);
}
if (tempNode.left != null) {
s2.push(tempNode.left);
}
}
} else {
while (!s2.empty()) {
tempNode = s2.pop();
tempList.add(tempNode.val);
if (tempNode.left != null) {
s1.push(tempNode.left);
}
if (tempNode.right != null) {
s1.push(tempNode.right);
}
}
}
result.add(tempList);
helper(result, s1, s2);
return;
}
public List<List<Integer>> zigzagLevelOrder(TreeNode root) {
List<List<Integer>> result = new ArrayList<List<Integer>>();
Stack<TreeNode> s1 = new Stack<TreeNode>();
Stack<TreeNode> s2 = new Stack<TreeNode>();
if (root == null) return result;
else {
List<Integer> curr = new ArrayList<Integer>();
curr.add(root.val);
result.add(curr);
if (root.left != null)
s1.push(root.left);
if (root.right != null)
s1.push(root.right);
helper(result, s1, s2);
return result;
}
}
private void helper(List<List<Integer>> result, Stack<TreeNode> s1, Stack<TreeNode> s2) {
if (s1.empty() && s2.empty()) return;
List<Integer> tempList = new ArrayList<Integer>();
TreeNode tempNode = null;
if (!s1.empty()) {
while (!s1.empty()) {
tempNode = s1.pop();
tempList.add(tempNode.val);
if (tempNode.right != null) {
s2.push(tempNode.right);
}
if (tempNode.left != null) {
s2.push(tempNode.left);
}
}
} else {
while (!s2.empty()) {
tempNode = s2.pop();
tempList.add(tempNode.val);
if (tempNode.left != null) {
s1.push(tempNode.left);
}
if (tempNode.right != null) {
s1.push(tempNode.right);
}
}
}
result.add(tempList);
helper(result, s1, s2);
return;
}
Flatten Binary Tree to LinkedList LeetCode
Recursion
public TreeNode lastNode = null;
public void flatten(TreeNode root) {
// IMPORTANT: Please reset any member data you declared, as
// the same Solution instance will be reused for each test case.
if (root == null) return;
if (lastNode != null) {
lastNode.left = null;
lastNode.right = root;
}
TreeNode left = root.left;
TreeNode right = root.right;
lastNode = root;
flatten(left);
flatten(right);
}
public TreeNode lastNode = null;
public void flatten(TreeNode root) {
// IMPORTANT: Please reset any member data you declared, as
// the same Solution instance will be reused for each test case.
if (root == null) return;
if (lastNode != null) {
lastNode.left = null;
lastNode.right = root;
}
TreeNode left = root.left;
TreeNode right = root.right;
lastNode = root;
flatten(left);
flatten(right);
}
Tuesday, November 18, 2014
Path Sum II LeetCode
public List<List<Integer>> pathSum(TreeNode root, int sum) {
List<List<Integer>> result = new ArrayList<List<Integer>>();
if (root == null) return result;
if (root.left == null && root.right == null && sum == root.val) {
List<Integer> curr = new ArrayList<Integer>();
curr.add(root.val);
result.add(curr);
return result;
}
if (root.left != null) {
List<List<Integer>> leftResults = pathSum(root.left, sum - root.val);
for (int j=0; j<leftResults.size();j++) {
List<Integer> curr = new ArrayList<Integer>();
curr.add(root.val);
curr.addAll(leftResults.get(j));
result.add(curr);
}
}
if (root.right != null) {
List<List<Integer>> rightResults = pathSum(root.right, sum - root.val);
for (int j=0; j<rightResults.size();j++) {
List<Integer> curr = new ArrayList<Integer>();
curr.add(root.val);
curr.addAll(rightResults.get(j));
result.add(curr);
}
}
return result;
}
List<List<Integer>> result = new ArrayList<List<Integer>>();
if (root == null) return result;
if (root.left == null && root.right == null && sum == root.val) {
List<Integer> curr = new ArrayList<Integer>();
curr.add(root.val);
result.add(curr);
return result;
}
if (root.left != null) {
List<List<Integer>> leftResults = pathSum(root.left, sum - root.val);
for (int j=0; j<leftResults.size();j++) {
List<Integer> curr = new ArrayList<Integer>();
curr.add(root.val);
curr.addAll(leftResults.get(j));
result.add(curr);
}
}
if (root.right != null) {
List<List<Integer>> rightResults = pathSum(root.right, sum - root.val);
for (int j=0; j<rightResults.size();j++) {
List<Integer> curr = new ArrayList<Integer>();
curr.add(root.val);
curr.addAll(rightResults.get(j));
result.add(curr);
}
}
return result;
}
Add Two Numbers LeetCode
Recursion method is quite simple.
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
return helper(l1,l2,0);
}
private ListNode helper(ListNode l1, ListNode l2, int carry) {
if (l1==null && l2==null && carry == 0) return null;
int sum = 0;
if (l1 != null) {
carry += l1.val;
l1=l1.next;
}
if (l2 != null) {
carry += l2.val;
l2=l2.next;
}
ListNode curr = new ListNode(carry%10);
carry = carry/10;
curr.next = helper(l1,l2,carry);
return curr;
}
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
return helper(l1,l2,0);
}
private ListNode helper(ListNode l1, ListNode l2, int carry) {
if (l1==null && l2==null && carry == 0) return null;
int sum = 0;
if (l1 != null) {
carry += l1.val;
l1=l1.next;
}
if (l2 != null) {
carry += l2.val;
l2=l2.next;
}
ListNode curr = new ListNode(carry%10);
carry = carry/10;
curr.next = helper(l1,l2,carry);
return curr;
}
Triangle LeetCode
Bottom-up!
public int minimumTotal(List<List<Integer>> triangle) {
for(int i = triangle.size() - 2; i >= 0; i--){
for(int j = 0; j < triangle.get(i).size(); j++){
triangle.get(i).set(j, triangle.get(i).get(j) + Math.min(triangle.get(i + 1).get(j), triangle.get(i + 1).get(j + 1)));
}
}
return triangle.get(0).get(0);
}
public int minimumTotal(List<List<Integer>> triangle) {
for(int i = triangle.size() - 2; i >= 0; i--){
for(int j = 0; j < triangle.get(i).size(); j++){
triangle.get(i).set(j, triangle.get(i).get(j) + Math.min(triangle.get(i + 1).get(j), triangle.get(i + 1).get(j + 1)));
}
}
return triangle.get(0).get(0);
}
Monday, November 17, 2014
Valid Sudoku LeetCode
public boolean isValidSudoku(char[][] board) {
//check the column
for (int i=0; i<board[0].length; i++) {
boolean[] dupCheck = new boolean[256];
for (int j=0; j<board.length; j++) {
if (board[j][i] != '.') {
if (dupCheck[board[j][i]] == true) return false;
else dupCheck[board[j][i]] = true;
}
}
}
//check the row
for (int i=0; i<board.length; i++) {
boolean[] dupCheck = new boolean[256];
for (int j=0; j<board[0].length; j++) {
if (board[i][j] != '.') {
if (dupCheck[board[i][j]] == true) return false;
else dupCheck[board[i][j]] = true;
}
}
}
//check the subBox
for (int i=0; i <board.length/3; i++) {
for (int j=0; j <board[0].length/3; j++) {
boolean[] dupCheck = new boolean[256];
for (int m=i*3; m<i*3+3; m++) {
for (int n=j*3; n<j*3+3; n++) {
if (board[m][n] != '.') {
if (dupCheck[board[m][n]] == true) return false;
else dupCheck[board[m][n]] = true;
}
}
}
}
}
return true;
}
Length of Last Word LeetCode
public int lengthOfLastWord(String s) {
if (s== null || s.length()==0) return 0;
int end = s.length()-1;
while (end >=0 && s.charAt(end) == ' ') {
end--;
}
int start = end;
while (start >=0 && s.charAt(start) != ' ') {
start--;
}
return end-start;
}
public int lengthOfLastWord(String s) {
if (s==null ||s.length()==0) return 0;
int end = s.length()-1;
//Scan from the last character and skip all the whitespace
while (end>=0 && Character.isWhitespace(s.charAt(end))) {
end--;
}
//Already scan all the string return 0
int start = end;
while (start>=0 && !Character.isWhitespace(s.charAt(start))) {
start--;
}
return end - start;
}
if (s== null || s.length()==0) return 0;
int end = s.length()-1;
while (end >=0 && s.charAt(end) == ' ') {
end--;
}
int start = end;
while (start >=0 && s.charAt(start) != ' ') {
start--;
}
return end-start;
}
public int lengthOfLastWord(String s) {
if (s==null ||s.length()==0) return 0;
int end = s.length()-1;
//Scan from the last character and skip all the whitespace
while (end>=0 && Character.isWhitespace(s.charAt(end))) {
end--;
}
//Already scan all the string return 0
int start = end;
while (start>=0 && !Character.isWhitespace(s.charAt(start))) {
start--;
}
return end - start;
}
Friday, November 7, 2014
Plus One LeetCode
Try to add 1 for the lowest digit and return.
There is a corner condition like 999.
So if all the digits are 0, we will create a new integer array to store the result.
public int[] plusOne(int[] digits) {
int index = digits.length-1;
while (index >= 0) {
if (digits[index] != 9) {
digits[index]++;
return digits;
} else {
digits[index--] = 0;
}
}
int[] result = new int[digits.length+1];
result[0] = 1;
for (int i=1; i<result.length; i++) {
result[i]=0;
}
return result;
}
LeetCode CountAndSay
public String countAndSay(int n) {
if (n==0) return "";
if (n==1) return "1";
String lastResult = countAndSay(n-1);
StringBuilder sb = new StringBuilder();
for (int i=0; i<lastResult.length();) {
char currChar = lastResult.charAt(i);
int count = 0;
while(i<lastResult.length() && currChar == lastResult.charAt(i)) {
count++;
i++;
}
sb.append(count).append(currChar);
}
return sb.toString();
}
if (n==0) return "";
if (n==1) return "1";
String lastResult = countAndSay(n-1);
StringBuilder sb = new StringBuilder();
for (int i=0; i<lastResult.length();) {
char currChar = lastResult.charAt(i);
int count = 0;
while(i<lastResult.length() && currChar == lastResult.charAt(i)) {
count++;
i++;
}
sb.append(count).append(currChar);
}
return sb.toString();
}
Tuesday, October 28, 2014
Minimum Depth of Binary Tree LeetCode
Recursion:
public int minDepth(TreeNode root) {
if (root == null) return 0;
if (root.left == null && root.right == null) {
return 1;
}
else if (root.left != null && root.right != null) {
return 1+Math.min(minDepth(root.left), minDepth(root.right));
}
else if (root.left == null && root.right != null) {
return 1+minDepth(root.right);
} else {
return 1+minDepth(root.left);
}
}
Non-Recursion:
Why we use this method. Sometimes the tree is not balanced. This way will save lots of time. The worst of time complexity is O(n).
public int minDepth(TreeNode root) {
if (root == null) return 0;
Queue<TreeNode> nodeQueue = new LinkedList<TreeNode>();
Queue<Integer> intQueue = new LinkedList<Integer>();
nodeQueue.add(root);
intQueue.add(1);
while (!nodeQueue.isEmpty()) {
TreeNode currNode = nodeQueue.poll();
int currDepth = intQueue.poll();
if (currNode.left != null) {
nodeQueue.add(currNode.left);
intQueue.add(currDepth+1);
}
if (currNode.right != null) {
nodeQueue.add(currNode.right);
intQueue.add(currDepth+1);
}
if (currNode.right == null && currNode.left == null) {
return currDepth;
}
}
return -1;//Should never reach here.
}
public int minDepth(TreeNode root) {
if (root == null) return 0;
if (root.left == null && root.right == null) {
return 1;
}
else if (root.left != null && root.right != null) {
return 1+Math.min(minDepth(root.left), minDepth(root.right));
}
else if (root.left == null && root.right != null) {
return 1+minDepth(root.right);
} else {
return 1+minDepth(root.left);
}
}
Non-Recursion:
Why we use this method. Sometimes the tree is not balanced. This way will save lots of time. The worst of time complexity is O(n).
public int minDepth(TreeNode root) {
if (root == null) return 0;
Queue<TreeNode> nodeQueue = new LinkedList<TreeNode>();
Queue<Integer> intQueue = new LinkedList<Integer>();
nodeQueue.add(root);
intQueue.add(1);
while (!nodeQueue.isEmpty()) {
TreeNode currNode = nodeQueue.poll();
int currDepth = intQueue.poll();
if (currNode.left != null) {
nodeQueue.add(currNode.left);
intQueue.add(currDepth+1);
}
if (currNode.right != null) {
nodeQueue.add(currNode.right);
intQueue.add(currDepth+1);
}
if (currNode.right == null && currNode.left == null) {
return currDepth;
}
}
return -1;//Should never reach here.
}
Path Sum LeetCode
Recursion:
public boolean hasPathSum(TreeNode root, int sum) {
// Note: The Solution object is instantiated only once and is reused by each test case.
if (root == null) return false;
if (root.left == null && root.right == null && sum == root.val) {
return true;
} else {
return hasPathSum(root.left, sum-root.val) || hasPathSum(root.right, sum-root.val);
}
}
Non-recursion:
public boolean hasPathSum(TreeNode root, int sum) {
// Note: The Solution object is instantiated only once and is reused by each test case.
if (root==null) return false;
Queue<TreeNode> nodeQueue = new LinkedList<TreeNode>();
Queue<Integer> intQueue = new LinkedList<Integer>();
nodeQueue.add(root);
intQueue.add(root.val);
while (!nodeQueue.isEmpty()) {
TreeNode currNode = nodeQueue.poll();
int currVal = intQueue.poll();
if (currNode.left == null && currNode.right == null && sum == currVal) {
return true;
}
if (currNode.left != null) {
nodeQueue.add(currNode.left);
intQueue.add(currVal + currNode.left.val);
}
if (currNode.right != null) {
nodeQueue.add(currNode.right);
intQueue.add(currVal + currNode.right.val);
}
}
return false;
}
public boolean hasPathSum(TreeNode root, int sum) {
// Note: The Solution object is instantiated only once and is reused by each test case.
if (root == null) return false;
if (root.left == null && root.right == null && sum == root.val) {
return true;
} else {
return hasPathSum(root.left, sum-root.val) || hasPathSum(root.right, sum-root.val);
}
}
Non-recursion:
public boolean hasPathSum(TreeNode root, int sum) {
// Note: The Solution object is instantiated only once and is reused by each test case.
if (root==null) return false;
Queue<TreeNode> nodeQueue = new LinkedList<TreeNode>();
Queue<Integer> intQueue = new LinkedList<Integer>();
nodeQueue.add(root);
intQueue.add(root.val);
while (!nodeQueue.isEmpty()) {
TreeNode currNode = nodeQueue.poll();
int currVal = intQueue.poll();
if (currNode.left == null && currNode.right == null && sum == currVal) {
return true;
}
if (currNode.left != null) {
nodeQueue.add(currNode.left);
intQueue.add(currVal + currNode.left.val);
}
if (currNode.right != null) {
nodeQueue.add(currNode.right);
intQueue.add(currVal + currNode.right.val);
}
}
return false;
}
Pascal's Triangle LeetCode
Check Pascal's Triangle
public List<List<Integer>> generate(int numRows) {
List<List<Integer>> result = new ArrayList<List<Integer>>();
if (numRows < 1) return result;
if (numRows == 1) {
List<Integer> currList = new ArrayList<Integer>();
currList.add(1);
result.add(currList);
return result;
}
List<List<Integer>> lastResult = generate(numRows-1);
result.addAll(lastResult);
List<Integer> lastList = lastResult.get(lastResult.size() - 1);
List<Integer> newList = new ArrayList<Integer>();
newList.add(1);
for (int i=0; i<lastList.size()-1; i++) {
newList.add(lastList.get(i) + lastList.get(i+1));
}
newList.add(1);
result.add(newList);
return result;
}
public List<List<Integer>> generate(int numRows) {
List<List<Integer>> result = new ArrayList<List<Integer>>();
if (numRows < 1) return result;
if (numRows == 1) {
List<Integer> currList = new ArrayList<Integer>();
currList.add(1);
result.add(currList);
return result;
}
List<List<Integer>> lastResult = generate(numRows-1);
result.addAll(lastResult);
List<Integer> lastList = lastResult.get(lastResult.size() - 1);
List<Integer> newList = new ArrayList<Integer>();
newList.add(1);
for (int i=0; i<lastList.size()-1; i++) {
newList.add(lastList.get(i) + lastList.get(i+1));
}
newList.add(1);
result.add(newList);
return result;
}
Pascal's Triangle II Leetcode
Trivial solution without considering space
public List<Integer> getRow(int rowIndex) {
List<Integer> result = new ArrayList<Integer>();
if (rowIndex == 0) {
result.add(1);
return result;
}
List<Integer> currList = getRow(rowIndex - 1);
List<Integer> newList = new ArrayList<Integer>();
newList.add(1);
for (int i = 0; i < currList.size() - 1; i++) {
newList.add(currList.get(i) + currList.get(i+1));
}
newList.add(1);
return newList;
}
Consider about the space.
Collections.nCopies(n,0) is a smart way to initialize the arraylist as zero.
public List<Integer> getRow(int rowIndex) {
List<Integer> result = new ArrayList<Integer>(Collections.nCopies(rowIndex+1,0));
result.set(0,1);
for (int i=0; i<=rowIndex; i++) {
result.set(i,1);
for (int j=i-1; j>0; j--) {
result.set(j, result.get(j)+result.get(j-1));
}
}
return result;
}
public List<Integer> getRow(int rowIndex) {
List<Integer> result = new ArrayList<Integer>();
if (rowIndex == 0) {
result.add(1);
return result;
}
List<Integer> currList = getRow(rowIndex - 1);
List<Integer> newList = new ArrayList<Integer>();
newList.add(1);
for (int i = 0; i < currList.size() - 1; i++) {
newList.add(currList.get(i) + currList.get(i+1));
}
newList.add(1);
return newList;
}
Consider about the space.
Collections.nCopies(n,0) is a smart way to initialize the arraylist as zero.
public List<Integer> getRow(int rowIndex) {
List<Integer> result = new ArrayList<Integer>(Collections.nCopies(rowIndex+1,0));
result.set(0,1);
for (int i=0; i<=rowIndex; i++) {
result.set(i,1);
for (int j=i-1; j>0; j--) {
result.set(j, result.get(j)+result.get(j-1));
}
}
return result;
}
Wednesday, October 22, 2014
Symmetric Tree LeetCode
Recursively:
public class Solution {
public boolean isSymmetric(TreeNode root) {
if (root == null) return true;
return isSymmetric(root.left, root.right);
}
private boolean isSymmetric(TreeNode left, TreeNode right) {
if (left == null && right == null) return true;
if (left == null || right == null) return false;
if (left.val != right.val ) return false;
return isSymmetric(left.left, right.right) && isSymmetric(left.right, right.left);
}
}
Iteratively:
public boolean isSymmetric(TreeNode root) {
if (root == null || root.left == null && root.right == null) return true;
Queue<TreeNode> lq = new LinkedList<TreeNode>();
Queue<TreeNode> rq = new LinkedList<TreeNode>();
lq.add(root.left);
rq.add(root.right);
TreeNode leftTreeNode = null;
TreeNode rightTreeNode = null;
while (lq.isEmpty() == false && rq.isEmpty() == false) {
leftTreeNode = lq.poll();
rightTreeNode = rq.poll();
if (leftTreeNode == null && rightTreeNode == null) {
continue;
}
if ((leftTreeNode == null && rightTreeNode != null )|| (leftTreeNode != null && rightTreeNode == null)) {
return false;
}
if (leftTreeNode.val != rightTreeNode.val) {
return false;
}
lq.add(leftTreeNode.left);
lq.add(leftTreeNode.right);
rq.add(rightTreeNode.right);
rq.add(rightTreeNode.left);
}
return (lq.isEmpty()&&rq.isEmpty());
}
public class Solution {
public boolean isSymmetric(TreeNode root) {
if (root == null) return true;
return isSymmetric(root.left, root.right);
}
private boolean isSymmetric(TreeNode left, TreeNode right) {
if (left == null && right == null) return true;
if (left == null || right == null) return false;
if (left.val != right.val ) return false;
return isSymmetric(left.left, right.right) && isSymmetric(left.right, right.left);
}
}
Iteratively:
public boolean isSymmetric(TreeNode root) {
if (root == null || root.left == null && root.right == null) return true;
Queue<TreeNode> lq = new LinkedList<TreeNode>();
Queue<TreeNode> rq = new LinkedList<TreeNode>();
lq.add(root.left);
rq.add(root.right);
TreeNode leftTreeNode = null;
TreeNode rightTreeNode = null;
while (lq.isEmpty() == false && rq.isEmpty() == false) {
leftTreeNode = lq.poll();
rightTreeNode = rq.poll();
if (leftTreeNode == null && rightTreeNode == null) {
continue;
}
if ((leftTreeNode == null && rightTreeNode != null )|| (leftTreeNode != null && rightTreeNode == null)) {
return false;
}
if (leftTreeNode.val != rightTreeNode.val) {
return false;
}
lq.add(leftTreeNode.left);
lq.add(leftTreeNode.right);
rq.add(rightTreeNode.right);
rq.add(rightTreeNode.left);
}
return (lq.isEmpty()&&rq.isEmpty());
}
Wednesday, October 1, 2014
LeetCode Maximum Subarray
General solution.
public int maxSubArray(int[] A) {
// Note: The Solution object is instantiated only once and is reused by each test case.
int runningSum = 0;
int totalSum = A[0];
for (int i = 0; i < A.length; i++) {
runningSum += A[i];
if (runningSum > 0) {
totalSum = Math.max(runningSum, totalSum);
} else {
totalSum = Math.max(totalSum, A[i]);
runningSum = 0;
}
}
return totalSum;
}
DP
Memory optimization
public int maxSubArray(int[] A) {
int maxEndingHere = A[0], maxSoFar = A[0];
for (int i=1; i<A.length; i++) {
maxEndingHere = Math.max(maxEndingHere + A[i], A[i]);
maxSoFar = Math.max(maxEndingHere, maxSoFar);
}
return maxSoFar;
}
D&C
Implement the binary search everywhere.
public int maxSubArray(int[] A) {
// Note: The Solution object is instantiated only once and is reused by each test case.
int maxSum = Integer.MIN_VALUE;
return findMaxSub(A, 0, A.length - 1, maxSum);
}
//Recursive to find max sum
//may appear on the left, right or crossing the mid point
private int findMaxSub(int[] A, int left, int right, int maxSum) {
if (left > right) return Integer.MIN_VALUE;
//Get Max sub by recursive ways
int mid = (left + right)/2;
int leftMax = findMaxSub(A, left, mid-1, maxSum);
int rightMax = findMaxSub(A, mid+1, right, maxSum);
maxSum = Math.max(maxSum, Math.max(leftMax, rightMax));
//GEt Max sum by crossing mid
int lSum = 0;
int midLeftMax = 0;
for (int i = mid-1; i>=left; i--) {
lSum = lSum + A[i];
if (lSum > midLeftMax) midLeftMax = lSum;
}
int rSum = 0;
int midRightMax = 0;
for (int i = mid+1; i<=right; i++) {
rSum = rSum + A[i];
if (rSum > midRightMax) midRightMax = rSum;
}
maxSum = Math.max(maxSum, midLeftMax + midRightMax + A[mid]);
return maxSum;
}
public int maxSubArray(int[] A) {
// Note: The Solution object is instantiated only once and is reused by each test case.
int runningSum = 0;
int totalSum = A[0];
for (int i = 0; i < A.length; i++) {
runningSum += A[i];
if (runningSum > 0) {
totalSum = Math.max(runningSum, totalSum);
} else {
totalSum = Math.max(totalSum, A[i]);
runningSum = 0;
}
}
return totalSum;
}
DP
Memory optimization
public int maxSubArray(int[] A) {
int maxEndingHere = A[0], maxSoFar = A[0];
for (int i=1; i<A.length; i++) {
maxEndingHere = Math.max(maxEndingHere + A[i], A[i]);
maxSoFar = Math.max(maxEndingHere, maxSoFar);
}
return maxSoFar;
}
D&C
Implement the binary search everywhere.
public int maxSubArray(int[] A) {
// Note: The Solution object is instantiated only once and is reused by each test case.
int maxSum = Integer.MIN_VALUE;
return findMaxSub(A, 0, A.length - 1, maxSum);
}
//Recursive to find max sum
//may appear on the left, right or crossing the mid point
private int findMaxSub(int[] A, int left, int right, int maxSum) {
if (left > right) return Integer.MIN_VALUE;
//Get Max sub by recursive ways
int mid = (left + right)/2;
int leftMax = findMaxSub(A, left, mid-1, maxSum);
int rightMax = findMaxSub(A, mid+1, right, maxSum);
maxSum = Math.max(maxSum, Math.max(leftMax, rightMax));
//GEt Max sum by crossing mid
int lSum = 0;
int midLeftMax = 0;
for (int i = mid-1; i>=left; i--) {
lSum = lSum + A[i];
if (lSum > midLeftMax) midLeftMax = lSum;
}
int rSum = 0;
int midRightMax = 0;
for (int i = mid+1; i<=right; i++) {
rSum = rSum + A[i];
if (rSum > midRightMax) midRightMax = rSum;
}
maxSum = Math.max(maxSum, midLeftMax + midRightMax + A[mid]);
return maxSum;
}
Tuesday, September 30, 2014
LeetCode PostOrder Traversal
Divided each each tree node process into 3 cases (according to the traversal path we drew previously):
2.1. Previous node from current node's parent
2.1.1. if current node has left child, process left subtree.
2.1.2. if current node has no left child but right child, process right subtree. (current child has both left child and right is the case of 2.1.1. <- keep processing the left subtree)
2.1.3. if current has no left or right child (leaf), add the value of current tree node to result set and remove this node from stack, which means this node has been processed.
2.2. Previous node from current node's left child (left subtree has been processed)
2.2.1. if there the current node has right child, process the right subtree.
2.2.2. if no right child, add value of current node into result set and remove it from stack (current node processed).
2.3. Previous node from current node's right child (both left subtree and right subtree has been processed). <- add current node into result set and remove it from stack (current node processed).
public List<Integer> postorderTraversal(TreeNode root) {
List<Integer> result = new ArrayList<Integer>();
if (root == null) return result;
Stack<TreeNode> stack = new Stack<TreeNode>();
stack.push(root);
TreeNode prev = null;
while (!stack.empty()) {
TreeNode curr = stack.peek();
//from root or parent
if (prev == null || prev.left == curr || prev.right == curr) {
if (curr.left != null) stack.push(curr.left);
else if (curr.right != null) stack.push(curr.right);
else {
stack.pop();
result.add(curr.val);
}
}
//from the left child
else if (curr.left == prev) {
if (curr.right != null) stack.push(curr.right);
else {
stack.pop();
result.add(curr.val);
}
}
//from the right child
else if (curr.right == prev) {
stack.pop();
result.add(curr.val);
}
prev = curr;
}
return result;
}
Monday, June 23, 2014
Leetcode Climbing Stairs
One dimension DP.
public int climbStairs(int n) {
int[] steps = new int[n+1];
steps[0] = 1;
steps[1] = 1;
for (int i=2; i<=n; i++) {
steps[i] = steps[i-1] + steps[i-2];
}
return steps[n];
}
public int climbStairs(int n) {
int[] steps = new int[n+1];
steps[0] = 1;
steps[1] = 1;
for (int i=2; i<=n; i++) {
steps[i] = steps[i-1] + steps[i-2];
}
return steps[n];
}
Leecode Search Insert Position
O(logn) Binary Search
public int searchInsert(int[] A, int target) {
if (A == null) return 0;
return searchInsert(A,target, 0, A.length-1);
}
private int searchInsert(int[] A, int target, int start, int end) {
int mid = (start+end)/2;
if (target == A[mid]) {
return mid;
} else if (target < A[mid]) {
return start < mid ? searchInsert(A, target, start, mid-1) : start;
} else {
return end > mid ? searchInsert(A, target, mid+1, end) : (end + 1);
}
}
public int searchInsert(int[] A, int target) {
if (A == null) return 0;
return searchInsert(A,target, 0, A.length-1);
}
private int searchInsert(int[] A, int target, int start, int end) {
int mid = (start+end)/2;
if (target == A[mid]) {
return mid;
} else if (target < A[mid]) {
return start < mid ? searchInsert(A, target, start, mid-1) : start;
} else {
return end > mid ? searchInsert(A, target, mid+1, end) : (end + 1);
}
}
Subscribe to:
Posts (Atom)