Given a set of distinct integers, S, return all possible subsets. Note: Elements in a subset must be in non-descending order. The solution set must not contain duplicate subsets. For example, If S = [1,2,3], a solution is:
privatevoidsubset_helper(ArrayList<ArrayList<Integer>> subsets, ArrayList<Integer> subset, int start, int[] s){
for(int i=start;i<s.length;i++){
subset.add(s[i]);
//add new arraylist subset here
subsets.add(new ArrayList<Integer>(subset));
subset_helper(subsets, subset, i+1, s);
subset.remove(subset.size()-1);
}
}
Subsets II
Given a collection of integers that might contain duplicates, S, return all possible subsets. Note: Elements in a subset must be in non-descending order. The solution set must not contain duplicate subsets. For example, If S = [1,2,2], a solution is:
1
2
3
4
5
6
7
8
[
[2],
[1],
[1,2,2],
[2,2],
[1,2],
[]
]
Only difference is the added while loop. If completed current layer, and found the next element is the same then skip.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public ArrayList<ArrayList<Integer>> subsetsWithDup(int[] num) {
privatevoidsubset_helper(ArrayList<ArrayList<Integer>> subsets, ArrayList<Integer> subset, int start, int[] s){
for(int i=start;i<s.length;i++){
subset.add(s[i]);
//add new arraylist subset here
subsets.add(new ArrayList<Integer>(subset));
subset_helper(subsets, subset, i+1, s);
subset.remove(subset.size()-1);
while(i < s.length-1 && s[i]==s[i+1])
{i++;}
}
}
Missing Ranges
Given a sorted integer array where the range of elements are [lower, upper] inclusive, return its missing ranges. For example, given [0, 1, 3, 50, 75], lower = 0 and upper = 99, return [“2”, “4->49”, “51->74”, “76->99”].
Main idea: output accrodingly when two elements differ>=2, pay attention to edge cases.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public ArrayList<String> findmissingRanges(int[] num, int lower, int upper){
Given a linked list, remove the nth node from the end of list and return its head. For example, Given linked list: 1->2->3->4->5, and n = 2. After removing the second node from the end, the linked list becomes 1->2->3->5.
Solution
Honestly I don’t know how my first solution got accepted, basically I just count the size of list and then remove that element in the second pass.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public ListNode removeNthFromEnd(ListNode head, int n) {
ListNode cur=head;
int i=0;
while(cur!=null){cur=cur.next;i++;}
System.out.println(i);
ListNode cur2=head;
if(n==i){head=head.next;}
for(int j=0;j<i-n-1;j++){
System.out.println(j);
cur2=cur2.next;
}
if (cur2.next == null) {
returnnull;
}
else cur2.next=cur2.next.next;
return head;
}
One pass solution using two pointers: one fake pointer to move n steps from the beginning, then move both pointers until list ends.
1
2
3
4
5
6
7
8
9
10
11
12
13
public ListNode removeNthFromEnd(ListNode head, int n) {
ListNode cur=head;
ListNode p=head;
for(int i=0;i<n;i++){cur=cur.next;}
//deal with removing head cases
if(cur==null) head=head.next;
//made a mistake here, forgot to move cur with p...
Or, instead of dividing into two parts, we can use ArrayDeque Class. (Similar to brute force solution, merges two list each time, whose complexity is n(2+3+…k)=O(nk^2))
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public ListNode mergeKLists(List<ListNode> lists) {
if(lists == null || lists.isEmpty()) returnnull;
ArrayDeque<ListNode> q = new ArrayDeque<ListNode>();
for(ListNode n : lists) {
if (n != null) q.offer(n);
}
while(q.size() > 1) {
ListNode a = q.poll();
ListNode b = q.poll();
q.offer(mergeTwoLists(a, b));
}
return q.poll();
}
Second Solution is PQ. We can add the heads of all lists into the queue. And we can poll out the smallest one. If the next node of this smallest node is not null, we can add the next node to the queue. Until we empty the PQ, we get the sorted lists. The complexity is also O(nklogk).
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public ListNode mergeKLists(List<ListNode> lists) {
if(lists == null || lists.isEmpty()) returnnull;
PriorityQueue<ListNode> heap=new PriorityQueue<>(lists.size(), new Comparator<ListNode>(){
Given an unsorted integer array, find the first missing positive integer. For example, Given [1,2,0] return 3, and [3,4,-1,1] return 2. Your algorithm should run in O(n) time and uses constant space.
Solution
First solution I thought of is simply sort the array, then find the fist missing positive by comparing each positive element with index. However, even though this passed the OJ, it’s still O(logn) time.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
publicintfirstMissingPositive(int A[]) {
int n= A.length;
int i=0;
int index=0;
if(n==0) return1;
Arrays.sort(A);
while(i<n && A[i]<=0) i++;
for(;i<n;i++){
if(i>0&&A[i]==A[i-1]) continue;
elseif(A[i]-index!=1) return index+1;
else index=A[i];
}
return index+1;
}
Second solution sorts every number corresponding with index, index i holds number i+1, if i+1 is not in the array then we return the smallest mismatch. The runtime is O(n).
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
publicintfirstMissingPositive(int A[]) {
int n= A.length;
int i=0;
int tmp=0;
while(i<n){
if(A[i]>0 && A[i]<n && A[i]!=A[A[i]-1])
{
tmp=A[A[i]-1];
A[A[i]-1]=A[i];
A[i]=tmp;
}
else i++;
}
for(i=0;i<n;i++){
if(A[i]!=i+1) return i+1;
}
return n+1;
}
Sort Colors
Given an array with n objects colored red, white or blue, sort them so that objects of the same color are adjacent, with the colors in the order red, white and blue. Here, we will use the integers 0, 1, and 2 to represent the color red, white, and blue respectively. Note: You are not suppose to use the library’s sort function for this problem.
Solution
First solution is counting sort, two pass algorithm.
1
2
3
4
5
6
7
8
9
10
11
12
13
publicvoidsortColors(int[] A) {
int n=A.length;
int[] B=newint[3];
for (int i=0;i<n;i++){
B[A[i]]++;
}
int p=0;
for(int j=0;j<B.length;j++){
for (int k=0;k<B[j];k++)
A[p++]=j;
}
}
Second Solution is one pass three way partition, using three pointers: pr for the first not red, pb for first not blue and i for current.
Given two sorted integer arrays A and B, merge B into A as one sorted array. Note: You may assume that A has enough space (size that is greater or equal to m + n) to hold additional elements from B. The number of elements initialized in A and B are m and n respectively.
Two Pointer Solution:
Unlike merge sort, we need to merge these two arrays in place. So start from the end (A[m+n-1]), we compare each pointer. Until one of the pointers reached 0, copy the rest of B to A.
1
2
3
4
5
6
7
8
publicvoidmerge(int A[], int m, int B[], int n) {
int cur=m+n;
while(m>0 && n>0){
if(A[m-1]<B[n-1]){A[--cur]=B[--n];}
else {A[--cur]=A[--m];}
}
while(n>0){A[--cur]=B[--n];}
}
Merge Intervals
Given a collection of intervals, merge all overlapping intervals. For example, Given [1,3],[2,6],[8,10],[15,18], return [1,6],[8,10],[15,18].
Correct Solution
At first sort the Intervals, then I thought of three basic cases:
cur.end > next.end (&& cur.end > next.start)
cur.end < next.end && cur.end > next.start
cur.end < next.end && cur.end < next.start
we can leave the third case alone, and only the first two cases need to be merged: if(cur.end > next.start) we set cur.end to the max out of two ends.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public ArrayList<Interval> merge(ArrayList<Interval> intervals) {
//sort according to start using inline comparator
Collections.sort(intervals, new Comparator<Interval>(){
Given a set of non-overlapping intervals, insert a new interval into the intervals (merge if necessary). You may assume that the intervals were initially sorted according to their start times. Example 1: Given intervals [1,3],[6,9], insert and merge [2,5] in as [1,5],[6,9]. Example 2: Given [1,2],[3,5],[6,7],[8,10],[12,16], insert and merge [4,9] in as [1,2],[3,10],[12,16]. This is because the new interval [4,9] overlaps with [3,5],[6,7],[8,10].
Solution(while loop)
Still three cases:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public ArrayList<Interval> insert(ArrayList<Interval> intervals, Interval newInterval) {
Say you have an array for which the ith element is the price of a given stock on day i. If you were only permitted to complete at most one transaction (ie, buy one and sell one share of the stock), design an algorithm to find the maximum profit.
Brute Force Solution
1
2
3
4
5
6
7
8
9
publicintmaxProfit(int[] prices) {
int maxp=0, low=Integer.MAX_VALUE;
for(int i=0;i<prices.length;i++){
if(prices[i]<low) low=prices[i];
if(prices[i]-low>maxp)
maxp=prices[i]-low;
}
return maxp;
}
DP Solution
1
2
3
4
5
6
7
8
9
10
11
12
13
14
publicintmaxProfit(int[] prices) {
int maxp=0, tmp=0;
if (prices == null || prices.length <2) { return0;}
int[] t=newint[prices.length-1];
for(int i=0;i<prices.length-1;i++){
t[i]=prices[i+1]-prices[i];
}
for(int i=0;i<t.length;i++){
tmp+=t[i];
if(tmp>maxp) maxp=tmp;
if(tmp<0) tmp=0;
}
return maxp;
}
Best Time to Buy and Sell Stock II
Greedy Solution: trasaction once there exist profit.
1
2
3
4
5
6
7
8
9
publicintmaxProfit(int[] prices) {
if(prices.length == 0) return0;
int ans = 0;
for(int i=1; i<prices.length; i++){
if(prices[i] > prices[i-1])
ans += prices[i]-prices[i-1];
}
return ans;
}
DP Solution
1
2
3
4
5
6
7
8
9
10
11
12
publicintmaxProfit(int[] prices) {
int maxp=0, tmp=0,curmax=0;
if (prices == null || prices.length <2) { return0;}
int[] t=newint[prices.length-1];
for(int i=0;i<prices.length-1;i++){
t[i]=prices[i+1]-prices[i];
}
for(int i=0;i<t.length;i++){
if(t[i]>0) maxp+=t[i];
}
return maxp;
}
Best Time to Buy and Sell Stock III
Say you have an array for which the ith element is the price of a given stock on day i. Design an algorithm to find the maximum profit. You may complete at most two transactions. Note: You may not engage in multiple transactions at the same time (ie, you must sell the stock before you buy again).
DP Solution
First thought: we can cut the array in half in n ways, and get the max profit from both sides using solution in the first question. This will be O(n^2), too LTE… Using DP to store the max profit from both sides? just scan twice from both directions and update the max profit array for [0…i] and [i…n-1]. Return the max value when a[i]+b[i] is max.
Given n non-negative integers a1, a2, …, an, where each represents a point at coordinate (i, ai). n vertical lines are drawn such that the two endpoints of line i is at (i, ai) and (i, 0). Find two lines, which together with x-axis forms a container, such that the container contains the most water. Note: You may not slant the container.
Solution
Two Pointers l and r:
start from two ends, keep updating maxsofar area
changing rule: if left’<’right then we know moving right makes no change(width decreases and min board is still left), so we need to move left pointer, vise versa
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
publicintmaxArea(int[] height) {
if(height==null) return -1;
int curmax=-1, maxsofar=-1, l=0,r=height.length-1;
while(l<r){
curmax=(r-l)*Math.min(height[l],height[r]);
if(curmax>maxsofar){
maxsofar=curmax;
}
if(height[l]<height[r]){
//move r-- would never increase area with same l
int tmp=height[l];
while(l<r && height[l]<=tmp)
l++;
}
else{
int tmp=height[r];
while(l<r && height[r]<=tmp)
r--;
}
}
return maxsofar;
}
Trapping Rain Water
Given n non-negative integers representing an elevation map where the width of each bar is 1, compute how much water it is able to trap after raining. For example, Given [0,1,0,2,1,0,1,3,2,1,2,1], return 6.
Crazy Smart Solution
left[i] to store the largest to the left of i; right[i] to store the largest to the right of i. The min of these two, subtracted by A[i], determines how much water A[i] can hold remember to add up volume from 1 to n-2, since two sides cannot hold water.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
publicinttrap(int[] A) {
if (A == null || A.length == 0) {
return0;
}
int i, n=A.length,vol=0,max=0,left[]=newint[n],right[]=newint[n];
Given a string, determine if it is a palindrome, considering only alphanumeric characters and ignoring cases. For example, “A man, a plan, a canal: Panama” is a palindrome. “race a car” is not a palindrome. Note: Have you consider that the string might be empty? This is a good question to ask during an interview. For the purpose of this problem, we define empty string as valid palindrome.
Determine whether an integer is a palindrome. Do this without extra space. Could negative integers be palindromes? (ie, -1) If you are thinking of converting the integer to string, note the restriction of using extra space. You could also try reversing an integer. However, if you have solved the problem “Reverse Integer”, you know that the reversed integer might overflow. How would you handle such case? There is a more generic way of solving this problem.
Solution
refer my solution to reverse integer.
reverse the number. If the number is the same as its reversed, then it must be a palindrome.
negative integers as non-palindromes.
Even thought this passed OJ, didn’t deal with overflow issues.
First, compare the first and last digit. If they are not the same, it must not be a palindrome. If they are the same, chop off one digit from both ends and continue until you have no digits left, which you conclude that it must be a palindrome.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
publicbooleanisPalindrome2(int x) {
if (x < 0) returnfalse;
int div = 1;
while (x / div >= 10) {
div *= 10;
}
while (x != 0) {
int l = x / div;
int r = x % 10;
if (l != r) returnfalse;
x = (x % div) / 10;
div /= 100;
}
returntrue;
}
Scramble String
Given a string s1, we may represent it as a binary tree by partitioning it to two non-empty substrings recursively. Below is one possible representation of s1 = “great”:
1
2
3
4
5
6
7
great
/ \
gr eat
/ \ / \
g r e at
/ \
a t
To scramble the string, we may choose any non-leaf node and swap its two children. For example, if we choose the node “gr” and swap its two children, it produces a scrambled string “rgeat”.
1
2
3
4
5
6
7
rgeat
/ \
rg eat
/ \ / \
r g e at
/ \
a t
We say that “rgeat” is a scrambled string of “great”. Similarly, if we continue to swap the children of nodes “eat” and “at”, it produces a scrambled string “rgtae”.
1
2
3
4
5
6
7
rgtae
/ \
rg tae
/ \ / \
r g ta e
/ \
t a
We say that “rgtae” is a scrambled string of “great”. Given two strings s1 and s2 of the same length, determine if s2 is a scrambled string of s1.
Iterative Solution
If string s1 and s2 are scramble strings, there must be a point(i) that breaks s1 to two parts s11, s12, and a point(l-i) that breaks s2 to two parts, s21, s22, and isScramble(s11, s21) && isScramble(s12, s22) is true, or isScramble(s11, s22) && isScramble(s12, s21) is true.
Cases to consider to avoid LTE:
If the lengths of two strings are different, they can’t be scramble.
If the characters in two strings are different, they can’t be scramble either.
System.out.println(" d "+Integer.toBinaryString(d) +" tmp "+tmp);
res=tmp+res;
d >>= 1;
System.out.println(" d: "+d+ " b "+Integer.toBinaryString(d));
}
System.out.println(res);
return res;
}
2) 1100->0011 1111->1111
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public String ReverseBinary(int d){
int n=Integer.toBinaryString(d).length();
StringBuffer sb=new StringBuffer();
System.out.println(" d "+d);
while(d!=0){
sb.append(d ^ 0x01);
System.out.println(" d "+d+" sb "+sb+ " "+0x01);
d >>= 1;
System.out.println(" d: "+d+ " b "+Integer.toBinaryString(d));
}
String s=sb.toString();
System.out.println(" s: "+s);
String res=Integer.valueOf(s, 2).toString();
return res;
}
Interleaving String
Given s1, s2, s3, find whether s3 is formed by the interleaving of s1 and s2. For example, Given: s1 = “aabcc”, s2 = “dbbca”, When s3 = “aadbbcbcac”, return true. When s3 = “aadbbbaccc”, return false.
Recursive Solution
Three pointers, four cases:
char at p3 equals to both p2, p1. either result could be true
char at p3 only equals to p2, increment these two pointers. If one of p1, p2 reached its length, just compare the rest substring
Multiply Strings Given two numbers represented as strings, return multiplication of the numbers as a string. Note: The numbers can be arbitrarily large and are non-negative.
First Solution
reverse two input strings, so index and digits are the same
create a tmp int[] to store the additions of two digits multiply results
add up the array, while inserting into a stringbuilder
delete zeros in the beginning
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public String multiply(String num1, String num2) {
Implement strStr(). Returns the index of the first occurrence of needle in haystack, or -1 if needle is not part of haystack. Update (2014-11-02): The signature of the function had been updated to return the index instead of the pointer. If you still see your function signature returns a char * or String, please click the reload button to reset your code definition.
Naive Solution
Two pointers:
i: from 0 to n-m, check each substring(i,i+m) equals to needle
j: from i to m+i-1, break if non-equal character found
If j=m+i after some round, then we found a substring(i, i+m) matches the needle.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
publicintstrStr(String haystack, String needle)
{
int n = haystack.length();
int m = needle.length();
//if haystack empty but needle not
if (n==0 && m!=0) return -1;
//special case
elseif(n==0||m==0) return0;
else{
for (int i = 0; i < n - m+1; i++)
{ int j=i;
for (; j < m+i; j++)
{
if (needle.charAt(j-i) != haystack.charAt(j)) break;
Given an input string, reverse the string word by word. For example, Given s = “the sky is blue”, return “blue is sky the”. Clarification: What constitutes a word? A sequence of non-space characters constitutes a word. Could the input string contain leading or trailing spaces? Yes. However, your reversed string should not contain leading or trailing spaces. How about multiple spaces between two words? Reduce them to a single space in the reversed string.
Correct Solution:
First, split words into array by spaces. Then from last element in array, append to stringBuilder if not space, add one space after that element in the new string. At last, get the substring from 0 to sb.length()-1 to delete the ending space.
Implement atoi to convert a string to an integer. Hint: Carefully consider all possible input cases. If you want a challenge, please do not see below and ask yourself what are the possible input cases. Notes: It is intended for this problem to be specified vaguely (ie, no given input specs). You are responsible to gather all the input requirements up front.
Naive Sulotion
Case 1: general case, given string is a valid input, convert to int directly
Case 2: input string is null or all blank, return 0;
Given two binary strings, return their sum (also a binary string). For example, a = “11” b = “1” Return “100”.
Solution
Note:Int can be converted to String for manipulation, however, converting String to Int might cause overflow errors.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
public String addBinary(String a, String b) {
if(a==null|a.length()==0)
return b;
if(b==null|b.length()==0)
return a;
//switch a,b if a is shorter than b
if(a.length() < b.length()){
String temp = a;
a = b;
b = temp;
}
int m = a.length()-1;
int n = b.length()-1;
int res = 0;
String rst = "";
//Add from last digit
while(n >= 0){
int sum = (int)(a.charAt(m) - '0') + (int)(b.charAt(n) - '0') + res;
rst = String.valueOf(sum % 2) + rst;
res = sum / 2;
m --;
n --;
}
//Add the longer digits
while(m >= 0){
int sum = (int)(a.charAt(m) - '0') + res;
rst = String.valueOf(sum % 2) + rst;
res = sum / 2;
m --;
}
//Don't forget the highest digit
if (res == 1)
rst = "1" + rst;
return rst;
}
Add Two Numbers
You are given two linked lists representing two non-negative numbers. The digits are stored in reverse order and each of their nodes contain a single digit. Add the two numbers and return it as a linked list. Input: (2 -> 4 -> 3) + (5 -> 6 -> 4) Output: 7 -> 0 -> 8
Solution
We don’t have to compare the length of two lists an match digits since we are given reversed order. So just add each pair and the rest, pay attention to the last carries.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {