0% found this document useful (0 votes)
0 views149 pages

Coding Puzzles_ Thinking in Code

This document is a coding puzzle book aimed at helping software engineers prepare for programming interviews. It contains 105 puzzles covering various topics, including data structures and algorithms, with detailed explanations and implementations for each puzzle. The book is intended for fun and can be accessed for free online, although knowledge of Chinese is required for the free version.

Uploaded by

Murat Yildiz
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
0 views149 pages

Coding Puzzles_ Thinking in Code

This document is a coding puzzle book aimed at helping software engineers prepare for programming interviews. It contains 105 puzzles covering various topics, including data structures and algorithms, with detailed explanations and implementations for each puzzle. The book is intended for fun and can be accessed for free online, although knowledge of Chinese is required for the free version.

Uploaded by

Murat Yildiz
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 149

CODING PUZZLES

Thinking in code
This book is dedicated to the memory of my dog,
Maomao,
who was passed away last year, aged 13.
Contents
Preface
1. 2 Sum
2. 3 Sum
3. 3Sum Closest
4. 4Sum
5. Add Binary
6. Add Two Numbers
7. Anagrams
8. Best Time to Buy and Sell Stock
9. Best Time to Buy and Sell Stock II
10. Best Time to Buy and Sell Stock III
11. Balanced Binary Tree
12. Binary Tree Inorder Traversal
13. Binary Tree Level Order Traversal
14. Binary Tree Maximum Path Sum
15. Climbing Stairs
16. Combination Sum
17. Combination Sum II
18. Combinations
19. Construct Binary Tree from Preorder and Inorder Traversal
20. Container With Most Water
21. Convert Sorted Array to Binary Search Tree
22. Convert Sorted List to Binary Search Tree
23. Count and Say
24. Decode Ways
25. Distinct Subsequences
26. Divide Two Integers
27. Edit Distance
28. First Missing Positive
29. Flatten Binary Tree to Linked List
30. Generate Parentheses
31. Gray Code
32. Implement strStr()
33. Insert Interval
34. Integer to Roman
35. Interleaving String
36. Jump Game
37. Jump Game II
38. Largest Rectangle in Histogram
39. Length of Last Word
40. Letter Combinations of a Phone Number
41. Longest Common Prefix
42. Longest Palindromic Substring
43. Longest Substring Without Repeating Characters
44. Maximum Depth of Binary Tree
45. Maximum Subarray
46. Median of Two Sorted Arrays
47. Merge k Sorted Lists
48. Merge Sorted Array
49. Minimum Depth of Binary Tree
50. Minimum Path Sum
51. Minimum Window Substring
52. Multiply Strings
53. Next Permutation
54. Palindrome Number
55. Partition List
56. Pascal's Triangle II
57. Path Sum
58. Path Sum II
59. Permutations
60. Permutations II
61. Plus One
62. Populating Next Right Pointers in Each Node
63. Populating Next Right Pointers in Each Node II
64. Recover Binary Search Tree
65. Pow(x, n)
66. Remove Duplicates from Sorted Array
67. Remove Duplicates from Sorted Array II
68. Remove Duplicates from Sorted List
69. Remove Duplicates from Sorted List II
70. Remove Element
71. Remove Nth Node From End of List
72. Restore IP Addresses
73. Reverse Integer
74. Reverse Linked List II
75. Reverse Nodes in k-Group
76. Roman To Integer
77. Rotate Image
78. Rotate List
79. Scramble String
80. Search for a Range
81. Search in Rotated Sorted Array
82. Search in Rotated Sorted Array II
83. Search Insert Position
84. Set Matrix Zeroes
85. Simplify Path
86. Sort Colors
87. Spiral Matrix
88. Sqrt(x)
89. String to Integer (atoi)
90. Subsets
91. Subsets II
92. Substring with Concatenation of All Words
93. Swap Nodes in Pairs
94. Symmetric Tree
95. Text Justification
96. Trapping Rain Water
97. Triangle
98. Unique Paths
99. Unique Paths II
100. Valid Parentheses
101. Valid Sudoku
102. Validate Binary Search Tree
103. Wildcard Matching
104. Word Search
105. ZigZag Conversion
Preface
If you are preparing the programming interview for a software engineer position, you might want to look at this
book.
Make sure you have basic knowledge of data structure and algorithm, because this book is mostly focus on how to
resolve the coding puzzles with existing data structure and algorithm. If you need some refresh of data structure and
algorithm, there is a good book you might want to take a look first, <Introduction to Algorithms> by Thomas H.
Cormen.
This book has 105 puzzles. Every puzzle contains a detailed explanation and some implementations. If you find any
error in this book, please send your findings to [email protected].
And at last, this book is only for fun, so that my friends can read it in their kindle offline. If you want to a free
version, you can get it at http://fisherlei.blogspot.com/, but the prerequisite is you need to be able to understand
Chinese ☺

CodingTMD
@Seattle
1. 2 Sum
Given an array of integers, find two numbers such that they add up to a specific target number.
The function twoSum should return indices of the two numbers such that they add up to the target, where index1
must be less than index2. Please note that your returned answers (both index1 and index2) are not zero-based.
You may assume that each input would have exactly one solution.
Input: numbers={2, 7, 11, 15}, target=9
Output: index1=1, index2=2
» Solve this problem

[Thoughts]
There are three sorts of solutions:
The first solution is hashing.
Scan the array from the left to the right, and store the number and its index(the original index in the array) in the
map. Then, scan the array again with the help of map. The time complexity is O(n).
The second solution is two-pointer scanning.
Sort the array first, unfortunately, you need to remember the original index during sorting. It’s better to use a new
object to hold the number-index mapping.After the array is sorted, then, use two pointers to scan from two bounds to
the middle. Find the solution and return their original index. The time complexity is O(n*lgn).

Note:
Two-pointers Scanning
Two-pointer is a optimized way to search targets on top of a SORTED array. One pointer points to the head of the
sorted array, and the other one points to the tail of the sorted array. The two points move towards the middle of
the array until they meet.

The third solution is brute-force searching.


This is the most obvious solution, but with the highest time complexity O(n*n)
[Code]
Following is the execution of solution 1 :
1: vector<int> twoSum(vector<int> &numbers, int target) {
2: map<int, int> mapping;
3: vector<int> result;
4: for(int i =0; i< numbers.size(); i++)
5: {
6: mapping[numbers[i]]=i;
7: }
8: for(int i =0; i< numbers.size(); i++)
9: {
10: int searched = target - numbers[i];
11: if(mapping.find(searched) != mapping.end())
12: {
13: result.push_back(i+1);
14: result.push_back(mapping[searched]+1);
15: break;
16: }
17: }
18: return result;
19: }
Solution 2:
1: struct Node
2: {
3: int val;
4: int index;
5: Node(int pVal, int pIndex):val(pVal), index(pIndex){}
6: };
7: static bool compare(const Node &left, const Node &right)
8: {
9: return left.val < right.val;
10: }
11: vector<int> twoSum(vector<int> &numbers, int target) {
12: vector<Node> elements;
13: for(int i =0; i< numbers.size(); i++)
14: {
15: elements.push_back(Node(numbers[i], i));
16: }
17: std::sort(elements.begin(), elements.end(), compare);
18: int start = 0, end = numbers.size()-1;
19: vector<int> result;
20: while(start < end)
21: {
22: int sum = elements[start].val + elements[end].val;
23: if(sum == target)
24: {
25: result.push_back(elements[start].index+1);
26: if(elements[start].index < elements[end].index)
27: result.push_back(elements[end].index+1);
28: else
29: result.insert(result.begin(), elements[end].index+1);
30: break;
31: }
32: else if(sum > target)
33: end--;
34: else
35: start++;
36: }
37: return result;
38: }
Solution 3: two nested loop. The implementation of the solution is left out here.
2. 3 Sum
Given an array S of n integers, are there elements a, b, c in S such that a + b + c = 0? Find all unique triplets in the
array which gives the sum of zero.
Note:

Elements in a triplet (a,b,c) must be in non-descending order. (ie, a ≤ b ≤ c)


The solution set must not contain duplicate triplets.

For example, given array S = {-1 0 1 2 -1 -4},


A solution set is:
(-1, 0, 1)
(-1, -1, 2)

» Solve this problem

[Thoughts]
Change the equation a little bit.
a + b + c =0 => a + b = -c
So with the new equation, the problem is changed as finding two element a and b, which sums to –c.
Sort the array first. And use two pointers to scan from both sorted array bounds to middle. Since the problem
requires no duplicate solution set. Need add some tricks to de-duplicate as below:

1. Line 21 and Line 22.

filter the duplicate during two-pointer scanning. For example [-2, 0, 0, 2,2], the expected output
should be [-2,0,2]. If no filter here, the output will be duplicate as [-2,0,2] and [-2,0,2]

2. Line 35

filter the duplicate for outside iteration. For example [-2, -2, -2, 0,2].
[Code]
1: vector<vector<int> > threeSum(vector<int> &num) {
2: // Start typing your C/C++ solution below
3: // DO NOT write int main() function
4: std::sort(num.begin(), num.end());
5: vector<vector<int> > result;
6: int len = num.size();
7: for(int i =0; i< len; i++)
8: {
9: int target = 0-num[i];
10: int start = i+1, end =len-1;
11: while(start<end)
12: {
13: if(num[start] + num[end] == target)
14: {
15: vector<int> solution;
16: solution.push_back(num[i]);
17: solution.push_back(num[start]);
18: solution.push_back(num[end]);
19: result.push_back(solution);
20: start++; end--;
21: while(start<end && num[start] == num[start-1]) start++;
22: while(start<end && num[end] == num[end+1]) end--;
23: }
24: else if(num[start] + num[end] < target)
25: {
26: start++;
27: }
28: else
29: {
30: end--;
31: }
32: }
33: if(i<len-1)
34: {
35: while(num[i] == num[i+1]) i++;
36: }
37: }
38: return result;
39: }
3. 3Sum Closest
Given an array S of n integers, find three integers in S such that the sum is closest to a given number, target. Return the sum of the three integers. You may
assume that each input would have exactly one solution.

For example, given array S = {-1 2 1 -4}, and target = 1.


The sum that is closest to the target is 2. (-1 + 2 + 1 = 2).

» Solve this problem

[Thoughts]
Similar as 3Sum. Only need to add a new variable to track the minimum history. See below highlight code for the
differences.
[Code]
1: int threeSumClosest(vector<int> &num, int target) {
2: // Start typing your C/C++ solution below
3: // DO NOT write int main() function
4: std::sort(num.begin(), num.end());
5: int len = num.size();
6: int minV = INT_MAX, record;
7: for(int i =0; i< len; i++)
8: {
9: int start = i+1, end =len-1;
10: while(start<end)
11: {
12: int sum = num[i] + num[start] + num[end];
13: if(sum == target)
14: {
15: minV = 0;
16: record = sum;
17: break;
18: }
19: if(sum < target)
20: {
21: if(target-sum < minV)
22: {
23: minV = target-sum;
24: record = sum;
25: }
26: start++;
27: }
28: else
29: {
30: if(sum-target < minV)
31: {
32: minV = sum - target;
33: record = sum;
34: }
35: end--;
36: }
37: }
38: if(record == target) break;
39: while(i<len-1 && num[i] == num[i+1]) i++; //de-duplicate
40: }
41: return record;
42: }
4. 4Sum
Given an array S of n integers, are there elements a, b, c, and d in S such that a + b + c + d = target? Find all unique
quadruplets in the array which gives the sum of target.
Note:
Elements in a quadruplet (a,b,c,d) must be in non-descending order. (ie, a ≤ b ≤ c ≤ d)
The solution set must not contain duplicate quadruplets.

For example, given array S = {1 0 -1 0 -2 2}, and target = 0.


A solution set is:
(-1, 0, 0, 1)
(-2, -1, 1, 2)
(-2, 0, 0, 2)

[Thoughts]
This problem is better understood after doing a little transformation:
a + b + c + d => (a+b) + (c+d).
Look at Problem “2 Sum”. This problem can be done by doing “2 Sum” twice.
The first time, use two loops to calculate all the possible sums of the two numbers (a+b) and (c+d). For instance,
using the above example S = {1 0 -1 0 -2 2}, and calculate all the possible two-number combinations S-Com and the
mapping between S<->S-Com.
In this case, the S-Com = {-3, -2, -1, 0, 1, 2, 3}. And the mapping will be
S S-Com
{-2,-1} {-3}
{-2,0} {-2}
{-2, 1}, {-1, 0} {-1}
{0,0}, {-1, 1}, {-2,2} {0}
{0, 1}, {-1,2} {1}
{0, 2} {2}
{1,2} {3}
Then do a 2sum again based on S-Com.
Keep in mind that before returning all the results, filter the duplications. You should be able to finish this code by
referring to previous “2Sum”.
5. Add Binary
Giveng two binary strings, return their sum (also a binary string).
For example,
a = "11"
b = "1"
Return "100".
» Solve this problem

[Thoughts]
A general implementation. No trick here. Simulate the add process one digit by one. Don’t miss the carry.
[Code]
1: string addBinary(string a, string b) {
2: int carry =0;
3: string result;
4: for(int i = a.size()-1, j = b.size()-1; i >=0 || j>=0; --i,--j)
5: {
6: int ai = i>=0? a[i]-'0':0;
7: int bj = j>=0? b[j]-'0':0;
8: int val = (ai+bj+carry)%2;
9: carry = (ai+bj+carry) /2;
10: result.insert(result.begin(), val+'0');
11: }
12: if(carry ==1)
13: {
14: result.insert(result.begin(), '1');
15: }
16: return result;
17: }
[Note]
There is another extension. How to change the code to handle hexadecimal instead of binary. In this code, change the line 13 and line 14 from 2 to 16.
6. 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
» Solve this problem

[Thoughts]
Similar as "Add Binary". The logic part is same. And the only difference is the pointer operation because this is
linked list.
[Code]
1: ListNode *addTwoNumbers(ListNode *l1, ListNode *l2) {
2: ListNode* result = new ListNode(-1);
3: ListNode* pre = result;
4: ListNode *pa = l1, *pb = l2;
5: int carry =0;
6: while(pa!=NULL || pb!=NULL)
7: {
8: int av = pa == NULL? 0:pa->val;
9: int bv = pb == NULL? 0:pb->val;
10: ListNode* node = new ListNode((av+bv+carry)%10);
11: carry = (av+bv+carry)/10;
12: pre->next = node;
13: pre = pre->next;
14: pa = pa==NULL? NULL:pa->next;
15: pb = pb==NULL? NULL:pb->next;
16: }
17: if(carry >0)
18: pre->next = new ListNode(1);
19: pre = result->next;
20: delete result;
21: return pre;
22: }
7. Anagrams
Given an array of strings, return all groups of strings that are anagrams.
Note: All inputs will be in lower-case.
» Solve this problem

[Thoughts]
Generate footprint for each string, if they has the same footprint, they are anagrams. But how to generate footprint is
tricky. At beginning, I try to generate footprint as a full description of string content(as highlight code), but this
costs too much time when the string is huge. Instead, I choose to generate hash number for each string.A potential
risk is hash collision. So choose a prime number as the factor to avoid this.
[Code]
1: vector<string> anagrams(vector<string> &strs) {
2: // Start typing your C/C++ solution below
3: // DO NOT write int main() function
4: vector<string> result;
5: if(strs.size() ==0) return result;
6: map<long, vector<string> > smap;
7: for(int i =0; i< strs.size(); i++)
8: {
9: smap[footprint(strs[i])].push_back(strs[i]);
10: }
11: for(map<long, vector<string> >::iterator it = smap.begin();
12: it!=smap.end(); ++it)
13: {
14: if(it->second.size() <=1)
15: continue;
16: result.insert(result.begin(), it->second.begin(), it->second.end());
17: }
18: return result;
19: }
20: long footprint(string str)
21: {
22: int index[26];
23: memset(index, 0, 26*sizeof(int));
24: for(int i = 0; i < str.size(); i++)
25: {
26: index[str[i]-'a']++;
27: }
28: /*string footp;
29: for(int i =0; i<26; i++)
30: {
31: footp.append(1,i+'a');
32: stringstream ss;
33: ss << index[i];
34: footp.append(ss.str());
35: }*/
36: long footp=0;
37: int feed =7;
38: for(int i =0; i< 26; i++)
39: {
40: footp= footp*feed +index[i];
41: }
42: return footp;
43: }
8. Best Time to Buy and Sell Stock
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.
» Solve this problem

[Thoughts]
Scan the array from left to right. And keep tracking the minimal price in scanned elements. In the meantime, track
the max profit by calculating the difference between current price and minimal price and updating the max profit if
the difference is larger than existing max profit.

[Code]
1: int maxProfit(vector<int> &prices) {
2: // Start typing your C/C++ solution below
3: // DO NOT write int main() function
4: int minV=INT_MAX; int max =0;
5: int diff=0;
6: for(int i =0; i< prices.size(); i++)
7: {
8: if(prices[i]<minV) minV = prices[i];
9: diff = prices[i] - minV;
10: if(max<diff)
11: max = diff;
12: }
13: return max;
14: }
9. Best Time to Buy and Sell Stock II
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 as many transactions as you like (ie, buy one
and sell one share of the stock multiple times). However, you may not engage in multiple transactions at the same
time (ie, you must sell the stock before you buy again).
» Solve this problem

[Thoughts]
A little different with previous one. Since we can make unlimited transactions, this question turns to sum all the
positive price difference.
So, scan the array from left to right, and sum all positive diff value.
[Code]
1: int maxProfit(vector<int> &prices) {
2: // Start typing your C/C++ solution below
3: // DO NOT write int main() function
4: int max=0;
5: int sum = 0;
6: for(int i =1; i< prices.size(); i++)
7: {
8: int diff = prices[i] -prices[i-1];
9: if(diff>0)
10: sum+=diff;
11: }
12: return sum;
13: }
10. 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).
» Solve this problem

[Thoughts]
One-dimension dynamic planning.
Given an i, split the whole array into two parts:
[0,i] and [i+1, n], it generates two max value based on i, MaxProfit(0,i) and MaxProfit(i+1,n)
So, we can define the transformation function as:
FinalMaxProfix = max(MaxProfit(0,i) + MaxProfit(i+1, n)) 0<=i<n

Pre-processing MaxProfit(0,i) and MaxProfit(i+1,n). And easy to find the FinalMaxProfit in one pass.
[Code]
Line 6~12 and Line 15~21 can be merged into one pass. But keep it for readability.
1: int maxProfit(vector<int> &prices) {
2: if(prices.size() <= 1) return 0;
3: vector<int> maxFromLeft(prices.size(), 0);
4: vector<int> maxFromRight(prices.size(), 0);
5: int minV = INT_MAX, maxP = INT_MIN;
6: for(int i =0; i< prices.size(); i++)
7: {
8: if(minV > prices[i]) minV = prices[i];
9: int temp = prices[i] - minV;
10: if(temp > maxP) maxP = temp;
11: maxFromLeft[i] = maxP;
12: }
13: int maxV = INT_MIN;
14: maxP = INT_MIN;
15: for(int i =prices.size()-1; i>=0; i--)
16: {
17: if(maxV < prices[i]) maxV = prices[i];
18: int temp = maxV - prices[i];
19: if(temp > maxP) maxP = temp;
20: maxFromRight[i] = maxP;
21: }
22: int maxProfit = INT_MIN;
23: for(int i =0; i< prices.size()-1; i++)
24: {
25: int sum = maxFromLeft[i] + maxFromRight[i+1];
26: if(sum > maxProfit) maxProfit = sum;
27: }
28: if(maxProfit < maxFromRight[0])
29: maxProfit = maxFromRight[0];
30: return maxProfit;
31: }
11. Balanced Binary Tree
Given a binary tree, determine if it is height-balanced.
For this problem, a height-balanced binary tree is defined as a binary tree in which the depth of the two subtrees
of everynode never differ by more than 1.
» Solve this problem

[Thoughts]
For the tree question, the most apparent way is to use Recursion. Here, for each node, check the left branch and right
branch recursively.
[Code]
1: bool isBalanced(TreeNode *root) {
2: // Start typing your C/C++ solution below
3: // DO NOT write int main() function
4: if(root == NULL) return true;
5: int val = GetBalance(root);
6: if(val ==-1) return false;
7: return true;
8: }
9: int GetBalance(TreeNode* node)
10: {
11: if(node == NULL)
12: return 0;
13: int left = GetBalance(node->left);
14: if(left == -1) return -1;
15: int right = GetBalance(node->right);
16: if(right == -1) return -1;
17: if(left-right>1 || right-left>1)
18: return -1;
19: return left>right? left+1:right+1;
20: }
12. Binary Tree Inorder Traversal
Given a binary tree, return the inorder traversal of its nodes' values.
For example:
Given binary tree {1,#,2,3} ,
1
\
2
/
3

return [1,3,2].
Note: Recursive solution is trivial, could you do it iteratively?
confused what "{1,#,2,3}" means? > read more on how binary tree is serialized on OJ.
» Solve this problem

[Thoughts]
For recursion solution, it's very easy to write. But for iterative solution, we need a stack to track the visited path.
[Code]
Recursion version
1: vector<int> inorderTraversal(TreeNode *root) {
2: // Start typing your C/C++ solution below
3: // DO NOT write int main() function
4: vector<int> result;
5: inorderTra(root, result);
6: return result;
7: }
8: void inorderTra(TreeNode* node, vector<int> &result)
9: {
10: if(node == NULL)
11: {
12: return;
13: }
14: inorderTra(node->left, result);
15: result.push_back(node->val);
16: inorderTra(node->right, result);
17: }
Iteration version
1: vector<int> inorderTraversal(TreeNode *root) {
2: // Start typing your C/C++ solution below
3: // DO NOT write int main() function
4: vector<TreeNode*> sta;
5: vector<int> result;
6: if(root == NULL) return result;
7: TreeNode* node =root;
8: while(sta.size()>0 || node!=NULL)
9: {
10: while(node!=NULL)
11: {
12: sta.push_back(node);
13: node = node->left;
14: }
15: node= sta.back();
16: sta.pop_back();
17: result.push_back(node->val);
18: node =node->right;
19: }
20: return result;
21: }
Note:
Post-order iteratively travel is bit tricky. Think about it.
13. Binary Tree Level Order Traversal
Given a binary tree, return the level order traversal of its nodes' values. (ie, from left to right, level by level).
For example:
Given binary tree {3,9,20,#,#,15,7},
3
/\
9 20
/ \
15 7

return its level order traversal as:


[
[3],
[9,20],
[15,7]
]

confused what "{1,#,2,3}" means? > read more on how binary tree is serialized on OJ. » Solve this problem

[Thoughts]
Two ways to resolve this problem:

1. Breadth first search


Initial an int variable to track the node count in each level and print level by level. And here need
a QUEUE as a helper.
2. Depth first search
Rely on the recursion. Decrement level by one as you advance to the next level. When level
equals 1, you’ve reached the given level and output them.
The cons is, DFS will revisit the node, which make it less efficient than BFS. So normally, no one
use DFS in this case.

[Code]
Here, only provide the BFS solution.
1: vector<vector<int> > levelOrder(TreeNode *root) {
2: vector<vector<int> > result;
3: if(root == NULL) return result;
4: queue<TreeNode*> nodeQ;
5: nodeQ.push(root);
6: int nextLevelCnt=0, currentLevelCnt=1;
7: vector<int> layer;
8: int visitedCnt=0;
9: while(nodeQ.size() != 0)
10: {
11: TreeNode* node = nodeQ.front();
12: nodeQ.pop();
13: visitedCnt++;
14: layer.push_back(node->val);
15: if(node->left != NULL)
16: {
17: nodeQ.push(node->left);
18: nextLevelCnt++;
19: }
20: if(node->right != NULL)
21: {
22: nodeQ.push(node->right);
23: nextLevelCnt++;
24: }
25: if(visitedCnt == currentLevelCnt)
26: {
27: visitedCnt =0;
28: currentLevelCnt = nextLevelCnt;
29: nextLevelCnt=0;
30: result.push_back(layer);
31: layer.clear();
32: }
33: }
34: return result;
35: }
14. Binary Tree Maximum Path Sum
Given a binary tree, find the maximum path sum.
The path may start and end at any node in the tree.
For example:
Given the below binary tree,
1
/\
2 3

Return 6 .
» Solve this problem

[Thoughts]
For each node like below example, there should be four paths existing for max path:

1. Node only
2. L-sub + Node
3. R-sub + Node
4. L-sub + Node + R-sub
So, in the recursion process, keep tracing the four paths and pick up the max one in each step.
[Code]
1: int maxPathSum(TreeNode *root) {
2: // Start typing your C/C++ solution below
3: // DO NOT write int main() function
4: int maxAcrossRoot=INT_MIN;
5: int maxEndByRoot = GetMax(root, maxAcrossRoot);
6: return std::max(maxAcrossRoot, maxEndByRoot);
7: }
8: int GetMax(TreeNode *node, int& maxAcrossRoot)
9: {
10: if(node == NULL) return 0;
11: int left = GetMax(node->left, maxAcrossRoot);
12: int right = GetMax(node->right, maxAcrossRoot);
13: int cMax = node->val;
14: if(left>0)
15: cMax+=left;
16: if(rifht>0)
17: cMax+=right;
18: maxAcrossRoot = std::max(maxAcrossRoot, cMax);
19: return std::max(
20: node->val,
21: std::max(node->val+left, node->val+right));
22: }
15. Climbing Stairs
You are climbing a stair case. It takes n steps to reach to the top.
Each time you can either climb 1 or 2 steps. In how many distinct ways can you climb to the top?
» Solve this problem

[Thoughts]
A transformation of Fibonacci Number. (http://en.wikipedia.org/wiki/Fibonacci_number)
Solve it by one dimension dynamic programming. The transition function should be:
f(n) = f(n-1) + f(n-2) n>2;
or = 1 n=1
or = 2 n=2
[Code]
1: int climbStairs(int n) {
2: // Start typing your C/C++ solution below
3: // DO NOT write int main() function
4: int fn_2 =1, fn_1=2;
5: if(n==1) return fn_2;
6: if(n ==2) return fn_1;
7: int fn;
8: for(int i =3; i<=n; i++)
9: {
10: fn = fn_2+fn_1;
11: fn_2 = fn_1;
12: fn_1= fn;
13: }
14: return fn;
15: }
16. Combination Sum
Given a set of candidate numbers (C) and a target number (T), find all unique combinations in C where the
candidate numbers sums to T.
The same repeated number may be chosen from C unlimited number of times.
Note:

All numbers (including target) will be positive integers.


Elements in a combination (a1, a2, … , ak) must be in non-descending order. (ie, a1 ≤ a2 ≤ … ≤
ak).
The solution set must not contain duplicate combinations.

For example, given candidate set 2,3,6,7 and target 7 ,


A solution set is:
[7]
[2, 2, 3]
» Solve this problem

[Thoughts]
This is a classic recursion question. For each candidate, add its value and verify whether equals to he target. If it hit,
add it as a part of solution.
[Code]
1: vector<vector<int> > combinationSum(vector<int> &candidates, int target) {
2: // Start typing your C/C++ solution below
3: // DO NOT write int main() function
4: vector<vector<int> > result;
5: vector<int> solution;
6: int sum=0;
7: std::sort(candidates.begin(), candidates.end());
8: GetCombinations(candidates,sum, 0, target, solution, result);
9: return result;
10: }
11: void GetCombinations(
12: vector<int>& candidates,
13: int& sum,
14: int level,
15: int target,
16: vector<int>& solution,
17: vector<vector<int> >& result)
18: {
19: if(sum > target) return;
20: if(sum == target)
21: {
22: result.push_back(solution);
23: return;
24: }
25: for(int i =level; i< candidates.size(); i++)
26: {
27: sum+=candidates[i];
28: solution.push_back(candidates[i]);
29: GetCombinations(candidates, sum, i, target, solution, result);
30: solution.pop_back(); // do not miss cleaning the num
31: sum-=candidates[i];
32: }
33: }
17. Combination Sum II
Given a collection of candidate numbers (C) and a target number (T), find all unique combinations in C where the
candidate numbers sums to T.
Each number in C may only be used once in the combination.
Note:

All numbers (including target) will be positive integers.


Elements in a combination (a1, a2, … , ak) must be in non-descending order. (ie, a1 ≤ a2 ≤ … ≤
ak).
The solution set must not contain duplicate combinations.

For example, given candidate set 10,1,2,7,6,1,5 and target 8 ,


A solution set is:
[1, 7]
[1, 2, 5]
[2, 6]
[1, 1, 6]
» Solve this problem

[Thoughts]
Similar with previous "Combination Sum". But the only difference is about how to handle the index and skip
duplicate candidate. See the special logic highlighted in red.
[Code]
1: vector<vector<int> > permuteUnique(vector<int> &num) {
2: vector<vector<int> > coll;
3: vector<int> solution;
4: if(num.size() ==0) return coll;
5: vector<int> visited(num.size(), 0);
6: sort(num.begin(), num.end());
7: GeneratePermute(num, 0, visited, solution, coll);
8: return coll;
9: }
10: void GeneratePermute(vector<int> & num, int step, vector<int>& visited, vector<int>& solution,
vector<vector<int> >& coll)
11: {
12: if(step == num.size())
13: {
14: coll.push_back(solution);
15: return;
16: }
17: for(int i =0; i< num.size(); i++)
18: {
19: if(visited[i] == 0)
20: {
21: visited[i] = 1;
22: solution.push_back(num[i]);
23: GeneratePermute(num, step+1, visited, solution, coll);
24: solution.pop_back();
25: visited[i] =0;
26: while(i< num.size()-1 && num[i] == num[i+1])
27: i++;
28: }
29: }
30: }
18. Combinations
Given two integers n and k, return all possible combinations of k numbers out of 1 ... n.
For example,
If n = 4 and k = 2, a solution is:
[
[2,4],
[3,4],
[2,3],
[1,2],
[1,3],
[1,4],
]

» Solve this problem

[Thoughts]
Similar as previous "Conbination Sum". But here the terminate condition is "k", not sum. In code, the difference is
about the termination condition. See highlight code.
[Code]
1: vector<vector<int> > combine(int n, int k) {
2: // Start typing your C/C++ solution below
3: // DO NOT write int main() function
4: vector<vector<int> > result;
5: vector<int> solution;
6: GetCombine(n,k,1, solution, result);
7: return result;
8: }
9: void GetCombine(
10: int n,
11: int k,
12: int level,
13: vector<int>& solution,
14: vector<vector<int> >& result)
15: {
16: if(solution.size() == k)
17: {
18: result.push_back(solution);
19: return;
20: }
21: for(int i =level; i<= n; i++)
22: {
23: solution.push_back(i);
24: GetCombine(n,k,i+1, solution, result);
25: solution.pop_back();
26: }
27: }
19. Construct Binary Tree from Preorder and Inorder Traversal
Given preorder and inorder traversal of a tree, construct the binary tree.
Note:
You may assume that duplicates do not exist in the tree.
» Solve this problem

[Thoughts]
Let’s see some example first.

_______7______
/ \
__10__ ___2
/ \ /
4 3 _8
\ /
1 11
The preorder and inorder traversals for the binary tree above is:
preorder = {7,10,4,3,1,2,8,11}
inorder = {4,10,3,1,7,11,8,2}

The first node in preorder always the root of the tree. We can break the tree like:
1st round:
preorder: {7}, {10,4,3,1}, {2,8,11}
inorder: {4,10,3,1}, {7}, {11, 8,2}

_______7______
/ \
{4,10,3,1} {11,8,2}

Since we already find that {7} will be the root, and in "inorder" traversals, all the data in the left of {7} will
construct the left sub-tree. And the right part will construct a right sub-tree. We can the left and right part agin based
on the preorder.
2nd round
left part right part
preorder: {10}, {4}, {3,1} {2}, {8,11}
inorder: {4}, {10}, {11,8}, {2}

_______7______
/ \
__10__ ___2
/ \ /
4 {3,1} {11,8}

see that, {10} will be the root of left-sub-tree and {2} will be the root of right-sub-tree.
Same way to split {3,1} and {11,8}, yo will get the complete tree now.

_______7______
/ \
__10__ ___2
/ \ /
4 3 _8
\ /
1 11

So, simulate this process from bottom to top with recursion as following code.
[Code]
1: TreeNode *buildTree(
2: vector<int> &preorder,
3: vector<int> &inorder) {
4: // Start typing your C/C++ solution below
5: // DO NOT write int main() function
6: return BuildTreePI(
7: preorder, inorder, 0, preorder.size()-1, 0, preorder.size());
8: }
9: TreeNode* BuildTreePI(
10: vector<int> &preorder,
11: vector<int> &inorder,
12: int p_s, int p_e,
13: int i_s, int i_e)
14: {
15: if(p_s > p_e)
16: return NULL;
17: int pivot = preorder[i_s];
18: int i =p_s;
19: for(;i< p_e; i++)
20: {
21: if(inorder[i] == pivot)
22: break;
23: }
24: TreeNode* node = new TreeNode(pivot);
25: node->left = BuildTreePI(preorder, inorder, p_s, i-1, i_s+1, i-p_s+i_s);
26: node->right = BuildTreePI(preorder, inorder, i+1, p_e, i-p_s+i_s+1, i_e);
27: return node;
28: }
20. Container With Most Water
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.
» Solve this problem

[Thoughts]
Think a while and still no idea? This problem is actually challenge! Let’s bring in a hint here.

For any container, its volume depends on the shortest board.


Get the idea? The solution is actually simple. Two-pointer scanning. And always move the pointer with shorter
board. The next max will only happen when you try to change the shorter board!
[Code]
1: int maxArea(vector<int> &height) {
2: // Start typing your C/C++ solution below
3: // DO NOT write int main() function
4: int start =0;
5: int end = height.size()-1;
6: int maxV = INT_MIN;
7: while(start<end)
8: {
9: int contain = min(height[end], height[start]) * (end-start);
10: maxV = max(maxV, contain);
11: if(height[start]<= height[end])
12: {
13: start++;
14: }
15: else
16: {
17: end--;
18: }
19: }
20: return maxV;
21: }
21. Convert Sorted Array to Binary Search Tree
Given an array where elements are sorted in ascending order, convert it to a height balanced BST.
» Solve this problem

[Thoughts]
If we build BST from array, we can build it from top to bottom, like
1. choose the middle one as root,
2. build left sub BST via left part array
3. build right sub BST via right part array
4. do this recursively.
[Code]
1: TreeNode *sortedArrayToBST(vector<int> &num) {
2: return BuildTree(num, 0, num.size()-1);
3: }
4: TreeNode *BuildTree(vector<int> &num, int start, int end)
5: {
6: if(start>end) return NULL;
7: if(start == end) return new TreeNode(num[start]);
8: int mid = (start+end)/2;
9: TreeNode *node = new TreeNode(num[mid]);
10: node->left = BuildTree(num, start, mid-1);
11: node->right = BuildTree(num, mid+1, end);
12: return node;
13: }
22. Convert Sorted List to Binary Search Tree
Given a singly linked list where elements are sorted in ascending order, convert it to a height balanced BST.
» Solve this problem

[Thoughts]
It is similar with "Convert Sorted Array to Binary Search Tree". But the difference here is we have no way to
random access item in O(1), because it is linked list.
If we build BST from array, we can build it from top to bottom, like
1. choose the middle one as root,
2. build left sub BST
3. build right sub BST
4. do this recursively.
But for linked list, we can't do that because Top-To-Bottom are heavily relied on the index operation.
As an alternative solution, we can use Bottom-TO-Top:
1. Get the length of list first
2. Travel the tree in-order and populate the tree node. The bottom-up approach enables us to access
the list in its order while creating nodes.
With this, we no longer need to find the middle element.
[Code]
1: TreeNode *sortedListToBST(ListNode *head) {
2: // Start typing your C/C++ solution below
3: // DO NOT write int main() function
4: int len =0;
5: ListNode *p = head;
6: while(p)
7: {
8: len++;
9: p = p->next;
10: }
11: return BuildBST(head, 0, len-1);
12: }
13: TreeNode* BuildBST(ListNode*& list, int start, int end)
14: {
15: if (start > end) return NULL;
16: int mid = (start+end)/2;
17: TreeNode *leftChild = BuildBST(list, start, mid-1);
18: TreeNode *parent = new TreeNode(list->val);
19: parent->left = leftChild;
20: list = list->next;
21: parent->right = BuildBST(list, mid+1, end);
22: return parent;
23: }
23. Count and Say
The count-and-say sequence is the sequence of integers beginning as follows:
1, 11, 21, 1211, 111221, ...
1 is read off as "one 1" or 11.
11 is read off as "two 1s" or 21.
21 is read off as "one 2, then one 1" or 1211.
Given an integer n, generate the nth sequence.
Note: The sequence of integers will be represented as a string.
» Solve this problem

[Thoughts]
No trick here. Only some string operations. The only beautiful thing is Line9. seq[seq.size()] always '\0'. It will help
to save an "if" statement.
[Code]
1: string countAndSay(int n) {
2: string seq = "1";
3: int it = 1;
4: while(it<n)
5: {
6: stringstream newSeq;
7: char last = seq[0];
8: int count =0;
9: for(int i =0; i<= seq.size();i++)
10: {
11: if(seq[i] ==last)
12: {
13: count ++;
14: continue;
15: }
16: else
17: {
18: newSeq<<count<<last;
19: last = seq[i];
20: count =1;
21: }
22: }
23: seq = newSeq.str();
24: it++;
25: }
26: return seq;
27: }
24. Decode Ways
A message containing letters from A-Z is being encoded to numbers using the following mapping:
'A' -> 1
'B' -> 2
...
'Z' -> 26

Given an encoded message containing digits, determine the total number of ways to decode it.
For example,
Given encoded message "12", it could be decoded as "AB" (1 2) or "L" (12).
The number of ways decoding "12" is 2.
» Solve this problem

[Thoughts]
Similar as previous "Climbing Stairs". DP. Just add some logic to compare character.
Transformation function can be defined as:
Count[i] = Count[i-1] if S[i-1] is a valid char
or = Count[i-1] + Count[i-2] if S[i-1] and S[i-2] together is still a valid char.
[Code]
1: int numDecodings(string s) {
2: if(s.empty() || s[0] =='0') return 0;
3: if(s.size() ==1) return check(s[0]);
4: int fn=0, fn_1=0, fn_2=1;
5: fn_1 = (check(s[0]) * check(s[1]))+check(s[0], s[1]);
6: for(int i=2; i< s.size(); i++)
7: {
8: if(check(s[i])) fn+= fn_1;
9: if(check(s[i-1], s[i])) fn+=fn_2;
10: if(fn ==0)
11: return 0;
12: fn_2 = fn_1;
13: fn_1 = fn;
14: fn=0;
15: }
16: return fn_1;
17: }
18: int check(char one)
19: {
20: return (one != '0') ? 1 : 0;
21: }
22: int check(char one, char two)
23: {
24: return (one == '1' || (one == '2' && two <= '6'))? 1 : 0;
25: }
25. Distinct Subsequences
Given a string S and a string T, count the number of distinct subsequences of T in S.
A subsequence of a string is a new string which is formed from the original string by deleting some (can be none) of
the characters without disturbing the relative positions of the remaining characters. (ie, "ACE" is a subsequence
of "ABCDE"while "AEC" is not).
Here is an example:
S = "rabbbit", T = "rabbit"
Return 3.
» Solve this problem

[Thoughts]
DP again. The key is how to get the transition function. Let’s define t[i][j] as the number of dictinct subsequences of
T[0,i] in S[0,j]
If the last character in T[0,i] not equals the last character in S[0,j], that is, T[i] != S[j], the t[i][j] is exactly same as
t[i][j-1].
But if they are equal, that is T[i] == S[j], there are two possibilities:

Don’t use S[j] to match. The count of distinct subsequences of T[0,i] in S[0,j-1]
Use S[j] to match. The count of distinct subsequences of T[0,i-1] in S[0,j-1]

So t[i][j] = t[i][j-1] + t[i-1][j-1]


The transition function is
t[i][j] = t[i][j-1] if T[i] != S[j]
or = t[i][j-1] + t[i-1][j-1] if T[i] == S[j]

[Code]
1: int numDistinct(string S, string T) {
2: // Start typing your C/C++ solution below
3: // DO NOT write int main() function
4: int match[200];
5: if(S.size() < T.size()) return 0;
6: match[0] = 1;
7: for(int i=1; i <= T.size(); i++)
8: match[i] = 0;
9: for(int i=1; i<= S.size(); i ++)
10: for(int j =T.size(); j>=1; j--)
11: if(S[i-1] == T[j-1])
12: match[j]+= match[j-1];
13: return match[T.size()];
14: }
26. Divide Two Integers
Divide two integers without using multiplication, division and mod operator.
[Thoughts]
bit operation. The main idea is to simulate the division by

1. rotating the divisor to the left(<<1) until finding the number which is most close to
dividend.
2. Substract the dividend by the rotated divisor and get the difference as the new dividend.
3. Repeat doing #1 and #2 until dividend is zero

[Code]
1: int divide(int dividend, int divisor) {
2: // Start typing your C/C++ solution below
3: // DO NOT write int main() function
4: int sign = 1;
5: if(dividend ==0) return 0;
6: if(dividend <0) sign*=-1;
7: if(divisor <0) sign *=-1;
8: unsigned int dvd = dividend >0? dividend: -dividend;
9: unsigned int dvs = divisor >0? divisor: -divisor;//abs(divisor);
10: unsigned int inc[32];
11: unsigned int migValue = dvs;
12: int i =0;
13: while(migValue > 0 && migValue <= dvd)
14: {
15: inc[i] = migValue;
16: migValue = migValue <<1;
17: i++;
18: }
19: i--;
20: unsigned int res = 0;
21: while(i>=0 && dvd!=0)
22: {
23: if(dvd >= inc[i])
24: {
25: dvd = dvd - inc[i];
26: res += 1<<i;
27: }
28: i--;
29: }
30: res*= sign;
31: return res;
32: }
27. Edit Distance
Given two words word1 and word2, find the minimum number of steps required to convert word1 to word2. (each
operation is counted as 1 step.)
You have the following 3 operations permitted on a word:
a) Insert a character
b) Delete a character
c) Replace a character
» Solve this problem

[Thoughts]
This is an interesting problem. This is a two-dimension dynamic programming.
Define d(i,j) as the edit distance of A[0, i] and B[0, j]. If assume A[0, i] as somestr1c and B[0, j] as somestr2d, we
can get following assumption too:

The edit distance of “somestr1” and “somestr2”is d(i-1,j-1)


The edit distance of “somestr1” and “somestr2” is d(i,j-1)
The edit distance of “somestr1” and “somestr2d” is d(i-1,j)

Based on these three variable, we can derive the d(i,j) as :

If c==d, it is obvious that d(i,j) is same as d(i-1,j-1)


If c!=d, let’s see how to convert,
If replace c with d, the edit distance is the one converting “somestr1” to
“somestr2” plus 1, that is, d(i-1,j-1) + 1
if append d after c, the edit distance is the one converting “somestr1c” to
“somestr2” plus , that is, d(i,j-1) + 1
if delete c, the edit distance is the one converting “somestr1” to “somestr2d”,
that is, d(i-1,j) + 1

After comaring the 3 edit distances, pick up the minimal one as the solution.
So, the transition function is here:
dp[i][j] = dp[i-1][j-1] if (A[i] == B[j])
or = min(dp[i][j-1], dp[i-1][j],
dp[i-1][j-1]) +1; if A[i] != B[j]
or = j if i ==0
or = i if j ==0

[Code]
No need to initialize a two-dimension array to represent d[i,j]. Here, use two iterative arrays.
1: int minDistance(string word1, string word2) {
2: int * matchUp = new int[20000];
3: int* matchDown = new int[20000];
4: for(int i=0; i<= smallStr.size(); i++)
5: {
6: matchUp[i] = 0;
7: matchDown[i] = i;
8: }
9: for(int i=1; i<=word1.size(); i++)
10: {
11: matchUp[0] = i;
12: for(int j= 1; j<=word2.size(); j++)
13: {
14: if(word1[i-1] == word2[j-1])
15: {
16: matchUp[j] = matchDown[j-1];
17: }
18: else
19: {
20: matchUp[j] = min(matchDown[j], matchDown[j-1]);
21: matchUp[j] = min(matchUp[j], matchUp[j-1]) +1;
22: }
23: }
24: int* temp = matchUp;
25: matchUp = matchDown;
26: matchDown = temp;
27: }
28: return matchDown[word2.size()];
29: }
28. First Missing Positive
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.
» Solve this problem

[Thoughts]
If there is a unlimited array C here, we can use counting sort. Like for each A[i], set C[A[i]] =1. After iterating array
A, iterate array C and return the first element which is zero.
But unfortunately, only constant space is available. In this case, reuse array A.
Maintain A as a sorted array, during the iteration, for each A[i],
If A[i] != i, keep swapping A[i] and A[ A[i] ], until either A[i] == A[A[i]] or no element availale
to
Then, go through array A again, and find the first element which not meet A[i] ==i condition.
[Code]
In the real implementation, there is a little trick. Since problem asked for positive number, so, no need to store zero.
A[0] should be used to store number 1 instead of 0. The equation below used is A[i] == i+1, not A[i] == i. See the
highlight part for this trick.
1: int firstMissingPositive(int A[], int n) {
2: // Start typing your C/C++ solution below
3: // DO NOT write int main() function
4: int i =0;
5: for(int i =0; i< n; i++)
6: {
7: while(A[i] != i+1)
8: {
9: if(A[i] <= 0 || A[i] >n || A[i] == A[A[i] -1]) break;
10: int temp = A[i];
11: A[i] = A[temp-1];
12: A[temp-1] = temp;
13: }
14: }
15: for(int i =0; i< n; i++)
16: if(A[i]!=i+1)
17: return i+1;
18: return n+1;
19: }
29. Flatten Binary Tree to Linked List
Given a binary tree, flatten it to a linked list in-place.
For example,
Given
1
/\
2 5
/\ \
3 4 6

The flattened tree should look like:

1
\
2
\
3
\
4
\
5
\
6

click to show hints.


» Solve this problem

[Thoughts]
flatten the tree in recursion. For each node K,

1. Flatten the left sub-tree to a linked list A


2. Insert node K to the linked list A and as the new head
3. Flatten the right sub-tree to a linked list B, and append B to the end of A.

[Code]
1: void flatten(TreeNode *root) {
2: // Start typing your C/C++ solution below
3: // DO NOT write int main() function
4: if(root == NULL)
5: return;
6: ConvertToLink(root);
7: }
8: TreeNode* ConvertToLink(TreeNode* node)
9: {
10: if(node->left == NULL && node->right == NULL)
11: return node;
12: TreeNode* rHead = NULL;
13: if(node->right != NULL) // flatten right-sub tree first
14: rHead = ConvertToLink(node->right);
15: TreeNode* p = node;
16: if(node->left!=NULL)
17: {
18: TreeNode* lHead = ConvertToLink(node->left);
19: node->right = lHead;
20: lHead->left = NULL;
21: node->left = NULL;
22: while(p->right!=NULL)// move p to the tail
23: p = p->right;
24: }
25: if(rHead != NULL)
26: { // link the left sub-tree and right sub-tree together
27: p->right = rHead;
28: rHead->left = NULL;
29: }
30: return node;
31: }
[Notes]
1. Line 13~14
In the real implementation, if flatten left sub-tree first and then the right sub-tree, the structure of the tree will be
damaged. E.g. {1,2,3} ,
1
/ \
2 3
After flatten left sub-tree, the structure will be changed as
1
\
2
\
3
The right sub-tree of node 1 is changed to a different location. Of cource, you can use a variable to hole the pointer
of right sub-tree before flattening the left sub-tree. But not necessary, flattening the right sub-tree first will resolve
this problem.
2. Line 20, 28
Don’t forget to clean the unused pointer.In the flattened linked list, the left pointer has no meaning here.
30. Generate Parentheses
Given n pairs of parentheses, write a function to generate all combinations of well-formed parentheses.
For example, given n = 3, a solution set is:
"((()))", "(()())", "(())()", "()(())", "()()()"
» Solve this problem

[Thoughts]
Build it in recursion,
If the count of left parenthses is less than n, can append more left parenthses;
If the count of right parenthses is less than the left one, can append more right parenthses.
[Code]
1: void CombinationPar(vector<string>& result, string& sample,
2:: int deep, int n, int leftNum, int rightNum)
3: {
4: if(deep == 2*n)
5: {
6: result.push_back(sample);
7: return;
8: }
9: if(leftNum<n)
10: {
11: sample.push_back('(');
12: CombinationPar(result, sample, deep+1, n, leftNum+1, rightNum);
13: sample.resize(sample.size()-1);
14: }
15: if(rightNum<leftNum)
16: {
17: sample.push_back(')');
18: CombinationPar(result, sample, deep+1, n, leftNum, rightNum+1);
19: sample.resize(sample.size()-1);
20: }
21: }
22: vector<string> generateParenthesis(int n) {
23: // Start typing your C/C++ solution below
24: // DO NOT write int main() function
25: vector<string> result;
26: string sample;
27: if(n!= 0)
28: CombinationPar(result, sample, 0, n, 0, 0);
29: return result;
30: }
31. Gray Code
The gray code is a binary numeral system where two successive values differ in only one bit.
Given a non-negative integer n representing the total number of bits in the code, print the sequence of gray code. A
gray code sequence must begin with 0.
For example, given n = 2, return [0,1,3,2]. Its gray code sequence is:
00 - 0
01 - 1
11 - 3
10 - 2
Note:
For a given n, a gray code sequence is not uniquely defined.
For example, [0,2,3,1] is also a valid gray code sequence according to the above definition.
For now, the judge is able to judge based on one instance of gray code sequence. Sorry about that.
» Solve this problem

[Thoughts]
look more example when n=3
000
001
011
010
110
111
101
100

And the pattern comes out. The gray code of n=k, is the reverse sequence of the gray code of n=k-1 plus 1<<k.
[Code]
1: vector<int> grayCode(int n) {
2: // Start typing your C/C++ solution below
3: // DO NOT write int main() function
4: vector<int> result;
5: result.push_back(0);
6: for(int i=0; i< n; i++)
7: {
8: int highestBit = 1<<i;
9: int len = result.size();
10: for(int i = len-1; i>=0; i--)
11: {
12: result.push_back(highestBit + result[i]);
13: }
14: }
15: return result;
16: }
And since gray code is a muture encoding protocol used in the industry, there is also a math solution.

1: vector<int> grayCode(int n)
2: {
3: vector<int> ret;
4: int size = 1 << n;
5: for(int i = 0; i < size; ++i)
6: ret.push_back((i >> 1)^i);
7: return ret;
8: }
32. Implement strStr()
Implement strStr().
Returns a pointer to the first occurrence of needle in haystack, or null if needle is not part of haystack.
» Solve this problem

[Thoughts]
It’s easy to implement a O(n^2) solution by comparing the needle with every substring in the haystack, as code
example #1. But a beauty solution is to use KMP, which provides a O(n) solution in average. But KMP need to pre-
process the string for recognizing pattern.
[Code]
1: char *strStr(char *haystack, char *needle) {
2: // Start typing your C/C++ solution below
3: // DO NOT write int main() function
4: if(haystack == NULL || needle == NULL)
5: return NULL;
6: int hLen = strlen(haystack);
7: int nLen = strlen(needle);
8: if(hLen<nLen)
9: return NULL;
10: for(int i=0; i<hLen - nLen+1; i++)
11: {
12: int j=0;
13: char* p = &haystack[i];
14: for(; j< nLen; j++)
15: {
16: if(*p != needle[j])
17: break;
18: p++;
19: }
20: if(j == nLen)
21: return &haystack[i];
22: }
23: return NULL;
24: }
But the most efficient way of implementing strStr() is to use KMP algorithm. If not familiar with KMP, search the
wiki.

1: char *strStr(char *haystack, char *needle) {


2: // Start typing your C/C++ solution below
3: // DO NOT write int main() function
4: if(haystack == NULL || needle == NULL) return NULL;
5: int hlen = strlen(haystack);
6: int nlen = strlen(needle);
7: if(nlen ==0) return haystack;
8: if(hlen == 0 ) return NULL;
9: int pattern[100000];
10: GeneratePattern(needle, nlen, pattern);
11: return Match(haystack, needle, pattern);
12: }
13: void GeneratePattern(char* str, int len, int* pattern)
14: {
15: pattern[0] = -1;
16: int k =-1;
17: for(int j =1; j< len; j++)
18: {
19: while(k >-1 && str[k+1] != str[j])
20: k = pattern[k];
21: if(str[k+1] == str[j])
22: k++;
23: pattern[j] = k;
24: }
25: }
26: char* Match(char* haystack, char* needle, int* pattern)
27: {
28: int hlen = strlen(haystack);
29: int nlen = strlen(needle);
30: int k =-1;
31: for(int j =0; j< hlen; j++, haystack++)
32: {
33: while(k >-1 && needle[k+1] != *haystack)
34: k = pattern[k];
35: if(needle[k+1] == *haystack)
36: k++;
37: if(k == nlen-1)
38: return haystack-k;
39: }
40: return NULL;
41: }
33. Insert 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].
» Solve this problem

[Thoughts]
Iterate the interval one by one,
If the new interval’s end is less than current interval’s start, insert the new interval here
If the new interval has overlap with current interval, merge two intervals together as the new interval for
next inserting.
[Code]
1: vector<Interval> insert(vector<Interval> &intervals, Interval newInterval) {
2: vector<Interval>::iterator it = intervals.begin();
3: while(it!= intervals.end())
4: {
5: if(newInterval.end < it->start)
6: {
7: intervals.insert(it, newInterval);
8: return intervals;
9: }
10: else if(newInterval.start > it->end)
11: {
12: it++;
13: continue;
14: }
15: else
16: {
17: newInterval.start = min(newInterval.start, it->start);
18: newInterval.end = max(newInterval.end, it->end);
19: it =intervals.erase(it);
20: }
21: }
22: intervals.insert(intervals.end(), newInterval);
23: return intervals;
24: }

[More challenge]
If the intervals are distributed in a ring, and currently give you a new interval, how could you insert the interval to
the ring? For example, if the ring is [0,255], and there is a interval [1,234] in the ring, currently insert a new interval
[222,4], what’s the result? The result should [1,4]! And you can see lots of tricky cases in the boundary.
The solution is simple, actually, if the interval across 0, split into two parts and merge them in the ring seperatelly.
For example, if given an interval [234,7] to insert, split this interval to two [234,255], [0,7] and insert them one by
one. And at the end, check the head element and tail element, if they are linked, merge them together.
34. Integer to Roman
Given an integer, convert it to a roman numeral.
Input is guaranteed to be within the range from 1 to 3999.
» Solve this problem

[Thoughts]
An implementation problem. The challenge is how to handle the digit conversion in different partition range:

1<=digit <=3
digit =4
digit = 5
5<digit<=8
digit =9

[Code]
1: string intToRoman(int num) {
2: // Start typing your C/C++ solution below
3: // DO NOT write int main() function
4: char symbol[7] = { 'I','V','X', 'L','C', 'D','M'};
5: string roman;
6: int scale = 1000;
7: for(int i =6; i>=0; i-=2)
8: {
9: int digit = num/scale;
10: if(digit != 0)
11: {
12: if(digit <= 3)
13: {
14: roman.append(digit, symbol[i]);
15: }
16: else if(digit ==4)
17: {
18: roman.append(1, symbol[i]);
19: roman.append(1, symbol[i+1]);
20: }
21: else if(digit ==5)
22: {
23: roman.append(1, symbol[i+1]);
24: }
25: else if(digit <=8)
26: {
27: roman.append(1, symbol[i+1]);
28: roman.append(digit-5, symbol[i]);
29: }
30: else if(digit ==9)
31: {
32: roman.append(1, symbol[i]);
33: roman.append(1, symbol[i+2]);
34: }
35: }
36: num = num%scale;
37: scale/=10;
38: }
39: return roman;
40: }
35. 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.
» Solve this problem

[Thoughts]
Could we do this via merge sort like below?
1: bool isInterleave(string s1, string s2, string s3) {
2: // Start typing your C/C++ solution below
3: // DO NOT write int main() function
4: if(s3.size() != (s1.size() + s2.size()))
5: {
6: return false;
7: }
8: int i =0, j= 0, k=0;
9: while(i< s1.size() && j< s2.size())
10: {
11: if(s1[i] == s3[k])
12: {
13: i ++;
14: }
15: else if(s2[j] == s3[k])
16: {
17: j++;
18: }
19: else
20: {
21: return false;
22: }
23: k++;
24: }
25: while(i< s1.size())
26: {
27: if(s1[i] == s3[k])
28: {
29: i++;k++;
30: }
31: else
32: {
33: return false;
34: }
35: }
36: while(j<s2.size())
37: {
38: if(s2[j] == s3[k])
39: {
40: j++;k++;
41: }
42: else
43: {
44: return false;
45: }
46: }
47: return true;
48: }
The answer is NO. Because merge sort didn’t conside the combination of S1 and S2. For example, {"C","CA",
"CAC"}.

This is still a dynamic programming problem. Let’s define the S1, S2, and S3 as below:
s1 = a1, a2 ........a(i-1), ai
s2 = b1, b2, .......b(j-1), bj
s3 = c1, c3, .......c(i+j-1), c(i+j)
Define match[i][j] as S1[0, i] and S2[0,j] matches S3[0, (i+j)].
If ai == c(i+j), we know match[i][j] = match[i-1][j]. see below example.
s1 = a1, a2 ........a(i-1)
s2 = b1, b2, .......b(j-1), bj
s3 = c1, c3, .......c(i+j-1)
The same as, if bj == c(i+j), match[i][j] = match[i][j-1].
So, the transition function shoule be:
Match[i][j]

= (s3.lastChar == s1.lastChar) && Match[i-1][j]

||(s3.lastChar == s2.lastChar) && Match[i][j-1]

Initia conditions :

i=0 && j=0 , Match[0][0] = true;

i=0 , s3[j] = s2[j], Match[0][j] |= Match[0][j-1]

s3[j] != s2[j], Match[0][j] = false;

j=0 , s3[i] = s1[i], Match[i][0] |= Match[i-1][0]

s3[i] != s1[i], Match[i][0] = false;

[Code]
1: bool isInterleave(string s1, string s2, string s3) {
2: // Start typing your C/C++ solution below
3: // DO NOT write int main() function
4: bool *matchUp = new bool[s2.size() +1];
5: bool *matchDown = new bool[s2.size()+1];
6: if(s3.size() != (s1.size() + s2.size())) return false;
7: //initialize
8: matchDown[0] = true;
9: for(int i =1; i< s2.size() +1; i++)
10: {
11: if(s2[i-1] == s3[i-1])
12: matchDown[i] |= matchDown[i-1];
13: else
14: matchDown[i]= false;
15: }
16: matchUp[0] = true;
17: for(int i =1; i< s1.size() +1; i++)
18: {
19: if(s1[i-1] == s3[i-1])
20: matchUp[0] |= matchDown[0];
21: else
22: matchUp[0]= false;
23: for(int j =1;j<s2.size() +1; j++)
24: {
25: matchUp[j]=false;
26: if(s1[i-1] == s3[i+j-1])
27: {
28: matchUp[j] |= matchDown[j];
29: }
30: if(s2[j-1] == s3[i+j-1])
31: {
32: matchUp[j] |= matchUp[j-1];
33: }
34: }
35: bool* temp = matchUp;
36: matchUp = matchDown;
37: matchDown = temp;
38: }
39: delete matchup;
40: delete matchDown;
41: return matchDown[s2.size()];
42: }
36. Jump Game
Given an array of non-negative integers, you are initially positioned at the first index of the array.
Each element in the array represents your maximum jump length at that position.
Determine if you are able to reach the last index.
For example:
A = [2,3,1,1,4], return true.
A = [3,2,1,0,4], return false.
» Solve this problem

[Thoughts]
One- dimension dynamic programming. If define jump[i] as the max left steps when jumps from 0 to I, the
transition function can be derived as below
jump[i] = max(jump[i-1], A[i-1]) -1, i!=0
= 0 , i==0

So scan the array from left to right, and try to find any i that leads to “jump[i]<0”. If this i exists, it means the robot
won’t be able to arrive i and return false. Otherwise, means robot can arrive the end of array, return true.
[Code]
1: bool canJump(int A[], int n) {
2: // Start typing your C/C++ solution below
3: // DO NOT write int main() function
4: int* jump = new int[n];
5: jump[0] = 0;
6: for(int i=1; i < n; i++)
7: {
8: jump[i] = max(jump[i-1], A[i-1]) -1;
9: if(jump[i] <0)
10: return false;;
11: }
12: return jump[n-1] >=0;
13: }
And here, we can also make another optimization. Do we really need an array(jump[]) to track the steps? The
answer is NO. We can also use one variable to track the maximal right boundary this robot can reach. And update
this variable during the scanning. If the variable already reaches the end of the array, return true.
1: bool canJump(int A[], int n) {
2: int maxCover = 0;
3: for(int start =0; start<= maxCover && start<n; start++)
4: {
5: if(A[start]+start > maxCover)
6: maxCover = A[start]+start;
7: if(maxCover >= n-1) return true;
8: }
9: return false;
10: }
37. Jump Game II
Given an array of non-negative integers, you are initially positioned at the first index of the array.
Each element in the array represents your maximum jump length at that position.
Your goal is to reach the last index in the minimum number of jumps.
For example:
Given array A = [2,3,1,1,4]
The minimum number of jumps to reach the last index is 2. (Jump 1 step from index 0 to 1, then 3 steps to the last
index.)
» Solve this problem

[Thoughts]
Greedy search. Scan the integer array from left to right, for each element, calculate the max right boundary it can
reach(A[i] + i).
In the implementation, can use a dynamic window to track the search range. Update the range index after each round
scanning.
[Code]
1: int jump(int A[], int n) {
2: // Start typing your C/C++ solution below
3: // DO NOT write int main() function
4: int start = 0;
5: int end = 0;
6: int count =0;
7: if(n == 1) return 0;
8: while(end < n)
9: {
10: int max = 0;
11: count++;
12: for(int i =start; i<= end ; i++ )
13: {
14: if(A[i]+i >= n-1)
15: {
16: return count;
17: }
18: if(A[i]+ i > max)
19: max = A[i]+i;
20: }
21: start = end+1;
22: end = max;
23: }
24: }
38. Largest Rectangle in Histogram
Given n non-negative integers representing the histogram's bar height where the width of each bar is 1, find the area
of largest rectangle in the histogram.

Above is a histogram where width of each bar is 1, given height = [2,1,5,6,2,3].

The largest rectangle is shown in the shaded area, which has area = 10 unit.
For example,
Given height = [2,1,5,6,2,3],
return 10.
» Solve this problem

[Thoughts]
Really good problem. The most straight forward solution is, scan the height value from left to right, and for each
height scanned, iterate all the previous height to calculate the rectangle, and track the maximal value. The time
complexity is O(n^2).

1: int largestRectangleArea(vector<int> &height) {


2: // Start typing your C/C++ solution below
3: // DO NOT write int main() function
4: //int result[height.size()];
5: int maxV = 0;
6: for(int i =0; i< height.size(); i++)
7: {
8: int minV = height[i];
9: for(int j =i; j>=0; j--)
10: {
11: minV = std::min(minV, height[j]);
12: int area = minV*(i-j+1);
13: if(area > maxV)
14: maxV = area;
15: }
16: }
17: return maxV;
18: }
As you see, previous code contains a lot of duplicate computation. Not every height value worths an iteration. A
small improvement is, only trigger the calculation when there is a peak. See below red code.
1: int largestRectangleArea(vector<int> &height) {
2: int maxV = 0;
3: for(int i =0; i< height.size(); i++)
4: {
5: if(i+1 < height.size() &&
6: height[i] <= height[i+1]) // if not peak node, skip it
7: continue;
8: int minV = height[i];
9: for(int j =i; j>=0; j--)
10: {
11: minV = std::min(minV, height[j]);
12: int area = minV*(i-j+1);
13: if(area > maxV)
14: maxV = area;
15: }
16: }
17: return maxV;
18: }
So, for a O(n^2) solution, we are done. But, could we do better? Yes, there is also a O(n) solution.
As showed in below figure, look at Height #4(the red dotted line), which is less than previous Height #3 and #2.
When we process Height #4, we know it doesn need to maintain Height #2 and #3 anymore, because in later part,
there won’t be any rectangle which can make use of #2 and #3. In this case, we can eliminate the diff part (black)
and combine #2, #3 and #4 together as a new rectangle for later processing.

Here, the solution comes out. Open a stack which holds the element in increasing order. Each time, compare the
processing height with the top of stack. If the current height is larger than the top element of stack, push the current
height into stack as the new top. Otherwise, merge the current height with the top element of stack and keep doing
this until the top element is less than current height. One trick here is, at the end, we need to push a zero into the
stack to kick the merge process with all the elements in the stack.

1: int largestRectangleArea(vector<int> &h) {


2: stack<int> S;
3: h.push_back(0); // the last trigger
4: int sum = 0;
5: for (int i = 0; i < h.size(); i++) {
6: if (S.empty() || h[i] > h[S.top()]) S.push(i);
7: else {
8: int tmp = S.top();
9: S.pop();
10: sum = max(sum, h[tmp]*(S.empty()? i : i-S.top()-1));
11: i--;
12: }
13: }
14: return sum;
15: }
39. Length of Last Word
Given a string s consists of upper/lower-case alphabets and empty space characters ' ', return the length of last word
in the string.
If the last word does not exist, return 0.
Note: A word is defined as a character sequence consists of non-space characters only.
For example,
Given s = "Hello World",
return 5.
» Solve this problem

[Thoughts]
An interesting implementation problem. There are 4 possibilities of the last word as below (* stands for zero or more
empty spaces)
1. "*"
2. "*word"
3. "*word*"
4. "word*"
So the algorithm is, scan the string from back to front. Skip all empty spaces at the end and capture the first word.
[Code]
1: int lengthOfLastWord(const char *s) {
2: int len = strlen(s);
3: if( len== 0) return 0;
4: int i = len-1;
5: while(s[i] == ' ' && i>=0) i--;
6: if(i == -1)
7: {
8: return 0;
9: }
10: int end = i;
11: for(; i >=0; i--)
12: {
13: if(s[i] == ' ')
14: break;
15: }
16: if(i ==-1)
17: return end+1;
18: return end-i;
19: }

The previous code is good. But not beauty enough. It can also be implemented as below
1: int lengthOfLastWord(const char *s) {
2: int len = strlen(s);
3: int count = 0;
4: for(int i =len-1; i>=0; i--)
5: {
6: if(s[i] == ' ')
7: {
8: if(count ==0) continue;
9: else return count;
10: }
11: count++;
12: }
13: return count;
14: }
40. Letter Combinations of a Phone Number
Given a digit string, return all possible letter combinations that the number could represent.
A mapping of digit to letters (just like on the telephone buttons) is given below.

Input:Digit string "23"


Output: ["ad", "ae", "af", "bd", "be", "bf", "cd", "ce", "cf"].

Note:
Although the above answer is in lexicographical order, your answer could be in any order you want.
» Solve this problem

[Thoughts]
A classical recursion problem. Similar as permutation.
[Code]
1: vector<string> letterCombinations(string digits) {
2: string trans[] = {"", " ", "abc", "def", "ghi", "jkl",
3: "mno", "pqrs", "tuv", "wxyz"};
4: vector<string> set;
5: string seq;
6: Generater(trans, digits, 0, seq, set);
7: return set;
8: }
9: void Generater(string trans[], string& digits,
10: int deep, string& result, vector<string>& set)
11: {
12: if(deep == digits.size())
13: {
14: set.push_back(result);
15: return;
16: }
17: int curDig = digits[deep] - 48; // convert ACSII code to integer
18: for(int i =0; i < trans[curDig].size(); i++)
19: {
20: result.push_back(trans[curDig][i]);
21: Generater(trans, digits, deep+1, result, set);
22: result.resize(result.size() -1);
23: }
24: }
41. Longest Common Prefix
Write a function to find the longest common prefix string amongst an array of strings.
» Solve this problem

[Thoughts]
An implementation problem. Add character to prefix one by one. And for each character, compare it with all strings.
If it matches all the strings, add it to prefix. If not, break and return exsiting prefix as the longest one.
[Code]
1: string longestCommonPrefix(vector<string> &strs) {
2: string prefix;
3: if(strs.size() ==0) return prefix;
4: int len =0;
5: while(1)
6: {
7: char var;
8: int i=0;
9: for(; i< strs.size(); i++)
10: {
11: if(i ==0) var =strs[0][len];
12: if(strs[i].size() == len || var != strs[i][len])
13: break;
14: }
15: if(i!= strs.size())
16: break;
17: len++;
18: prefix.append(1, var);
19: }
20: return prefix;
21: }
42. Longest Palindromic Substring
Given a string S, find the longest palindromic substring in S. You may assume that the maximum length of S is
1000, and there exists one unique longest palindromic substring.
» Solve this problem

[Thoughts]
What an interesting problem! Define P[i,j] as below:
P[i,j] = 1 if range[i,j] is a palindrome.
P[i,j] = 0 if range[i,j] is not a palindrome
Let’s see an example first. Suppose S="abccb",
S= a b c c b
Index = 0 1 2 3 4
P[0,0] =1 //each char is a palindrome
P[0,1] =S[0] == S[1] , P[1,1] =1
P[0,2] = S[0] == S[2] && P[1,1], P[1,2] = S[1] == S[2] , P[2,2] = 1
P[0,3] = S[0] == S[3] && P[1,2], P[1,3] = S[1] == S[3] && P[2,2] , P[2,3] =S[2] ==S[3], P[3,3]=1
......................
Base on these derivation, we can get the transition function as below:
P[i,j] = 1 if i ==j
= S[i] ==S[j] if j = i+1
= S[i] == S[j] && P[i+1][j-1] if j>i+1
[Code]
1: string longestPalindrome(string s) {
2: int len = s.size();
3: int P[len][len];
4: memset(P, 0, len*len*sizeof(int));
5: int maxL=0, start=0, end=0;
6: for(int i =0; i< s.size(); i++)
7: {
8: for(int j =0; j<i; j++)
9: {
10: P[j][i] = (s[j] == s[i] && (i-j<2 || P[j+1][i-1]));
11: if(P[j][i] && maxL < (i-j+1))
12: {
13: maxL = i-j+1;
14: start = j;
15: end = i;
16: }
17: }
18: P[i][i] =1;
19: }
20: return s.substr(start, end-start +1);
21: }
43. Longest Substring Without Repeating Characters
Given a string, find the length of the longest substring without repeating characters. For example, the longest
substring without repeating letters for "abcabcbb" is "abc", which the length is 3. For "bbbbb" the longest substring
is "b", with the length of 1.
» Solve this problem

[Thoughts]
Scan the string from left to right. If meets repeating character, use the index of previous repeating character as the
new start index of search. Keep doing this until arrives the end of string.
See below example:

[Code]
1: int lengthOfLongestSubstring(string s) {
2: int count[26];
3: memset(count, -1, 26*sizeof(int));
4: int len=0, maxL = 0;
5: for(int i =0; i< s.size(); i++,len++)
6: {
7: if(count[s[i]-'a']>=0)
8: {
9: maxL = max(len, maxL);
10: len =0;
11: i = count[s[i]-'a']+1;
12: memset(count, -1, 26*sizeof(int));
13: }
14: count[s[i]-'a']=i;
15: }
16: return max(len, maxL);
17: }
Note:
1. Line 3, since we store the index in array, so initializing the array as 0 will mistake the logic.
2. Line 16, catch the last string. for example, "abcd", if no Line 16, it will just return 0 since the Line 9 won't be
triggered.
44. Maximum Depth of Binary Tree
Given a binary tree, find its maximum depth.
The maximum depth is the number of nodes along the longest path from the root node down to the farthest leaf
node.
» Solve this problem

[Thoughts]
Define Max[K] as the maximal depth of node K(no matter where this K is in the tree). We can derive the transition
function as
Max [ K ] = max ( Max[K->left] , Max[K->right]) + 1
And, implement it as below.
[Code]
1: int maxDepth(TreeNode *root) {
2: // Start typing your C/C++ solution below
3: // DO NOT write int main() function
4: if(root == NULL)
5: return 0;
6: int lmax = maxDepth(root->left);
7: int rmax = maxDepth(root->right);
8: return max(lmax, rmax)+1;
9: }
Another solution is to traverse the tree in level order and count the level. You can refer to the problem “ Binary Tree
Level Order Traversal” in the later chapter.
45. Maximum Subarray
Find the contiguous subarray within an array (containing at least one number) which has the largest sum.
For example, given the array [−2,1,−3,4,−1,2,1,−5,4] ,
the contiguous subarray [4,−1,2,1] has the largest sum = 6 .
More practice:
If you have figured out the O(n) solution, try coding another solution using the divide and conquer approach, which
is more subtle.
» Solve this problem

[Thoughts]
Use one dimensional dynamic programming to achieve a O(n) complexity.
Assume there is a K existing in A(0, i), which makes A[k, i] generating the largest sum Max[i].
So, for Max[i+1], it’s easy to know get following transition function:

Max[i+1] = Max[i] + A[i+1], if (Max[i] + A[i+1] >0)


= 0, if(Max[i]+A[i+1] <0), the reason here is, A[i+1] must be a negative number, which has no value to keep.

Scan the array from left to right and easy to find the largest sum.
[Code]
1: int maxSubArray(int A[], int n) {
2: // Start typing your C/C++ solution below
3: // DO NOT write int main() function
4: int sum = 0;
5: int max = INT_MIN;
6: for(int i =0; i < n ; i ++)
7: {
8: sum +=A[i];
9: if(sum>max)
10: max = sum;
11: if(sum < 0)
12: sum = 0;
13: }
14: return max;
15: }
But this problem requires Divide & Conquer. It hints us to use binary search.
Suppose there exits a range [i,j], which generates the largest sum in A[left, right]. If use the middle value( mid =
(left + right)/2) to split the range, there are 3 conditions:

(1) subarray A[i,..j] is entirely in A[low,mid-1]


(2) subarray A[i,..j] is entirely in A[mid+1,high]
(3) subarray A[i,..j] is across mid

For Condition #1 and #2, just continue to do the recursion. But for Condition #3, it’s a little tricky. Need to search
bi-direction. Search A[left, Mid] to find the max range [i..mid], search A[mid+1, right] for A[mid+1..j], and merge
A[i.. mid] and A[mide+1.. j] together as the solution of Condition #3.
Implement as below :
1: int maxSubArray(int A[], int n) {
2: // Start typing your C/C++ solution below
3: // DO NOT write int main() function
4: int maxV = INT_MIN;
5: return maxArray(A, 0, n-1, maxV);
6: }
7: int maxArray(int A[], int left, int right, int& maxV)
8: {
9: if(left>right)
10: return INT_MIN;
11: int mid = (left+right)/2;
12: int lmax = maxArray(A, left, mid -1, maxV);
13: int rmax = maxArray(A, mid + 1, right, maxV);
14: maxV = max(maxV, lmax);
15: maxV = max(maxV, rmax);
16: int sum = 0, mlmax = 0;
17: for(int i= mid -1; i>=left; i--)
18: {
19: sum += A[i];
20: if(sum > mlmax)
21: mlmax = sum;
22: }
23: sum = 0; int mrmax = 0;
24: for(int i = mid +1; i<=right; i++)
25: {
26: sum += A[i];
27: if(sum > mrmax)
28: mrmax = sum;
29: }
30: maxV = max(maxV, mlmax + mrmax + A[mid]);
31: return maxV;
32: }
46. Median of Two Sorted Arrays
There are two sorted arrays A and B of size m and n respectively. Find the median of the two sorted arrays. The
overall run time complexity should be O(log (m+n)).
» Solve this problem

[Thoughts]
The solution to O(n) is intuitive: directly merge two arrays, then seek the median.
However, to O(log(m+n)), obviously binary-search is the solution. This is equivalent to the variation of “Kth
element in 2 sorted array”. If (m+n) is odd, then find “(m+n)/2+1 th element in 2 sorted array”. If (m+n) is even,
find (m+n)/2 th and (m+n)/2+1 th, then average them.
With regard to “ Kth element in 2 sorted array ” , the two arrays can be divided into four parts as the following
diagram by the two medians A[m/2] and B[n/2]. Abandoning which part depends on two conditions:
1 , (m/2 + n/2)?k ;
2 , A[m/2] ? B[n/2];

If (m/2 + n/2) > k, that means the current median is higher, the correct median is in either Section 1 or Section 3. If
A[m/2] > B[n/2], it means the median is absolutely not in Section 2, so this section will be abandon for the new
search. Likewise , the rest three circumstances can be deduced as the following formulas:
If (m/2+n/2+1) > k && am/2 > bn/2 , drop Section 2
If (m/2+n/2+1) > k && am/2 < bn/2 , drop Section 4
If (m/2+n/2+1) < k && am/2 > bn/2 , drop Section 3
If (m/2+n/2+1) < k && am/2 < bn/2 , drop Section 1

To be simple, it is to abandon the right section to the biggest median or the left section to the smallest median
[Code]
Note line 12~14. The terminal condition of recursion when n==0, m ==0, and k==1.
1: double findMedianSortedArrays(int A[], int m, int B[], int n) {
2: if((n+m)%2 ==0)
3: {
4: return (GetMedian(A,m,B,n, (m+n)/2) + GetMedian(A,m,B,n, (m+n)/2+1))/2.0;
5: }
6: else
7: return GetMedian(A,m,B,n, (m+n)/2+1);
8: }
9: int GetMedian(int a[], int n, int b[], int m, int k)
10: {
11: assert(a && b);
12: if (n <= 0) return b[k-1];
13: if (m <= 0) return a[k-1];
14: if (k <= 1) return min(a[0], b[0]);
15: if (b[m/2] >= a[n/2])
16: {
17: if ((n/2 + 1 + m/2) >= k)
18: return GetMedian(a, n, b, m/2, k);
19: else
20: return GetMedian(a + n/2 + 1, n - (n/2 + 1), b, m, k - (n/2 + 1));
21: }
22: else
23: {
24: if ((m/2 + 1 + n/2) >= k)
25: return GetMedian( a, n/2,b, m, k);
26: else
27: return GetMedian( a, n, b + m/2 + 1, m - (m/2 + 1),k - (m/2 + 1));
28: }
29: }
47. Merge k Sorted Lists
Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity.
» Solve this problem

[Thoughts]
Merge sort. Only need to pay attention of pointer operation.
[Code]
1: ListNode *mergeKLists(vector<ListNode *> &lists) {
2: if(lists.size() == 0) return NULL;
3: ListNode *p = lists[0];
4: for(int i =1; i< lists.size(); i++)
5: {
6: p = merge2Lists(p, lists[i]);
7: }
8: return p;
9: }
10: ListNode * merge2Lists(ListNode *head1, ListNode *head2)
11: {
12: ListNode *head = new ListNode(INT_MIN);
13: ListNode *p = head;
14: while(head1!=NULL && head2!=NULL)
15: {
16: if(head1->val < head2->val)
17: {
18: p->next = head1;
19: head1 = head1->next;
20: }
21: else
22: {
23: p->next = head2;
24: head2 = head2->next;
25: }
26: p = p->next;
27: }
28: if(head1 !=NULL)
29: {
30: p->next = head1;
31: }
32: if(head2 != NULL)
33: {
34: p->next = head2;
35: }
36: p = head;
37: head = head->next;
38: delete p;
39: return head;
40: }
48. Merge Sorted Array
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 to hold additional elements from B. The number of elements initialized in
A and B are m and n respectively.
» Solve this problem

[Thoughts]
Did you play a game to fill the blank with some characters in order. This problem actually uses the same idea.

But unfortunately, we don’t have extra array to fill. As problem mentioned, A has lots of blank space inside. So use
A as the extrac space. But need to fill the blank from back to front, or the content of array A will be polluted.
[Code]
1: void merge(int A[], int m, int B[], int n) {
2: int k = m+n-1;
3: int i = m-1, j =n-1;
4: for(; i>=0 && j>=0; k--)
5: {
6: if(A[i] >= B[j])
7: {
8: A[k] = A[i];
9: i--;
10: }
11: else
12: {
13: A[k] = B[j];
14: j--;
15: }
16: }
17: while(j >=0)
18: {
19: A[k] = B[j];
20: k--; j--;
21: }
22: }
49. Minimum Depth of Binary Tree
Given a binary tree, find its minimum depth.
The minimum depth is the number of nodes along the shortest path from the root node down to the nearest leaf node.
» Solve this problem

[Thoughts]
Recursion is the best friend of tree-related problems. Same here. If we define Min[K] as the minimal depth of node
K(no matter where this K is in the tree). We can derive the transition function as
Min[ K ] = min ( Min[K->left] , Min[K->right]) + 1
And, implement it as below.
[Code]
1: int minDepth(TreeNode *root) {
2: // Start typing your C/C++ solution below
3: // DO NOT write int main() function
4: if(root == NULL)
5: return 0;
6: int lmin = minDepth(root->left);
7: int rmin = minDepth(root->right);
8: if(lmin ==0 && rmin ==0)
9: return 1;
10: if(lmin ==0)
11: {
12: lmin = INT_MAX;
13: }
14: if(rmin ==0)
15: {
16: rmin = INT_MAX;
17: }
18: return min(lmin, rmin) +1;
19: }
50. Minimum Path Sum
Given a m x n grid filled with non-negative numbers, find a path from top left to bottom right which minimizes the
sum of all numbers along its path.
Note: You can only move either down or right at any point in time.
» Solve this problem

[Thoughts]
Two-dimension dynamic programming. Let’s use A[row][col] to represent the m x n grid. Define Min[i][j] as the
minimal sum of cell (i,j).
Since problem already requires that the path from top left to bottom right, so for cell (i,j), the path can only come
from either (i-1,j) or (i,j-1)

It’s easy to get the transition function:


Min[i][j] = min ( Min[i-1][j], Min[i][j-1] ) + A[i][j] if i>0 && j>0
or = A[0][j] if i==0
or = A[i][0] if j==0

[Code]
1: int minPathSum(vector<vector<int> > &grid) {
2: // Start typing your C/C++ solution below
3: // DO NOT write int main() function
4: if(grid.size() ==0) return 0;
5: int row = grid.size();
6: int col = grid[0].size();
7: int Min[row][col];
8: Min[0][0] =grid[0][0];
9: for(int i =1; i < row; i ++)
10: {
11: Min[i][0] =Min[i-1][0] + grid[i][0];
12: }
13: for(int i =1; i< col; i++)
14: {
15: Min[0][i] = Min[0][i-1] + grid[0][i];
16: }
17: for(int i =1; i< row; i++)
18: {
19: for(int j =1; j< col; j++)
20: {
21: Min[i][j] = min(Min[i-1][j], Min[i][j-1]) + grid[i][j];
22: }
23: }
24: return Min[row-1][col-1];
25: }

Previous code uses a two- dimension array to track and compute Min. But in real implementation, use a one-
dimension iterative array is enough. Below code is more beautiful.
1: int minPathSum(vector<vector<int> > &grid) {
2: int row = grid.size();
3: if(row == 0) return 0;
4: int col = grid[0].size();
5: if(col == 0) return 0;
6: vector<int> steps(col, INT_MAX);
7: steps[0] =0;
8: for(int i =0; i< row; i++)
9: {
10: steps[0] = steps[0] + grid[i][0];
11: for(int j=1; j<col; j++)
12: {
13: steps[j]=min(steps[j], steps[j-1]) + grid[i][j];
14: }
15: }
16: return steps[col-1];
17: }
51. Minimum Window Substring
Given a string S and a string T, find the minimum window in S which will contain all the characters in T in
complexity O(n).
For example,
S = "ADOBECODEBANC"
T = "ABC"
Minimum window is "BANC" .
Note:
If there is no such window in S that covers all characters in T, return the emtpy string "" .
If there are multiple such windows, you are guaranteed that there will always be only one unique minimum window
in S.
» Solve this problem

[Thoughts]
Use two pointers to maintain a window dynamically. The tail pointer keep moving forward. If the window contains
all the characters in T, try to shrink the window by moving head pointer forward. When the window can’t be
shrinked, track the window size if it is the minimal one.
[Code]
1: string minWindow(string S, string T) {
2: // Start typing your C/C++ solution below
3: // DO NOT write int main() function
4: if(S.size() == 0) return "";
5: if(S.size() < T.size()) return "";
6: int appearCount[256];
7: int expectCount[256];
8: memset(appearCount, 0, 256*sizeof(appearCount[0]));
9: memset(expectCount, 0, 256*sizeof(appearCount[0]));
10: for(int i =0; i < T.size(); i++)
11: {
12: expectCount[T[i]]++;
13: }
14: int minV = INT_MAX, min_start = 0;
15: int wid_start=0;
16: int appeared = 0;
17: for(int wid_end = 0; wid_end< S.size(); wid_end++)
18: {
19: if(expectCount[S[wid_end]] > 0)//his char is a part of T
20: {
21: appearCount[S[wid_end]]++;
22: if(appearCount[S[wid_end]] <= expectCount[S[wid_end]])
23: appeared ++;
24: }
25: if(appeared == T.size())
26: {
27: while(appearCount[S[wid_start]] > expectCount[S[wid_start]]
28: || expectCount[S[wid_start]] == 0)
29: {
30: appearCount[S[wid_start]]--;
31: wid_start ++;
32: }
33: if(minV > (wid_end - wid_start +1))
34: {
35: minV = wid_end - wid_start +1;
36: min_start = wid_start;
37: }
38: }
39: }
40: if(minV == INT_MAX) return "";
41: return S.substr(min_start, minV);
42: }
52. 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.
» Solve this problem

[Thoughts]
Big integer multiplication. Just implementation. Multiply the digit one by one. Pay more attention on the carry bit
and also Zero.
For example, Line 25~31, skipthe redundant zero. “9133” , “0” , the multiply result will be “000000”, but user
only need one zero --“0”.
[Code]
1: string multiply(string num1, string num2) {
2: // Start typing your C/C++ solution below
3: // DO NOT write int main() function
4: if(num1.size() ==0 || num2.size() ==0) return 0;
5: string res(num1.size()+num2.size()+1, '0');
6: std::reverse(num1.begin(), num1.end());
7: std::reverse(num2.begin(), num2.end());
8: for(int i =0; i < num1.size(); i++)
9: {
10: int dig1 = num1[i] -'0';
11: int carry = 0;
12: for(int j = 0; j< num2.size(); j++)
13: {
14: int dig2 = num2[j] - '0';
15: int exist = res[i+j] -'0';
16: res[i+j] = (dig1*dig2+carry+ exist) % 10 +'0';
17: carry = (dig1*dig2+carry+exist)/10;
18: }
19: if(carry >0)
20: {
21: res[i+num2.size()] = carry + '0';
22: }
23: }
24: std::reverse(res.begin(), res.end());
25: int start =0;
26: while(res[start] =='0' && start < res.size())
27: {
28: start++;
29: }
30: if(start == res.size()) return "0";
31: return res.substr(start, res.size()-start);
32: }
53. Next Permutation
Implement next permutation, which rearranges numbers into the lexicographically next greater permutation of
numbers.
If such arrangement is not possible, it must rearrange it as the lowest possible order (ie, sorted in ascending order).
The replacement must be in-place, do not allocate extra memory.
Here are some examples. Inputs are in the left-hand column and its corresponding outputs are in the right-hand
column.
1,2,3 → 1,3,2
3,2,1 → 1,2,3
1,1,5 → 1,5,1
» Solve this problem

[Thoughts]
More like a math problem. Below example demonstrates how to get the next permutation of 687432.

[Code]
1: void nextPermutation(vector<int> &num) {
2: assert(num.size() >0);
3: int vioIndex = num.size() -1;
4: while(vioIndex >0)
5: {
6: if(num[vioIndex-1] < num[vioIndex])
7: break;
8: vioIndex --;
9: }
10: if(vioIndex >0)
11: {
12: vioIndex--;
13: int rightIndex = num.size()-1;
14: while(rightIndex >=0 && num[rightIndex] <= num[vioIndex])
15: {
16: rightIndex --;
17: }
18: int swap = num[vioIndex];
10: num[vioIndex] = num[rightIndex];
20: num[rightIndex] = swap;
21: vioIndex++;
22: }
23: int end= num.size()-1;
24: while(end > vioIndex)
25: {
26: int swap = num[vioIndex];
27: num[vioIndex] = num[end];
28: num[end] = swap;
29: end--;
30: vioIndex++;
31: }
32: }
54. Palindrome Number
Determine whether an integer is a palindrome. Do this without extra space.
Some hints:
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.
» Solve this problem

[Thoughts]
Split the first digit and the last digit out , and compare them. If they are equal, continue to split the second one and
the last but one, etc. until no digit left or find non-equal digits.
[Code]
1: bool isPalindrome(int x) {
2: if(x<0) return false;
3: int div = 1;
4: while(x/div >=10)
5: div*=10;
6: while(x>0)
7: {
8: int l = x/div;
9: int r = x%10;
10: if(l!=r) return false;
11: x=x%div/10;
12: div/=100;
13: }
14: return true;
15: }
55. Partition List
Given a linked list and a value x, partition it such that all nodes less than x come before nodes greater than or equal
to x.
You should preserve the original relative order of the nodes in each of the two partitions.
For example,
Given 1->4->3->2->5->2 and x = 3,
return 1->2->2->4->3->5.
» Solve this problem

[Thoughts]
Scan from left to right. Find the first node K which is larger than X. And for any node which is less than X, insert it
on the left of K. And here, introduce a SafeGuard node(fake head) to avoid processing head node.
[Code]
1: ListNode *partition(ListNode *head, int x) {
2: // Start typing your C/C++ solution below
3: // DO NOT write int main() function
4: ListNode* p = new ListNode(x-1);
5: p->next = head;
6: head = p;
7: ListNode* pre;
8: while(p!=NULL && p->val < x)
9: {
10: pre = p;
11: p = p->next;
12: }
13: if(p!=NULL)
14: {
15: ListNode* cur = pre;//keep the insert position. It never changes
16: while(p!=NULL)
17: {
18: if(p->val <x)
19: {
20: ListNode* temp = cur->next;
21: pre->next = p->next;
22: cur->next = p;
23: cur = p;
24: p->next = temp;
25: p = pre;
26: }
27: pre=p;
28: p= p->next;
29: }
30: }
31: ListNode* temp = head;
32: head = head->next;
33: delete temp;
34: return head;
35: }
56. Pascal's Triangle II
Given an index k, return the kth row of the Pascal's triangle.
For example, given k = 3,
Return [1,3,3,1] .

[
[1],
[1,1],
[1,2,1],
[1,3,3,1],
[1,4,6,4,1]
]

Note:
Could you optimize your algorithm to use only O(k) extra space?
» Solve this problem

[Thoughts]
Dynamic programming.
Justify the sample by left as below:
[
[1],
[1,1],
[1,2,1],
[1,3,3,1],
[1,4,6,4,1]
]

Define T[i][j] as the element in the left-justified triangle. And we can get the transition function as,
T[i][j] = T[i-1][j] + T[i-1][j-1] if i>0 && j>0
Or
= 1 if i=0
Or
= T[i-1][j] if j=0

In the real implementation, we can use 1D array to calculate iteratively. For each level, compute from right to left.
Think why?
[Code]
1: vector<int> getRow(int rowIndex) {
2: // Start typing your C/C++ solution below
3: // DO NOT write int main() function
4: vector<int> result;
5: result.resize(rowIndex+2);
6: for(int i =0; i< rowIndex+2; i++)
7: result[i] = 0;
8: result[1]=1;
9: for(int i =0; i< rowIndex; i++)
10: {
11: for(int j =rowIndex+1; j>0; j--)//right-> left,avoid duplicate add
12: {
13: result[j] = result[j-1] + result[j];
14: }
15: }
16: result.erase(result.begin());
17: return result;
18: }
57. Path Sum
Given a binary tree and a sum, determine if the tree has a root-to-leaf path such that adding up all the values along
the path equals the given sum.
For example:
Given the below binary tree and sum = 22 ,
5
/\
4 8
/ /\
11 13 4
/ \ \
7 2 1

return true, as there exist a root-to-leaf path 5->4->11->2 which sum is 22.
» Solve this problem

[Thoughts]
Traversal of a binary tree. Add up the node values while traversing, when approach any leaf node, compare the
sum with expect value, if they equal, then return, or give up this path.
[Code]
1: bool hasPathSum(TreeNode *root, int sum) {
2: return hasPathSum(root, 0, sum);
3: }
4: bool hasPathSum(TreeNode *root, int sum, int target) {
5: if(root == NULL) return false;
6: sum += root->val;
7: if(root->left == NULL && root->right == NULL) //leaf
8: {
9: if(sum == target)
10: return true;
11: else
12: return false;
13: }
14: return hasPathSum(root->left, sum, target)
15: || hasPathSum(root->right, sum, target);
16: }
58. Path Sum II
Given a binary tree and a sum, find all root-to-leaf paths where each path's sum equals the given sum.
For example:
Given the below binary tree and sum = 22 ,
5
/\
4 8
/ /\
11 13 4
/ \ /\
7 2 5 1
return
[
[5,4,11,2],
[5,8,4,5]
]
» Solve this problem

[Thoughts]
Similar as previous one. But add extra logic to record all the solution paths as red highlight.
[Code]
1: vector<vector<int> > pathSum(TreeNode *root, int sum) {
2: vector<vector<int> > collect;
3: vector<int> solution;
4: if(root!=NULL)
5: GetPath(root, sum, 0, solution, collect);
6: return collect;
7: }
8: void GetPath(TreeNode* node, int sum, int cal, vector<int>& solution, vector<vector<int> >& collect)
9: {
10: solution.push_back(node->val);
11: cal += node->val;
12: if(cal == sum && node->left == NULL && node->right == NULL)
13: {
14: collect.push_back(solution);
15: }
16: else
17: {
18: if(node->left != NULL)
19: {
20: GetPath(node->left, sum, cal, solution, collect);
21: }
22: if(node->right != NULL)
23: {
24: GetPath(node->right, sum, cal, solution, collect);
25: }
26: }
27: solution.pop_back();
28: return;
29: }
59. Permutations
Given a collection of numbers, return all possible permutations.
For example,
[1,2,3] have the following permutations:
[1,2,3] , [1,3,2] , [2,1,3] , [2,3,1] , [3,1,2] , and [3,2,1] .
» Solve this problem

[Thoughts]
A classic recursion problem. And need a Visited array to track the usage of numbers.
[Code]
1: vector<vector<int> > permute(vector<int> &num) {
2: // Start typing your C/C++ solution below
3: // DO NOT write int main() function
4: vector<vector<int> > coll;
5: vector<int> solution;
6: if(num.size() ==0) return coll;
7: vector<int> visited(num.size(), 0);
8: GeneratePermute(num, 0, visited, solution, coll);
9: return coll;
10: }
11: void GeneratePermute(vector<int> & num, int step, vector<int>& visited, vector<int>& solution,
vector<vector<int> >& coll)
12: {
13: if(step == num.size())
14: {
15: coll.push_back(solution);
16: return;
17: }
18: for(int i =0; i< num.size(); i++)
19: {
20: if(visited[i] == 0)// if this number already used, skip it
21: {
22: visited[i] = 1;
23: solution.push_back(num[i]);
24: GeneratePermute(num, step+1, visited, solution, coll);
25: solution.pop_back();
26: visited[i] =0;
27: }
28: }
29: }
60. Permutations II
Given a collection of numbers that might contain duplicates, return all possible unique permutations.
For example,
[1,1,2] have the following unique permutations:
[1,1,2] , [1,2,1] , and [2,1,1] .
» Solve this problem

[Thoughts]
As previous problem, but need extro logic to de-duplicate. So sort the array first, and when DFS the solution, skip
unnecessary processing if the previous number is same as current one. Comparing with previous problem
‘Permutation’, Line 26~27 are the only changes.
[Code]
1: vector<vector<int> > permuteUnique(vector<int> &num) {
2: vector<vector<int> > coll;
3: vector<int> solution;
4: if(num.size() ==0) return coll;
5: vector<int> visited(num.size(), 0);
6: sort(num.begin(), num.end());
7: GeneratePermute(num, 0, visited, solution, coll);
8: return coll;
9: }
10: void GeneratePermute(vector<int> & num, int step, vector<int>& visited, vector<int>& solution,
vector<vector<int> >& coll)
11: {
12: if(step == num.size())
13: {
14: coll.push_back(solution);
15: return;
16: }
17: for(int i =0; i< num.size(); i++)
18: {
19: if(visited[i] == 0)
20: {
21: visited[i] = 1;
22: solution.push_back(num[i]);
23: GeneratePermute(num, step+1, visited, solution, coll);
24: solution.pop_back();
25: visited[i] =0;
26: while(i< num.size()-1 && num[i] == num[i+1])
27: i++;
28: }
29: }
30: }
61. Plus One
Given a number represented as an array of digits, plus one to the number.
» Solve this problem

[Thoughts]
Simulate the add operation one digit by one and take proper care of the carry.
[Code]
1: vector<int> plusOne(vector<int> &digits) {
2: // Start typing your C/C++ solution below
3: // DO NOT write int main() function
4: int cary=1, sum =0;
5: vector<int> result(digits.size(),0);
6: for(int i = digits.size()-1; i>=0; i--)
7: {
8: sum = cary+digits[i];
9: cary = sum/10;
10: result[i] = sum%10;
11: }
12: if(cary >0)
13: {
14: result.insert(result.begin(), cary);
15: }
16: return result;
17: }
62. Populating Next Right Pointers in Each Node
Given a binary tree
struct TreeLinkNode {
TreeLinkNode *left;
TreeLinkNode *right;
TreeLinkNode *next;
}

Populate each next pointer to point to its next right node. If there is no next right node, the next pointer should be set
to NULL .
Initially, all next pointers are set to NULL .
Note:

You may only use constant extra space.


You may assume that it is a perfect binary tree (ie, all leaves are at the same level, and every
parent has two children).

For example,
Given the following perfect binary tree,
1
/ \
2 3
/\ /\
4 5 6 7

After calling your function, the tree should look like:


1 -> NULL
/ \
2 -> 3 -> NULL
/\ /\
4->5->6->7 -> NULL

» Solve this problem

[Thoughts]
Notice that this problem gives a strict condition that this tree is a PERFECT binary tree. It simples the question a lot.
We can do it by recursion:
For each root node, for example node #2 in the sample

link its left sub-node to right sub-node (4->5)

link its right-sub node,


if root->next is not NULL, link to the left sub-node of root->next.(5->6)
If root->next is NULL, link to NULL.(7->NULL)

[Code]
1: void connect(TreeLinkNode *root) {
2: // Start typing your C/C++ solution below
3: // DO NOT write int main() function
4: if(root == NULL) return;
5: if(root->left != NULL)
6: root->left->next = root->right;
7: if(root->right !=NULL)
8: root->right->next = root->next? root->next->left:NULL;
9: connect(root->left);
10: connect(root->right);
11: }
63. Populating Next Right Pointers in Each Node II
Follow up for problem "Populating Next Right Pointers in Each Node".
What if the given tree could be any binary tree? Would your previous solution still work?
Note:

You may only use constant extra space.

For example,
Given the following binary tree,
1
/ \
2 3
/\ \
4 5 7

After calling your function, the tree should look like:


1 -> NULL
/ \
2 -> 3 -> NULL
/\ \
4-> 5 -> 7 -> NULL

» Solve this problem

[Thoughts]
Similar as previous one. But this time, the tree is not guaranteed to be a complete binary tree. For each node, how to
get the first valid node to be linked as next is the tricky part, e.g. node #6 in the sample is missed. So in order to link
to #7, need to traverse all the parents nodes(#2, #3, NULL) and find the first node which has non-empty sub-node.

[Code]
1: void connect(TreeLinkNode *root) {
2: // Start typing your C/C++ solution below
3: // DO NOT write int main() function
4: if(root== NULL) return;
5: TreeLinkNode* p = root->next;
6: while(p!=NULL)
7: {
8: if(p->left!=NULL)
9: {
10: p = p->left;
11: break;
12: }
13: if(p->right!=NULL)
14: {
15: p = p->right;
16: break;
17: }
18: p = p->next;
19: }
20: if(root->right!= NULL)
21: {
22: root->right->next = p; // link the right sub-node first
23: }
24: if(root->left !=NULL) // then, link the left sub-node
25: {
26: root->left->next = root->right? root->right:p;
27: }
28: connect(root->right);
29: connect(root->left);
30: }
But unfortunately, previous solution problem requires constant space. Could we do this with O(1) space? Yes, see
below:

1: void connect(TreeLinkNode *root) {


2: TreeLinkNode* cur = root, *next = NULL;
3: while(cur!=NULL)
4: {
5: TreeLinkNode *p = cur, *k= NULL;
6: while(p!=NULL)
7: {
8: TreeLinkNode* sub = getLinkedLeftNode(p);
9: if(sub != NULL)
10: {
11: if(next == NULL)
12: {
13: next = sub;
14: k = sub;
15: }
16: else
17: k->next = sub;
18: while(k->next !=NULL) // iterate to the tail
19: k = k->next;
20: }
21: p = p->next;
22: }
23: cur = next;
24: next = NULL;
25: }
26: }
27: TreeLinkNode* getLinkedLeftNode(TreeLinkNode * root)
28: {
29: if(root->left != NULL && root->right != NULL)
30: root->left->next = root->right;
31: if(root->left != NULL)
32: return root->left;
33: if(root->right != NULL)
34: return root->right;
35: return NULL;
36: }
64. Recover Binary Search Tree
Two elements of a binary search tree (BST) are swapped by mistake.
Recover the tree without changing its structure.
Note:
A solution using O(n) space is pretty straight forward. Could you devise a constant space solution?
confused what "{1,#,2,3}" means? > read more on how binary tree is serialized on OJ.
» Solve this problem

[Thoughts]
This is a really interesting problem. One straight forward way is to do the inorder traverse of this binary search tree
and reassign the value of each node. This solution is generic to N-swap mistakes.
Below is an example that shows how O(n) solution works.
1: void recoverTree(TreeNode *root) {
2: // Start typing your C/C++ solution below
3: // DO NOT write int main() function
4: vector<TreeNode*> list;
5: vector<int > vals;
6: InOrderTravel(root, list, vals);
7: sort(vals.begin(), vals.end());
8: for(int i =0; i< list.size(); i++)
9: {
10: list[i]->val = vals[i];
11: }
12: }
13: void InOrderTravel(TreeNode* node, vector<TreeNode*>& list, vector<int>& vals)
14: {
15: if(node == NULL) return;
16: InOrderTravel(node->left, list, vals);
17: list.push_back(node);
18: vals.push_back(node->val);
19: InOrderTravel(node->right, list, vals);
20: }
But for this question, it only has two elements swapped by mistake and it ask for a O(1) space complexity. How to?
If we traverse this tree in order, actually, we can easily detect the the misplaced nodes during traversing. But inorder
traversal always needs O(n) space because it needs a stack to track the path.
So here, the question becomes, could we travel the tree without any extral data struction like stack?
Fortunately, there is a solution Threaded Binary Tree. The general idea is, creating links to Inorder successor,
traverse the tree using these links, and finally revert the changes to restore original tree.
1. Initialize current as root
2. While current is not NULL
If current does not have left child
a) Print current’s data
b) Go to the right, i.e., current = current->right
Else
a) Make current as right child of the rightmost node in current's left subtree
b) Go to this left child, i.e., current = current->left
Following is the sample code of inorder traversal:
/* Function to traverse binary tree without recursion and without stack */
vector<int> inorderTraversal(TreeNode *root)
{
vector<int> result;
TreeNode *current,*pre;
if(root == NULL)
return result;
current = root;
while(current != NULL)
{
if(current->left == NULL)
{
result.push_back(current->val);
current = current->right;
}
else
{
/* Find the inorder predecessor of current */
pre = current->left;
while(pre->right != NULL && pre->right != current)
pre = pre->right;
/* Make current as right child of its inorder predecessor */
if(pre->right == NULL)
{
pre->right = current;
current = current->left;
}
/* Revert the changes made in if part to restore the original tree i.e., fix the right child of predecssor */
else
{
pre->right = NULL;
result.push_back(current->val);
current = current->right;
} /* End of if condition pre->right == NULL */
} /* End of if condition current->left == NULL*/
} /* End of while */
return result;
}
Based on threaded tree, we can use two pointers to travel the tree. Suppose, the pre pointer points the previous
access node. The cur pointer points the current access node. Then, we can
Find first misplaced node by
if ( current.val < prev.val )
Node first = prev;
Find second misplaced node by
if ( current.val < prev.val )
Node second = current;
After traversal, swap the values of first and second node. Only need two pointers, prev and current node. O(1) space.
With all these information, we are done here. Traverse the tree with O(1) space and add the logic of resetting the
misplaced nodes as a part of traversal logic.
[Code]
The change parts are highlight in red. Add an extra pointer to track the predecessor node. During traversing the tree,
detect the misplaced node by (parent->val > current->val). And swap the parent node of first violation and the
current node of second violation.

void recoverTree(TreeNode *root)


{
TreeNode *f1=NULL, *f2=NULL;
TreeNode *current,*pre, *parent=NULL;

if(root == NULL)
return;
bool found = false;
current = root;
while(current != NULL)
{
if(current->left == NULL)
{
if(parent && parent->val > current->val)
{
if(!found)
{
f1 = parent;
found = true;
}
f2 = current;
}
parent = current;
current = current->right;
}
else
{
/* Find the inorder predecessor of current */
pre = current->left;
while(pre->right != NULL && pre->right != current)
pre = pre->right;

/* Make current as right child of its inorder predecessor */


if(pre->right == NULL)
{
pre->right = current;
current = current->left;
}

/* Revert the changes made in if part to restore the original


tree i.e., fix the right child of predecssor */
else
{
pre->right = NULL;
if(parent->val > current->val)
{
if(!found)
{
f1 = parent;
found = true;
}
f2 = current;
}
parent = current;
current = current->right;
} /* End of if condition pre->right == NULL */
} /* End of if condition current->left == NULL*/
} /* End of while */

if(f1 && f2)


swap(f1->val, f2->val);
}
65. Pow(x, n)
Implement pow(x, n).
» Solve this problem

[Thoughts]
Recursive bisection partitioning.
If n is even, pow(x, n) = pow(x, n/2) * pow(x, n/2).
If n is odd, pow(x, n) = pow(x, n/2) * pow(x, n/2) * x.
Just pay attention of the case n<0.
[Code]
1: double power(double x, int n)
2: {
3: if (n == 0)
4: return 1;
5: double v = power(x, n / 2);
6: if (n % 2 == 0)
7: return v * v;
8: else
9: return v * v * x;
10: }
11: double pow(double x, int n) {
12: // Start typing your C/C++ solution below
13: // DO NOT write int main() function
14: if (n < 0)
15: return 1.0 / power(x, -n);
16: else
17: return power(x, n);
18: }
66. Remove Duplicates from Sorted Array
Given a sorted array, remove the duplicates in place such that each element appear only once and return the new
length.
Do not allocate extra space for another array, you must do this in place with constant memory.
For example,
Given input array A = [1,1,2] ,
Your function should return length = 2 , and A is now [1,2] .
» Solve this problem

[Thoughts]
This problem said SORTED array. This condition makes solution simpler. If the array is not sorted, we need either
sort it first or track the frequency of occurrence via a map. Fortunately, we don’t need to do too much work in this
problem.
A classical two-pointer problem. Use two pointers to scan the array together. Because it is sorted, the first pointer
can easily identify the duplicate by comparing the value with second pointer, and skip it. See code.
[Code]
1: int removeDuplicates(int A[], int n) {
2: if(n ==0) return 0;
3: int index = 0;
4: for(int i =0;i<n; i++)
5: {
6: if(A[index] == A[i]) // duplicate, skip
7: {
8: continue;
9: }
10: index++; // non-duplicate, copy it to second pointer
11: A[index] = A[i];
12: }
13: return index+1;
14: }
67. Remove Duplicates from Sorted Array II
Follow up for "Remove Duplicates":
What if duplicates are allowed at most twice?
For example,
Given sorted array A = [1,1,1,2,2,3] ,
Your function should return length = 5 , and A is now [1,1,2,2,3] .
» Solve this problem

[Thoughts]
Similar as previous problem. But need a variable to track the the frequency of occurrence during traversing. Again,
if this array is not sorted, it’s better to use a map.
[Code]
1: int removeDuplicates(int A[], int n) {
2: if(n == 0) return 0;
3: int occur = 1;
4: int index = 0;
5: for(int i =1; i< n; i++)
6: {
7: if(A[index] == A[i])
8: {
9: if(occur == 2)
10: {
11: continue;
12: }
13: occur++;
14: }
15: else
16: {
17: occur =1 ;
18: }
19: A[++index] = A[i];
20: }
21: return index+1;
22: }
68. Remove Duplicates from Sorted List
Given a sorted linked list, delete all duplicates such that each element appear only once.
For example,
Given 1->1->2 , return 1->2 .
Given 1->1->2->3->3 , return 1->2->3 .
» Solve this problem

[Thoughts]
Interesting transformation. Here, the problem is about linked list. Still use two-pointer, but this time, we need to deal
with pointer operation.
One more important thing is, DELETE the unused node to avoid memory leak.
[Code]
1: ListNode *deleteDuplicates(ListNode *head) {
2: // Start typing your C/C++ solution below
3: // DO NOT write int main() function
4: if(head == NULL) return NULL;
5: ListNode * pre = head;
6: ListNode *p = head->next;
7: while(p!=NULL)
8: {
9: if(pre->val == p->val)
10: {
11: ListNode* temp = p;
12: p = p->next;
13: pre->next =p;
14: delete temp; // need delete the unused node. Or memory leak
15: continue;
16: }
17: pre = pre->next;
18: p = p->next;
19: }
20: return head;
21: }
69. Remove Duplicates from Sorted List II
Given a sorted linked list, delete all nodes that have duplicate numbers, leaving only distinct numbers from the
original list.
For example,
Given 1->2->3->3->4->4->5 , return 1->2->5 .
Given 1->1->1->2->3 , return 2->3 .
» Solve this problem

[Thoughts]
Add more tricks than previous problem. In previous problem, we need only delete the duplicate number. But in
current one, we need to delete all the number which has duplicate. As above sample #2 {1->1->1->2->3}, we need
to delete the head too. In order to avoid handling head node, I use a Safeguard (a fake head).
[Code]
1: ListNode *deleteDuplicates(ListNode *head) {
2: if(head == NULL) return head;
3: ListNode *G = new ListNode(INT_MIN);
4: G->next = head;
5: ListNode *cur = G, *pre = head;
6: while(pre!=NULL)
7: {
8: bool isDup = false;
9: while(pre->next!=NULL && pre->val == pre->next->val)
10: {
11: isDup = true;
12: ListNode *temp = pre;
13: pre = pre->next;
14: delete temp;
15: }
16: if(isDup)
17: {
18: ListNode *temp = pre;
19: pre = pre->next;
20: delete temp;
21: continue;
22: }
23: cur->next = pre;
24: cur = cur->next;
25: pre= pre->next;
26: }
27: cur->next = pre;
28: ListNode *temp = G->next;
29: delete G;
30: return temp;
31: }
70. Remove Element
Given an array and a value, remove all instances of that value in place and return the new length.
The order of elements can be changed. It doesn't matter what you leave beyond the new length.
» Solve this problem

[Thoughts]
Use two pointers here. One pointer traverses the array and another pointer track the index of new string.
Suppose we are going to remove value N from array. If the first pointer points to a element which equals N too, skip
it. If not, copy it to new address(second pointer).
[Code]
1: int removeElement(int A[], int n, int elem) {
2: // Start typing your C/C++ solution below
3: // DO NOT write int main() function
4: int cur = 0;
5: for(int i =0; i< n; i++)
6: {
7: if(A[i] == elem)
8: continue;
9: A[cur]=A[i];
10: cur++;
11: }
12: return cur;
13: }
71. Remove Nth Node From End of List
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.

Note:
Given n will always be valid.
Try to do this in one pass.
» Solve this problem

[Thoughts]
A classical problem. Two pointers. One pointer moves n steps first, and then two pointers move together. When the
first pointer arrives tail, the second pointer points exactly the node need to be deleted. As every linked list problem,
head node always need more attention. E.g. 1->2->NULL, n =2; in this case, need delete the head node. Or, use a
safe guard node to bypass head node trick.
[Code]
1: ListNode *removeNthFromEnd(ListNode *head, int n) {
2: ListNode* pre, *cur;
3: pre = head;cur = head;
4: int step = 0;
5: while(step< n && cur!=NULL)
6: {
7: cur = cur->next;
8: step++;
9: }
10: if(step ==n && cur == NULL)
11: {
12: head = head->next;
13: delete pre;
14: return head;
15: }
16: while(cur->next!=NULL)
17: {
18: pre = pre->next;
19: cur = cur->next;
20: }
21: ListNode* temp = pre->next;
22: pre->next = temp->next;
23: delete temp;
24: return head;
25: }
72. Restore IP Addresses
Given a string containing only digits, restore it by returning all possible valid IP address combinations.
For example:
Given "25525511135" ,
return ["255.255.11.135", "255.255.111.35"] . (Order does not matter)
» Solve this problem

[Thoughts]
Partition the given string into 4 parts and validate each part is in a correct range [0,255] and stands for a valid
number, like “0.10.10.1” , not “0.10.010.1”.
No difficulty here, but need more attention on implementation.
[Code]
1: vector<string> restoreIpAddresses(string s) {
2: vector<string> col;
3: string ip;
4: partitionIP(s, 0, 0, ip, col);
5: return col;
6: }
7: void partitionIP(string s, int startIndex, int partNum,
8: string resultIp, vector<string>& col)
9: {
10: //max: 3 bits per partition
11: if(s.size() - startIndex > (4-partNum)*3) return;
12: //min: 1 bit per partition
13: if(s.size() - startIndex < (4-partNum)) return;
14: if(startIndex == s.size() && partNum ==4)
15: {
16: resultIp.resize(resultIp.size()-1);
17: col.push_back(resultIp);
18: return;
19: }
20: int num =0;
21: for(int i = startIndex; i< startIndex +3; i++)
22: {
23: num = num*10 + (s[i]-'0');
24: if(num<=255)
25: {
26: resultIp+=s[i];
27: partitionIP(s, i+1, partNum+1, resultIp+'.', col);
28: }
29: if(num ==0)//0.0.0.0 valid, but need to avoid 0.1.010.01
30: {
31: break;
32: }
33: }
34: }
73. Reverse Integer
Reverse digits of an integer.
Example1: x = 123, return 321
Example2: x = -123, return -321
click to show spoilers.
Have you thought about this?
Here are some good questions to ask before coding. Bonus points for you if you have already thought through this!
If the integer's last digit is 0, what should the output be? ie, cases such as 10, 100.
Did you notice that the reversed integer might overflow? Assume the input is a 32-bit integer, then the reverse of
1000000003 overflows. How should you handle such cases?
Throw an exception? Good, but what if throwing an exception is not an option? You would then have to re-design
the function (ie, add an extra parameter).
» Solve this problem

[Thoughts]
You might think about converting the integer to string and reverse the string. But there are some special cases as
‘3000’. Zero needs special care in this case.
Actually, we don’t need so complex solution. Just convert it as an integer.
[Code]
1: int reverse(int x) {
2: int newN =0, left =0;
3: while(x != 0)
4: {
5: left = x%10;
6: newN = newN*10 + left;
7: x = x/10;
8: }
9: return newN;
10: }

Previous code is beauty and brief. But it doesn’t cover the overflow case. Below code only reverse the positive
integer and detect the overflow if the integer becomes negative.

1: int reverse(int x) {
2: int lastDigit = 0;
3: int result = 0;
4: bool isNeg = x>0? false:true;
5: x = abs(x);
6: while(x>0)
7: {
8: lastDigit = x%10;
9: result = result*10 + lastDigit;
10: x = x/10;
11: }
12: if(result<0) return -1;
13: if(isNeg)
14: result *=-1;
15: return result;
16: }
74. Reverse Linked List II
Reverse a linked list from position m to n. Do it in-place and in one-pass.
For example:
Given 1->2->3->4->5->NULL , m = 2 and n = 4,
return 1->4->3->2->5->NULL .
Note:
Given m, n satisfy the following condition:
1 ≤ m ≤ n ≤ length of list.
» Solve this problem

[Thoughts]
Split the solution into 3 steps:
1. Find the previous node of position m(Here, add a SafeGuard node to avoid handling head node)
2. Reverse the next N nodes after position m ( two pointers:cur and post. cur always points to the head of reversed
sub-list )
3. Merge the original linked list before position m, the reversed linked list between position m and position n, and
also the left part linked list after position n.

This problem is a little tricky in implementation. Because it only ask for reverse a part of the original linked list, so
you need to keep in mind that the whole list will be splitted into 3 part and you need to relink them together in the
end.
[Code]
1: ListNode *reverseBetween(ListNode *head, int m, int n) {
2: int step = n-m;
3: ListNode* safeG = new ListNode(-1); //intro a safe guard to avoid handle head case
4: safeG->next = head;
5: head = safeG;
6: ListNode* pre = head;
7: while(m>1)
8: {
9: pre=pre->next;
10: m--;
11: }
12: ListNode* cur = pre->next, *post = cur->next;
13: if(step>=1)
14: {
15: while(step>0 && post!=NULL)// Reverse the list after m
16: {
17: ListNode* temp = post->next;
18: post->next = cur;
19: cur = post;
20: post = temp;
21: step--;
22: }
23: ListNode* temp = pre->next; // link the 3 lists together
24: pre->next = cur;
25: temp->next = post;
26: }
27: safeG = head; // remove safeG
28: head = head->next;
29: delete safeG;
30: return head;
31: }
75. Reverse Nodes in k-Group
Given a linked list, reverse the nodes of a linked list k at a time and return its modified list.
If the number of nodes is not a multiple of k then left-out nodes in the end should remain as it is.
You may not alter the values in the nodes, only nodes itself may be changed.
Only constant memory is allowed.
For example,
Given this linked list: 1->2->3->4->5
For k = 2, you should return: 2->1->4->3->5
For k = 3, you should return: 3->2->1->4->5
» Solve this problem

[Thoughts]
Similar as previous problem. Split the linked list into multiple K-groups. Apply the previous code for every K-
group. The only trap is in the last group. If the nodes in last group is less than K, we don’t need to reverse it. In the
implementation, just reverse the tail again if it is less than K.
[Code]
The reverse code could be a separated function. But here, just put them together for readability.
1: ListNode *reverseKGroup(ListNode *head, int k) {
2: ListNode* safeG = new ListNode(-1);
3: safeG->next = head;
4: if(head == NULL || k==1) return head;
5: ListNode* pre = safeG, *cur = head, *post = head->next;
6: while(cur!=NULL)
7: {
8: post = cur->next;
9: int i =0;
10: while(i<k-1 && post!=NULL)
11: {
12: ListNode *temp = post->next;
13: post->next = cur;
14: cur = post;
15: post = temp;
16: i++;
17: }
18: if(i!=k-1)
19: {
20: int k =0;
21: ListNode * temp = post;
22: post = cur;
23: cur = temp;
24: while(k<i)
25: {
26: temp = post->next;
27: post->next = cur;
28: cur = post;
29: post = temp;
30: k++;
31: }
32: break;
33: }
34: ListNode* temp = pre->next;
35: pre->next = cur;
36: temp->next = post;
37: pre = temp;
38: cur = pre->next;
39: }
40: head = safeG->next;
41: delete safeG;
42: return head;
43: }
76. Roman To Integer
Given a roman numeral, convert it to an integer.
Input is guaranteed to be within the range from 1 to 3999.
» Solve this problem

[Thoughts]
First, we need an static array or function to map the roman number to integer. Then, scan the roman string from left
to right,

if current roman number is larger than previous, it means these two numbers are combo
number. The correct value should be current number minus previous one, e.g. IV = 5-1
else, add current roman number into integer result and process next number. e.g. VI=5+1,
II = 1+1

[Code]
1: inline int c2n(char c) {
2: switch(c) {
3: case 'I': return 1;
4: case 'V': return 5;
5: case 'X': return 10;
6: case 'L': return 50;
7: case 'C': return 100;
8: case 'D': return 500;
9: case 'M': return 1000;
10: default: return 0;
11: }
12: }
13: int romanToInt(string s) {
14: // Start typing your C/C++ solution below
15: // DO NOT write int main() function
16: int result=0;
17: for(int i =0; i< s.size(); i++)
18: {
19: if(i>0&& c2n(s[i]) > c2n(s[i-1]))
20: {
21: result +=(c2n(s[i]) - 2*c2n(s[i-1]));
22: }
23: else
24: {
25: result += c2n(s[i]);
26: }
27: }
28: return result;
29: }
77. Rotate Image
You are given an n x n 2D matrix representing an image.
Rotate the image by 90 degrees (clockwise).
Follow up:
Could you do this in-place?
» Solve this problem

[Thoughts]
As below,first, rotate the image by diagonal. And then rotate it by the median line of y-axis.

[Code]
1: void rotate(vector<vector<int> > &matrix) {
2: // Start typing your C/C++ solution below
3: // DO NOT write int main() function
4: int len = matrix[0].size();
5: for(int i =0; i<len-1; i++)
6: {
7: for(int j=0;j<len-i;j++)
8: {
9: swap(matrix[i][j], matrix[len-1-j][len-1-i]);
10: }
11: }
12: for(int i =0; i<len/2; i++)
13: {
14: for(int j=0;j<len;j++)
15: {
16: swap(matrix[i][j], matrix[len-i-1][j]);
17: }
18: }
19: }
20: void swap(int& a1, int&a2)
21: {
22: int temp = a1;
23: a1=a2;
24: a2=temp;
25: }
78. Rotate List
Given a list, rotate the list to the right by k places, where k is non-negative.
For example:
Given 1->2->3->4->5->NULL and k = 2 ,
return 4->5->1->2->3->NULL .
» Solve this problem

[Thoughts]
Interesting problem.

1. scan from head to tail and get the length of linked list
2. Link tail to head and form a ring.
3. Continue to move forward for another (len – k%len) nodes
4. Break the ring, and done.

[Code]
1: ListNode *rotateRight(ListNode *head, int k) {
2: // Start typing your C/C++ solution below
3: // DO NOT write int main() function
4: if(head == NULL || k ==0) return head;
5: int len =1;
6: ListNode* p = head,*pre;
7: while(p->next!=NULL)
8: {
9: p = p->next;
10: len++;
11: }
12: k = len-k%len;
13: p->next = head;
14: int step =0;
15: while(step< k)
16: {
17: p = p->next;
18: step++;
19: }
20: head = p->next;
21: p->next = NULL;
22: return head;
23: }

[Note]
K might be larger than len. So here, need to use (K mod len).
79. 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" :
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" .
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" .
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.
» Solve this problem

[Thoughts]
Definitely, we can use recursion. Partition two string to 4 parts, and compare the four groups: (A.left, B.left) &&
(A.right, B.right), (A.left, B.right) && (A.right, B.left). But recursion usually is not efficient especially when the
data set is large. So, need some pruning to cut unnecessary computing.
There should be a O(n) solution. Still thinking.
[Code]
1: bool isScramble(string s1, string s2) {
2: // Start typing your C/C++ solution below
3: // DO NOT write int main() function
4: if(s1.size() != s2.size()) return false;
5: int A[26];
6: memset(A,0,26*sizeof(A[0]));
7: for(int i =0;i<s1.size(); i++)
8: {
9: A[s1[i]-'a']++;
10: }
11: for(int i =0;i<s2.size(); i++)
12: {
13: A[s2[i]-'a']--;
14: }
15: for(int i =0;i<26; i++)
16: {
17: if(A[i] !=0)
18: return false;
19: }
20: if(s1.size() ==1 && s2.size() ==1) return true;
21: for(int i =1; i< s1.size(); i++)
22: {
23: bool result= isScramble(s1.substr(0, i), s2.substr(0, i))
24: && isScramble(s1.substr(i, s1.size()-i), s2.substr(i, s1.size()-i));
25: result = result || (isScramble(s1.substr(0, i), s2.substr(s2.size() - i, i))
26: && isScramble(s1.substr(i, s1.size()-i), s2.substr(0, s1.size()-i)));
27: if(result) return true;
28: }
29: return false;
30: }
80. Search for a Range
Given a sorted array of integers, find the starting and ending position of a given target value.
Your algorithm's runtime complexity must be in the order of O(log n).
If the target is not found in the array, return [-1, -1] .
For example,
Given [5, 7, 7, 8, 8, 10] and target value 8,
return [3, 4] .
» Solve this problem

[Thoughts]
Do binary search twice. The first one is to find the left boundary, the second is to find the right boundary. So the
average complexity is O(lgn).
[Code]
1: vector<int> searchRange(int A[], int n, int target) {
2: vector<int> result;
3: result.push_back(-1);
4: result.push_back(-1);
5: // find the low bound of the range, O(lgn)
6: int start =0, end =n-1;
7: while(start < end)
8: {
9: int mid = (start + end)/2;
10: if(A[mid] < target)
11: {
12: start = mid + 1;
13: continue;
14: }
15: end = mid;
16: }
17: int low_bound = A[start] == target? start:-1;
18: if(low_bound == -1)
19: {
20: return result;
21: }
22: // find the high bound of the range, O(lgn)
23: start =low_bound, end =n;
24: while(start < end)
25: {
26: int mid = (start + end)/2;
27: if(A[mid] > target)
28: {
29: end = mid;
30: continue;
31: }
32: start = mid+1;
33: }
34: int high_bound = start-1;
35: result.clear();
36: result.push_back(low_bound);
37: result.push_back(high_bound);
38: return result;
39: }
81. Search in Rotated Sorted Array
Suppose a sorted array is rotated at some pivot unknown to you beforehand.
(i.e., 0 1 2 4 5 6 7 might become 4 5 6 7 0 1 2 ).
You are given a target value to search. If found in the array return its index, otherwise return -1.
You may assume no duplicate exists in the array.
» Solve this problem

[Thoughts]
Binary search. But need to pay more attention on the boundary of rotated part. Need two inequalities to judge:
1. A[m] ? A[left]
2. A[m] ? target
See the judging logic in code.
[Code]
1: int search(int A[], int n, int target) {
2: // Start typing your C/C++ solution below
3: // DO NOT write int main() function
4: int l = 0, r = n-1;
5: while(l<=r)
6: {
7: int m = (l+r)/2;
8: if(A[m] == target) return m;
9: if(A[m]>= A[l])
10: {
11: if(A[l]<=target && target<= A[m]) // target 5 in {4,5,6,2,3}
12: r=m-1;
13: else
14: l = m+1;
15: }
16: else
17: {
18: if(A[m] < target && target< A[l]) // target 2 in {5,0,1,2,3}
19: l = m+1;
20: else
21: r = m-1;
22: }
23: }
24: return -1;
25: }
82. Search in Rotated Sorted Array II
Follow up for "Search in Rotated Sorted Array":
What if duplicates are allowed?
Would this affect the run-time complexity? How and why?
Write a function to determine if a given target is in the array.
» Solve this problem

[Thoughts]
Yes, duplicates will impact the run-time complexity. In worst case, it will use O(n) to find the target, like
{1,1,1,1,5,1}. In previous solution, we use A[m]>=A[l] to detect whether [l,m] is an increasing sequence, but now
this assumption is not true any more, e.g. [1,3,1,1,1].

So in order to keep our assumption, we need to split previous inequality into two parts:
1. if A[m]>A[l], [l,m] is increasing sequence.
2. if A[m] ==A[l], no decision. So move forward one step(l++) and see.
[Code]
1: bool search(int A[], int n, int target) {
2: int start = 0;
3: int end = n-1;
4: while(start <= end)
5: {
6: int mid = (start+end)/2;
7: if(A[mid] == target) return true;
8: if(A[start] < A[mid])
9: {
10: if(target>=A[start] && target<A[mid])
11: end = mid-1;
12: else
13: start = mid+1;
14: }
15: else if(A[start] > A[mid])
16: {
17: if(target>A[mid] && target<=A[end])
18: start = mid+1;
19: else
20: end = mid-1;
21: }
22: else //skip duplicate one, A[start] == A[mid]
23: start++;
24: }
25: return false;
26: }
83. Search Insert Position
Given a sorted array and a target value, return the index if the target is found. If not, return the index where it would
be if it were inserted in order.
You may assume no duplicates in the array.
Here are few examples.
[1,3,5,6] , 5 → 2
[1,3,5,6] , 2 → 1
[1,3,5,6] , 7 → 4
[1,3,5,6] , 0 → 0
» Solve this problem

[Thoughts]
Similar as classic binary search, only one line difference(as Line 9) to determine the insert index.
[Code]
1: int searchInsert(int A[], int n, int target) {
2: // Start typing your C/C++ solution below
3: // DO NOT write int main() function
4: int l=0, r=n-1;
5: while(l<=r)
6: {
7: int mid = (l+r)/2;
8: if(A[mid] == target) return mid;
9: if(mid>l && A[mid]>target && A[mid-1]<target ) return mid;
10: if(A[mid] > target)
11: {
12: r= mid-1;
13: }
14: else
15: {
16: l=mid+1;
17: }
18: }
19: return l;
20: }
84. Set Matrix Zeroes
Given a m x n matrix, if an element is 0, set its entire row and column to 0. Do it in place.
Follow up:
Did you use extra space?
A straight forward solution using O(mn) space is probably a bad idea.
A simple improvement uses O(m + n) space, but still not the best solution.
Could you devise a constant space solution?
» Solve this problem

[Thoughts]
A quit boring problem. The tricky part is how to store the flag bits. One way is to create a O(m+n) array, but this
problem asks to use constant space. So the best way is to reuse the existing array. For example, to use the first row
and first column to store the flg bits like below:

1. Check whether the first row and first column need to be cleaned or not.
2. Scan the left matrix, if meets 0, set the flag bit in first row and first column
3. Rescan the matrix. Clean the matrix based on the flg bit in first row and first column
4. Clean first row and first column based on #1 result.

[Code]
1: void setZeroes(vector<vector<int> > &matrix) {
2: // Start typing your C/C++ solution below
3: // DO NOT write int main() function
4: assert(matrix.size()>0);
5: int row = matrix.size(), col = matrix[0].size();
6: bool zerorow=false, zerocol=false;
7: for(int i = 0; i< col; i++)
8: if(matrix[0][i] ==0)
9: zerorow = 1;
10: for(int i = 0; i< row; i++)
11: if(matrix[i][0] ==0)
12: zerocol=1;
13: for(int i =1; i < row; i++)
14: for(int j = 1; j<col; j++)
15: if(matrix[i][j] ==0)
16: {
17: matrix[0][j] =0;
18: matrix[i][0] =0;
19: }
20: for(int i =1; i < row; i++)
21: for(int j = 1; j<col; j++)
22: if(matrix[i][0] ==0 || matrix[0][j] ==0)
23: matrix[i][j] =0;
24: if(zerorow ==1)
25: for(int i =0; i< col; i++)
26: matrix[0][i] =0;
27: if(zerocol==1)
28: for(int i =0; i< row; i++)
29: matrix[i][0] =0;
30: }
85. Simplify Path
Given an absolute path for a file (Unix-style), simplify it.
For example,
path = "/home/" , => "/home"
path = "/a/./b/../../c/" , => "/c"
Corner Cases:

Did you consider the case where path = "/../" ?


In this case, you should return "/" .
Another corner case is the path might contain multiple slashes '/' together, such
as "/home//foo/" .
In this case, you should ignore redundant slashes and return "/home/foo" .
» Solve this problem

[Thoughts]
Take the advantage of the stack, if next string element

Equals “/” , skip and find the next element


Equals “.” , do nothing and find the next element
Equals “..” , pop the top element in stack, and find the next element
Equals other else, push the element into stack , and find the next element

And finally, reconstruct the path by stack. Using stack will need extra space, but it saves the complexity of tracking
the element index, like multiple “/../”
[Code]
1: string simplifyPath(string path) {
2: // Start typing your C/C++ solution below
3: // DO NOT write int main() function
4: vector<string> stack;
5: assert(path[0]=='/');
6: int i=0;
7: while(i< path.size())
8: {
9: while(path[i] =='/' && i< path.size()) i++; //skip the begining '////'
10: if(i == path.size())
11: break;
12: int start = i;
13: while(path[i]!='/' && i< path.size()) i++; //decide the end boundary
14: int end = i-1;
15: string element = path.substr(start, end-start+1);
16: if(element == "..")
17: {
18: if(stack.size() >0)
19: stack.pop_back();
20: }
21: else if(element!=".")
22: stack.push_back(element);
23: }
24: if(stack.size() ==0) return "/";
25: string simpPath;
26: for(int i =0; i<stack.size(); i++)
27: simpPath += "/" + stack[i];
28: return simpPath;
29: }
86. 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.
Follow up:
A rather straight forward solution is a two-pass algorithm using counting sort.
First, iterate the array counting number of 0's, 1's, and 2's, then overwrite array with total number of 0's, then 1's and
followed by 2's.
Could you come up with an one-pass algorithm using only constant space?
» Solve this problem

[Thoughts]
A very straight forward way is to use counting sort, but counting sort needs two round scan. The first round is to
count the number of red, white and blue. And the second round will generat the new array based on the statistic info
from the first round scan.
But this problem requires only one pass. So, use two-pointer to track two ‘index’ here. One for red, one for blue.
Narrow down the index from both sides to middle.
$redIndex=0
$blueIndex=N-1
San array[i] from 0 to N-1,

If meets 0, swap it with red index, and $redIndex ++


If meets 2, swap it with blue index, and $blueIndex - -
If meets 1, i++

One pass scan. Time complexity O(n), space complexity O(1).


[Code]
1: void sortColors(int A[], int n) {
2: // Start typing your C/C++ solution below
3: // DO NOT write int main() function
4: int redSt=0, bluSt=n-1;
5: int i=0;
6: while(i<bluSt+1)
7: {
8: if(A[i]==0)
9: {
10: std::swap(A[i],A[redSt]);
11: redSt++;
12: i++; //move scan index together with red index
13: continue;
14: }
15: if(A[i] ==2)
16: {
17: std::swap(A[i],A[bluSt]);
18: bluSt--; //only move blue index
19: continue;
20: }
21: i++;
22: }
23: }
[Note]
Line 12, move the scan index because we scan the array from left to right. But if we scan the array from right to left,
need to move the scan index in Line 19 instead of Line 12.
87. Spiral Matrix
Given a matrix of m x n elements (m rows, n columns), return all elements of the matrix in spiral order.
For example,
Given the following matrix:
[
[ 1, 2, 3 ],
[ 4, 5, 6 ],
[ 7, 8, 9 ]
]

You should return [1,2,3,6,9,8,7,4,5] .


» Solve this problem

[Thoughts]
An implementation, which need to be careful of handling 4 directions. See code part.
[Code]
1 vector<int> spiralOrder(vector<vector<int> > &matrix) {
2 vector<int> result;
3 int row = matrix.size();
4 if(row == 0) return result;
5 int col = matrix[0].size();
6 if(col == 0) return result;
7
8 //define the step for 4 directions
9 int x[4] = { 1, 0, -1, 0 };
10 int y[4] = { 0, 1, 0, -1 };
11
12 int visitedRows = 0;
13 int visitedCols = 0;
14
15 // define direction: 0 means up, 1 means down, 2 means left, 3 means up
16 int direction = 0;
17 int startx = 0, starty = 0;
18 int candidateNum = 0, moveStep = 0;
19 while (true)
20 {
21 if (x[direction] == 0) // visit y axis
22 candidateNum = row - visitedRows;
23 else // visit x axis
24 candidateNum = col - visitedCols;
25
26 if (candidateNum <= 0)
27 break;
28 result.push_back(matrix[starty][startx]);
29 moveStep++;
30 if (candidateNum == moveStep) // change direction
31 {
32 visitedRows += x[direction] == 0 ? 0 : 1;
33 visitedCols += y[direction] == 0 ? 0 : 1;
34 direction = (direction + 1) % 4;
35 moveStep = 0;
36 }
37 startx += x[direction];
38 starty += y[direction];
39 }
40 return result;
41 }
88. Sqrt(x)
Implement int sqrt(int x) .
Compute and return the square root of x.
» Solve this problem

[Thoughts]
Not an interesting problem, but a good example to show binary search. The one tricky here is how to determine the
end boundary of binary search. The multiply operation may cause integer overflow. So it’s hard to decide the end by
comparing the value with 0. A good way is to using a fixed end boundary, like sqrt(INT_MAX).

[Code]
1: int sqrt(int x) {
2: // Start typing your C/C++ solution below
3: // DO NOT write int main() function
4: int start =0, end;
5: end= x/2<std::sqrt(INT_MAX)? x/2+1:std::sqrt(INT_MAX);
6: while(start<= end)
7: {
8: int mid = (start+end)/2;
9: int sqr = mid*mid;
10: if(sqr ==x)
11: {
12: return mid;
13: }
14: if(sqr<x)
15: {
16: start = mid+1;
17: }
18: else
19: {
20: end = mid-1;
21: }
22: }
23: return (start+end)/2;
24: }
If take it serious, there is an efficient way(math)to resolve this problem. Newton iteration algorithm !
1: const float EPS = 0.000000001;
2: int sqrt(int x) {
3: // Start typing your C/C++ solution below
4: // DO NOT write int main() function
5: if(x==0) return x;
6: float dividend = x;
7: float val = x;//final
8: float last;//previous value
9: do
10: {
11: last = val;
12: val =(val + dividend/val) / 2;
13: }while(abs(val-last) > EPS);
14: int result = val;
15: if(result * result > x)
16: result--;
17: return result;
18: }
[Note]
For the Newton iteration solution, Line 15 & 16 will handle the iterating overflow. E.g., if x is 2147395599,the
result will be 46340, not 46339.
89. String to Integer (atoi)
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.
Requirements for atoi:
The function first discards as many whitespace characters as necessary until the first non-whitespace character is
found. Then, starting from this character, takes an optional initial plus or minus sign followed by as many numerical
digits as possible, and interprets them as a numerical value.
The string can contain additional characters after those that form the integral number, which are ignored and have no
effect on the behavior of this function.
If the first sequence of non-whitespace characters in str is not a valid integral number, or if no such sequence exists
because either str is empty or it contains only whitespace characters, no conversion is performed.
If no valid conversion could be performed, a zero value is returned. If the correct value is out of the range of
representable values, INT_MAX (2147483647) or INT_MIN (-2147483648) is returned.
» Solve this problem

[Thoughts]
No algrithom here, but really test your Carefulness. Need good implementation and careful thoughts. Pay attention
to several special cases, like:

1. irregular format.
"-3924x8fc" , " + 413",
2. invalid input
" ++c", " ++1"
3. overflow
"2147483648"

[Code]
1: int atoi(const char *str) {
2: int num=0;
3: int sign =1;
4: int len = strlen(str);
5: int i =0;
6: while(str[i] == ' ' && i< len) i++;
7: if(str[i] == '+') i++;
8: if(str[i] == '-') {sign = -1; i++;}
9: for(;i<len; i++)
10: {
11: if(str[i] == ' ') break;
12: if(str[i]<'0' || str[i] > '9') break;
13: if(INT_MAX/10 < num || INT_MAX/10 == num && INT_MAX%10 < (str[i] -'0'))
14: {
15: return sign == -1 ? INT_MIN : INT_MAX;
16: break;
17: }
18: num = num*10 + str[i] -'0';
19: }
20: return num*sign;
21: }
90. Subsets
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:
[
[3],
[1],
[2],
[1,2,3],
[1,3],
[2,3],
[1,2],
[]
]

» Solve this problem

[Thoughts]
A classic combination. We can solve it by recursion. The logic is :
Func GenerateSet
For each number N in S
Push N into subset and print
If N is not the last number in S
Execute GenerateSet on next num recursively.
[Code]
1: vector<vector<int> > subsets(vector<int> &S) {
2: // Start typing your C/C++ solution below
3: // DO NOT write int main() function
4: vector<vector<int> > result;
5: vector<int> output;
6: if(S.size() ==0) return result;
7: result.push_back(output); // the empty set
8: sort(S.begin(), S.end());
9: generateSub(S, 0, result, output);
10: }
11: void generateSub(
12: vector<int> &s,
13: int step,
14: vector<vector<int> > &result,
15: vector<int>& output)
16: {
17: for(int i = step;i<s.size(); i++ )
18: {
19: output.push_back(s[i]);
20: result.push_back(output);
21: if(i< s.size()-1)
22: generateSub(s, i+1, result, output);
23: output.pop_back();
24: }
25: }
91. 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:
[
[2],
[1],
[1,2,2],
[2,2],
[1,2],
[]
]

» Solve this problem

[Thoughts]
Like previous one. The difference is about how to remove the duplicate. Line 24, 25 is the magic code to filter the
duplicate number. If the next number is same as current(duplicate), filter it.
[Code]
1: vector<vector<int> > subsetsWithDup(vector<int> &S) {
2: // Start typing your C/C++ solution below
3: // DO NOT write int main() function
4: vector<vector<int> > result;
5: vector<int> output;
6: if(S.size() ==0) return result;
7: result.push_back(output);
8: sort(S.begin(), S.end());
9: generateSub(S, 0, result, output);
10: }
11: void generateSub(
12: vector<int> &s,
13: int step,
14: vector<vector<int> > &result,
15: vector<int>& output)
16: {
17: for(int i = step;i<s.size(); i++ )
18: {
19: output.push_back(s[i]);
20: result.push_back(output);
21: if(i< s.size()-1)
22: generateSub(s, i+1, result, output);
23: output.pop_back();
24: while(i<s.size()-1 && s[i] == s[i+1])
25: i++;
26: }
27: }
92. Substring with Concatenation of All Words
You are given a string, S, and a list of words, L, that are all of the same length. Find all starting indices of
substring(s) in S that is a concatenation of each word in L exactly once and without any intervening characters.
For example, given:
S: "barfoothefoobarman"
L: ["foo", "bar"]
You should return the indices: [0,9].
(order does not matter).
» Solve this problem

[Thoughts]
No pretty solution. Use two maps to track the appearance of the word in L. Scan S from left to right.
[Code]
1: vector<int> findSubstring(string S, vector<string> &L) {
2: // Start typing your C/C++ solution below
3: // DO NOT write int main() function
4: map<string, int> expectCount;
5: map<string, int> realCount;
6: for(int i =0; i< L.size(); i++)
7: {
8: expectCount[L.at(i)]++;
9: }
10: vector<int> result;
11: int row = L.size();
12: if(row ==0) return result;
13: int len = L[0].size();
14: for(int i =0; i< (int)S.size() - row*len+1; i++)
15: {
16: realCount.clear();
17: int j =0;
18: for(; j< row; j++)
19: {
20: string sub = S.substr(i+j*len, len);
21: if(expectCount.find(sub) != expectCount.end())
22: {
23: realCount[sub]++;
24: }
25: else
26: break;
27: if(realCount[sub] > expectCount[sub])
28: {
29: break;
30: }
31: }
32: if(j == row)
33: result.push_back(i);
34: }
35: return result;
36: }
[Note]
A tricky in Line 14 as highlight in red. The type of S.size() is unsigned int, if not convert to int, the result will be
promoted to unsigned int. For example, (unsigned int) 1 - (int)2, the final result is not -1, but 4294967295.
93. Swap Nodes in Pairs
Given a linked list, swap every two adjacent nodes and return its head.
For example,
Given 1->2->3->4, you should return the list as 2->1->4->3.
Your algorithm should use only constant space. You may not modify the values in the list, only nodes itself can be changed.
» Solve this problem

[Thoughts]
Two-pointers switch. Need to think about some special condition, like empty list, only 1 item in a list, only two
items in a list. And also think about the head node will also be changed during switching.
Adding a safeguard can make the logic much simpler.
[Code]
1: ListNode *swapPairs(ListNode *head) {
2: if(head == NULL) return NULL;
3: if(head->next == NULL) return head;
4: ListNode* safeG = new ListNode(-1);
5: safeG->next= head; // head will be changed in next switch
6: ListNode *pre = head->next;
7: ListNode *cur = head;
8: ListNode *post = safeG;
9: while(pre!=NULL)
10: {
11: ListNode* temp = pre->next;
12: pre->next = cur;
13: cur->next = temp;
14: post->next = pre;
15: post= cur;
16: if(post->next == NULL) break;
17: cur = post->next;
18: pre = cur->next;
19: }
20: head = safeG->next;
21: delete safeG;
22: return head;
23: }
Recursion(more concise)
1: ListNode *swapPairs(ListNode *head) {
2: if (head == NULL || head->next == NULL) {
3: return head;
4: }
5: ListNode* nextPair = head->next->next;
6: ListNode* newHead = head->next;
7: head->next->next = head;
8: head->next = swapPairs(nextPair);
9: return newHead;
10: }
94. Symmetric Tree
Given a binary tree, check whether it is a mirror of itself (ie, symmetric around its center).
For example, this binary tree is symmetric:
1
/\
2 2
/\/\
3 44 3

But the following is not:


1
/\
2 2
\ \
3 3

Note:
Bonus points if you could solve it both recursively and iteratively.
confused what "{1,#,2,3}" means? > read more on how binary tree is serialized on OJ.
» Solve this problem

[Thoughts]
Two ways to solve this problem:

1. Iteration. Travel the tree by level and check the symmetric in each level.
2. Recursion. For each tree node, it is symmetric if
a. Left node equals right node, or they are both null
b. The left sub-tree of left node is symmetric with the right sub-tree of right node
c. The right sub-tree of left node is symmetric with the left sub-tree of right node

[Code]
Iteration:
1: bool isSymmetric(TreeNode *root) {
2: if(root == NULL) return true;
3: vector<TreeNode*> visitQueue;
4: visitQueue.push_back(root);
5: int curLevel=1;
6: while(curLevel >0)
7: {
8: int i=0;
9: while(i<curLevel)
10: {
11: TreeNode* p = visitQueue[i];
12: i++;
13: if(p==NULL) continue;
14: visitQueue.push_back(p->left);
15: visitQueue.push_back(p->right);
16: }
17: int start = 0, end = curLevel-1;
18: while(start< end)
19: {
20: TreeNode *pl = visitQueue[start];
21: TreeNode *pr = visitQueue[end];
22: int l = pl== NULL? -1:pl->val;
23: int r = pr== NULL? -1: pr->val;
24: if(l!=r)
25: return false;
26: start++;
27: end--;
28: }
29: visitQueue.erase(visitQueue.begin(), visitQueue.begin() + curLevel);
30: curLevel = visitQueue.size();
31: }
32: return true;
33: }
Recursion:
1: bool isSymmetric(TreeNode *root) {
2: // Start typing your C/C++ solution below
3: // DO NOT write int main() function
4: if(root == NULL) return true;
5: return isSym(root->left, root->right);
6: }
7: bool isSym(TreeNode *left, TreeNode *right)
8: {
9: if(left == NULL)
10: return right ==NULL;
11: if(right == NULL)
12: return left == NULL;
13: if(left->val != right->val)
14: return false;
15: if(!isSym(left->left, right->right))
16: return false;
17: if(!isSym(left->right, right->left))
18: return false;
19: return true;
20: }
95. Text Justification
Given an array of words and a length L, format the text such that each line has exactly L characters and is fully (left
and right) justified.
You should pack your words in a greedy approach; that is, pack as many words as you can in each line. Pad extra
spaces' ' when necessary so that each line has exactly L characters.
Extra spaces between words should be distributed as evenly as possible. If the number of spaces on a line do not
divide evenly between words, the empty slots on the left will be assigned more spaces than the slots on the right.
For the last line of text, it should be left justified and no extra space is inserted between words.
For example,
words: ["This", "is", "an", "example", "of", "text", "justification."]
L: 16.
Return the formatted lines as:
[
"This is an",
"example of text",
"justification. "
]

Note: Each word is guaranteed not to exceed L in length.


Corner Cases:

A line other than the last line might contain only one word. What should you do in this case?
In this case, that line should be left-justified.
» Solve this problem

[Thoughts]
A trivial implementation problem. Writing the code only spends less than 20 minutes, but it will cost one hour to
debug and make it work.
[Code]
1: vector<string> fullJustify(vector<string> &words, int L) {
2: vector<string> result;
3: if(0 == words.size()) return result;
4: int i =0;
5: while(i< words.size())
6: {
7: int start = i;
8: int sum = 0;
9: while(i<words.size() && sum + words[i].size()<=L)
10: {
11: sum+=words[i].size() +1;
12: i++;
13: }
14: int end = i-1;
15: int intervalCount = end - start;
16: int avgSp = 0, leftSp = 0;
17: if(intervalCount >0)
18: {
19: avgSp = (L-sum + intervalCount+1)/intervalCount;
20: leftSp = (L-sum + intervalCount+1)%intervalCount;
21: }
22: string line;
23: for(int j = start; j<end; j++)
24: {
25: line+=words[j];
26: if(i == words.size()) // the last line
27: line.append(1, ' ');
28: else
29: {
30: line.append(avgSp, ' '); //average space
31: if(leftSp>0) // the extra space
32: {
33: line.append(1, ' ');
34: leftSp--;
35: }
36: }
37: }
38: line+=words[end];
39: if(line.size()<L)
40: line.append(L-line.size(), ' ');
41: result.push_back(line);
42: }
43: return result;
44: }
96. 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 .

The above elevation map is represented by array [0,1,0,2,1,0,1,3,2,1,2,1]. In this case, 6 units of rain water (blue section) are being trapped.Thanks
Marcos for contributing this image!
» Solve this problem

[Thoughts]
Look at each bar, its capacity of holding water is depending on the height difference between the max left and the
max right. So, if we define H[i] as the max units water this bar can hold, easy to get following equation:

H[i] = min( Max( Array[j] ) , Max( Array[k]) ) – Array[i] where j<i and k>i

For example, Bar 4 and Bar 5 has the same max left and max right. The red brackets show that how the water size is
calculated.
Algrithom is simple here, for each bar

1. Scan from let to right, and get the MaxLeft for each bar
2. Scan from right to left, and get the MaxRight for each bar
3. Scan from left to right again, apply the calculation equation for each bar, and sum the water size

[Code]
In the implementation, #2 and #3 can be processed in one round scan.
1: int trap(int A[], int n) {
2: // Start typing your C/C++ solution below
3: // DO NOT write int main() function
4: if(n<2) return 0;
5: int *maxL = new int[n], *maxR=new int[n];
6: int max = A[0];
7: maxL[0] =0;
8: for(int i =1; i<n-1; i++)
9: {
10: maxL[i] =max;
11: if(max < A[i])
12: max = A[i];
13: }
14: max=A[n-1];
15: maxR[n-1]=0;
16: int ctrap,ttrap=0;
17: for(int i = n-2; i>0; i--)
18: {
19: maxR[i] = max;
20: ctrap = min(maxL[i], maxR[i]) -A[i];
21: if(ctrap>0)
22: ttrap+=ctrap;
23: if(max<A[i])
24: max = A[i];
25: }
26: delete maxL, maxR;
27: return ttrap;
28: }
Note:
This problem can be transformed to a little challenge. If not ask for the whole volume, but ask for the max volumn.
How do you plan to resolve this?
97. Triangle
Given a triangle, find the minimum path sum from top to bottom. Each step you may move to adjacent numbers on
the row below.
For example, given the following triangle
[
[2],
[3,4],
[6,5,7],
[4,1,8,3]
]

The minimum path sum from top to bottom is 11 (i.e., 2 + 3 + 5 + 1 = 11).


Note:
Bonus point if you are able to do this using only O(n) extra space, where n is the total number of rows in the
triangle.
» Solve this problem

[Thoughts]
One dimension dynamic programming. Actually, this problem is easy to calculate from bottom to up. Otherwise,
you need to pay more attention to the handle the index boundary and the initia value.

Define MinV[i][j] as the minimal path sum at (i,j). And the equation will like following:
MinV[i][j] = array[i][j] if i== row-1
Or
= min( MinV[i+1][j], MinV[i+1][j+1] ) + array[i][j] if i!= row-1

[Code]
1: int minimumTotal(vector<vector<int> > &triangle) {
2: int row = triangle.size();
3: if(row ==0) return 0;
4: vector<int> minV(triangle[row-1].size());
5: for(int i =row-1; i>=0; i--)
6: {
7: int col = triangle[i].size();
8: for(int j =0; j<col; j++)
9: {
10: if(i == row-1)
11: {
12: minV[j] = triangle[i][j];
13: continue;
14: }
15: minV[j] = min(minV[j], minV[j+1]) + triangle[i][j];
16: }
17: }
18: return minV[0];
19: }
98. Unique Paths
A robot is located at the top-left corner of a m x n grid (marked 'Start' in the diagram below).
The robot can only move either down or right at any point in time. The robot is trying to reach the bottom-right
corner of the grid (marked 'Finish' in the diagram below).
How many possible unique paths are there?

Above is a 3 x 7 grid. How many possible unique paths are there?


Note: m and n will be at most 100.
» Solve this problem

[Thoughts]
One dimension dynamic programming.
Definition:
Step[i][j] means the unique paths from (0,0) to (i,j)
And easy to get get Step[i][j] in somewhat more general terms:
Step[i][j] = 1 i=0 && j=0
or
= Step[i-1][j] + Step[i][j-1] i!=0 || j!=0

[Code]
In implementation, we don’t really define two-dimensional array. Use an iterative array.
1: int uniquePaths(int m, int n) {
2: vector<int> maxV(n,0);
3: maxV[0]=1;
4: for(int i =0; i< m; i++)
5: {
6: for(int j =1; j<n; j++)
7: {
8: maxV[j] = maxV[j-1] + maxV[j];
9: }
10: }
11: return maxV[n-1];
12: }
99. Unique Paths II
Follow up for "Unique Paths":
Now consider if some obstacles are added to the grids. How many unique paths would there be?
An obstacle and empty space is marked as 1 and 0 respectively in the grid.
For example,
There is one obstacle in the middle of a 3x3 grid as illustrated below.
[
[0,0,0],
[0,1,0],
[0,0,0]
]

The total number of unique paths is 2 .


Note: m and n will be at most 100.
» Solve this problem

[Thoughts]
Similar as problem ‘Unique Path’.
Only one different in the equation(highlight):
Step[i][j] = 1 i=0 && j=0
Or
= Step[i-1][j] + Step[i][j-1] if Array[i][j] ==0
Or
=0 if Array[i][j] =1
[Code]
1: int uniquePathsWithObstacles(vector<vector<int> > &obstacleGrid) {
2: int m = obstacleGrid.size();
3: if(m ==0) return 0;
4: int n = obstacleGrid[0].size();
5: if(obstacleGrid[0][0] ==1) return 0;
6: vector<int> maxV(n,0);
7: maxV[0] =1;
8: for(int i =0; i<m; i++)
9: {
10: for(int j =0; j<n; j++)
11: {
12: if(obstacleGrid[i][j] ==1)
13: maxV[j]=0;
14: else if(j >0)
15: maxV[j] = maxV[j-1]+maxV[j];
16: }
17: }
18: return maxV[n-1];
19: }
100. Valid Parentheses
Given a string containing just the characters '(' , ')' , '{' , '}' , '[' and ']' , determine if the input string is valid.
The brackets must close in the correct order, "()" and "()[]{}" are all valid but "(]" and "([)]" are not.
» Solve this problem

[Thoughts]
A classic parentheses match via stack. Given one stack, push the left bracket, and pop it when meet a right bracket.
Check whether the stack is empty at the end.
[Code]
1: bool isValid(string s) {
2: // Start typing your C/C++ solution below
3: // DO NOT write int main() function
4: vector<char> sta;
5: if(s.size() ==0) return false;
6: sta.push_back(s[0]);
7: for(int i =1; i< s.size(); i++)
8: {
9: if(s[i] == '(' || s[i] == '[' || s[i] == '{')
10: {
11: sta.push_back(s[i]);
12: continue;
13: }
14: char current = sta.back();
15: if(s[i] == ')' && current != '(')
16: return false;
17: if(s[i] == ']' && current != '[')
18: return false;
19: if(s[i] == '}' && current != '{')
20: return false;
21: sta.pop_back();
22: }
23: if(sta.size() !=0) return false;
24: return true;
25: }
101. Valid Sudoku
Determine if a Sudoku is valid, according to: Sudoku Puzzles - The Rules.
The Sudoku board could be partially filled, where empty cells are filled with the character '.' .

A partially filled sudoku which is valid.


» Solve this problem

[Thoughts]
Just an implementation.
1. Check each row
2. Check each column
3. Check the sub-squares(9 cells)

[Code]
1: bool isValidSudoku(vector<vector<char> > &board) {
2: // Start typing your C/C++ solution below
3: // DO NOT write int main() function
4: if(board.size() == 0) return false;
5: int row[9], col[9];
6: for(int i =0; i<9; i++)
7: {
8: memset(row, 0, 9*sizeof(int));
9: memset(col, 0, 9*sizeof(int));
10: for(int j =0; j<9; j++)
11: {
12: if(board[i][j] != '.')
13: {
14: if(row[board[i][j]-49] ==1)
15: return false;
16: row[board[i][j]-49]++;
17: }
18: if(board[j][i] != '.')
19: {
20: if(col[board[j][i]-49] ==1)
21: return false;
22: col[board[j][i]-49]++;
23: }
24: }
25: }
26: for(int i =0; i< 9; i+=3)
27: {
28: for(int j =0; j<9; j+=3)
29: {
30: memset(row, 0, 9*sizeof(int));
31: for(int m=0; m<3; m++)
32: {
33: for(int n =0; n<3; n++)
34: {
35: if(board[m+i][n+j] == '.')
36: continue;
37: if(row[board[m+i][n+j]-49] ==1)
38: return false;
39: row[board[m+i][n+j]-49]++;
40: }
41: }
42: }
43: }
44: return true;
45: }
[Note]
If extend this problem to “Generate a valid Sudoku”, how you plan to solve it?
102. Validate Binary Search Tree
Given a binary tree, determine if it is a valid binary search tree (BST).
Assume a BST is defined as follows:

The left subtree of a node contains only nodes with keys less than the node's key.
The right subtree of a node contains only nodes with keys greater than the node's key.
Both the left and right subtrees must also be binary search trees.

confused what "{1,#,2,3}" means? > read more on how binary tree is serialized on OJ.
» Solve this problem

[Thoughts]
Recursion. For every tree node, check whether the left sub-tree is less than root, and the right sub-tree is larger than
root.
Another solution is, travel this tree in-order and check whether the travel path is increasing!
[Code]
1: bool isValidBST(TreeNode *root) {
2: return IsValidBST(root, INT_MIN, INT_MAX);
3: }
4: bool IsValidBST(TreeNode* node, int MIN, int MAX)
5: {
6: if(node == NULL)
7: return true;
8: if(node->val > MIN
9: && node->val < MAX
10: && IsValidBST(node->left,MIN,node->val)
11: && IsValidBST(node->right,node->val,MAX))
12: return true;
13: else
14: return false;
15: }
103. Wildcard Matching
Implement wildcard pattern matching with support for '?' and '*' .
'?' Matches any single character.
'*' Matches any sequence of characters (including the empty sequence).

The matching should cover the entire input string (not partial).

The function prototype should be:


bool isMatch(const char *s, const char *p)

Some examples:
isMatch("aa","a") → false
isMatch("aa","aa") → true
isMatch("aaa","aa") → false
isMatch("aa", "*") → true
isMatch("aa", "a*") → true
isMatch("ab", "?*") → true
isMatch("aab", "c*a*b") → false

» Solve this problem

[Thoughts]
String match, the tricky part is how to match *. If p meets a *, store the index of * and also s. Then, s continues to
match the left p, if match fails, revert s and p to previous stored index. And continue the search with the next
char(s++).
[Code]
1: bool isMatch(const char *s, const char *p) {
2: // Start typing your C/C++ solution below
3: // DO NOT write int main() function
4: bool star = false;
5: const char *str, *ptr;
6: for(str = s, ptr =p; *str!='\0'; str++, ptr++)
7: {
8: switch(*ptr)
9: {
10: case '?':
11: break;
12: case '*':
13: star =true;
14: s=str, p =ptr;
15: while(*p=='*')
16: p++;
17: if(*p == '\0') // if nil after '*', return true
18: return true;
19: str = s-1;
20: ptr = p-1;
21: break;
22: default:
23: {
24: if(*str != *ptr)
25: {
26: // if no '*' in front, match failed
27: if(!star)
28: return false;
29: s++;
30: str = s-1;
31: ptr = p-1;
32: }
33: }
34: }
35: }
36: while(*ptr== '*')
37: ptr++;
38: return (*ptr == '\0');
39: }
104. Word Search
Given a 2D board and a word, find if the word exists in the grid.
The word can be constructed from letters of sequentially adjacent cell, where "adjacent" cells are those horizontally
or vertically neighboring. The same letter cell may not be used more than once.
For example,
Given board =
[
["ABCE"],
["SFCS"],
["ADEE"]
]

word = "ABCCED" , -> returns true ,


word = "SEE" , -> returns true ,
word = "ABCB" , -> returns false .
» Solve this problem

[Thoughts]
Similar as “Unique Paths” problem. The difference here is, previous robat can only go down or right, but here the
search can also go up and left, four directions. In case of repeat visiting the same path(especially in a cycle),
introduce a new array ‘visited’ track the path.
[Code]
1: bool exist(vector<vector<char> > &board, string word) {
2: // Start typing your C/C++ solution below
3: // DO NOT write int main() function
4: if(word.size() ==0) return false;
5: if(board.size() ==0 || board[0].size() == 0) return false;
6: int row = board.size();
7: int col = board[0].size();
8: int * visited = new int[row*col];
9: memset(visited, 0, row*col*sizeof(int));
10: for(int i =0; i< board.size(); i++)
11: {
12: for(int j =0; j< board[0].size(); j++)
13: {
14: if(board[i][j] == word[0])
15: {
16: visited[i*col+j] = 1;
17: if(search(board, word, visited, -1, 1, i, j))
18: return true;
19: visited[i*col+j] =0;
20: }
21: }
22: }
23: delete visited;
24: return false;
25: }
26: bool search(vector<vector<char> > &board,
27: string& word,
28: int* visited,
29: int op, //0 up, 1 down, 2 left, 3 right
30: int matchLen,
31: int i,
32: int j)
33: {
34: if(matchLen == word.size()) return true;
35: int row = board.size();
36: int col = board[0].size();
37: if(i+1<row && op!=0)
38: {
39: if(visited[(i+1)*col+j] ==0 &&
40: board[i+1][j] == word[matchLen])
41: {
42: visited[(i+1)*col+j] =1;
43: if(search(board, word, visited, 1, matchLen+1, i+1, j))
44: return true;
45: visited[(i+1)*col+j] =0;
46: }
47: }
48: if(i-1>=0 && op!=1)
49: {
50: if(visited[(i-1)*col+j] ==0 && board[i-1][j] == word[matchLen])
51: {
52: visited[(i-1)*col+j] =1;
53: if(search(board, word, visited, 0, matchLen+1, i-1, j))
54: return true;
55: visited[(i-1)*col+j] =0;
56: }
57: }
58: if(j+1<col && op!=2)
59: {
60: if(visited[i*col+j+1] ==0 && board[i][j+1] == word[matchLen])
61: {
62: visited[i*col+j+1] =1;
63: if(search(board, word, visited, 3, matchLen+1, i, j+1))
64: return true;
65: visited[i*col+j+1] =0;
66: }
67: }
68: if(j-1>=0 && op!=3)
69: {
70: if(visited[i*col+j-1] ==0 && board[i][j-1] == word[matchLen])
71: {
72: visited[i*col+j-1] =1;
73: if(search(board, word, visited, 2, matchLen+1, i, j-1))
74: return true;
75: visited[i*col+j-1] =0;
76: }
77: }
78: return false;
79: }
105. ZigZag Conversion
The string "PAYPALISHIRING" is written in a zigzag pattern on a given number of rows like this: (you may want
to display this pattern in a fixed font for better legibility)
P A H N
APLSIIG
Y I R

And then read line by line: "PAHNAPLSIIGYIR"


Write the code that will take a string and make this conversion given a number of rows:
string convert(string text, int nRows);

convert("PAYPALISHIRING", 3) should return "PAHNAPLSIIGYIR" .


» Solve this problem

[Thoughts]
Really a boring problem. It is actually a math problem. See example,
n=4
P I N
A L S I G
Y A H R
P I

N=5
P H
A S I
Y I R
P L I G
A N

if look at above examples, it’s easy to see, for every layer, the index of the main element(red) is (j+1 )*n +i, but for
the inserted element(green) between two main elements is (j+1)*n –i
[Code]
1: string convert(string s, int nRows) {
2: // Start typing your C/C++ solution below
3: // DO NOT write int main() function
4: if(nRows <= 1) return s;
5: string result;
6: if(s.size() ==0) return result;
7: for(int i =0; i< nRows; i++)
8: {
9: for(int j =0, index =i; index < s.size();
10: j++, index = (2*nRows-2)*j +i)
11: {
12: result.append(1, s[index]); //red element
13: if(i ==0 || i == nRows-1) //green element
14: {
15: continue;
16: }
17: if(index+(nRows- i-1)*2 < s.size())
18: {
19: result.append(1, s[index+(nRows- i-1)*2]);
20: }
21: }
22: }
23: return result;
24: }

You might also like