Leetcode CPP
Leetcode CPP
Leetcode CPP
([email protected])
https://github.com/soulmachine/leetcode
2016-1-28
Creative Commons
3.0 Unported
http://creativecommons.org/licenses/by-nc-sa/3.0/
(cc by-nc-sa)
ACM
LeetCode Online Judge(http://leetcode.com/onlinejudge)
C++ 11
OJ
.h
Shorter is better
.cpp
STL
malloc()/new
nullptr
C++
GitHub
GitHub
https://github.com/soulmachine/leetcode
http://q.weibo.com/1312378
http://book.douban.com/subject/2024655/
Algorithms
Java
2.1
. . . . . . . . . . . . . . .
2.1.1
Remove
Duplicates
Remove
Search
in
Search
in
35
2.1.22 Candy . . . . . . . . . .
36
37
38
. . . . . . . . . . . . .
40
2.2.1
40
2.2.2
41
2.2.3
Partition List . . . . . .
42
2.2.4
Remove
Longest
Duplicates
2.2.5
2.1.6
Rotated
Sorted Array II . . . . .
2.1.5
33
2.2
Rotated
Sorted Array . . . . . .
2.1.4
Duplicates
Consecutive
Sequence . . . . . . . .
2.1.7
Two Sum . . . . . . . .
10
2.1.8
3Sum . . . . . . . . . . 12
2.1.9
3Sum Closest . . . . . .
13
Remove
43
Duplicates
44
2.2.6
Rotate List . . . . . . .
46
2.2.7
Remove
Nth
Node
47
2.2.8
47
2.2.9
2.1.10 4Sum . . . . . . . . . . 14
2.1.11 Remove Element . . . . 18
2.1.12 Next Permutation . . . . 19
2.1.13 Permutation Sequence . 21
Pointer . . . . . . . . .
50
51
52
53
55
23
24
27
28
3.1
Valid Palindrome . . . . . . . .
57
3.2
Implement strStr() . . . . . . . .
58
3.3
60
31
ii
57
iii
3.4
Add Binary . . . . . . . . . . .
61
3.5
3.6
66
3.7
Wildcard Matching . . . . . . .
67
3.8
3.9
Valid Number . . . . . . . . . . 70
5.1.5
5.1.6
Binary
Tree
Zigzag
94
96
98
99
72
5.1.8
Same Tree . . . . . . .
73
5.1.9
3.13 Anagrams . . . . . . . . . . . .
75
77
79
. . . . . . . . . . . . . . . .
5.2
. . . . . . . . . 106
5.2.1
79
4.1.1
Valid Parentheses . . . . 79
4.1.2
theses . . . . . . . . . . 80
4.1.3
4.1.4
82
5.3
4.2
Largest Rectangle in
Histogram . . . . . . . .
. . . . . . . . . . . 108
5.3.1
84
5.3.2
86
5.1
5.1.2
5.3.4
Tree . . . . . . . . . . . 111
86
5.3.5
5.1.4
5.1.3
5.3.3
90
. . . . . . . . . 86
5.1.1
. . . . . . . . . . . . . . . 85
5.4
. . . . . . . . . 114
5.4.1
92
iv
5.4.2
8.3.2
next_permu-
tation() . . . . . . . . . 142
8.3.3
5.4.3
5.4.4
5.4.5
8.4.1
8.4.2
5.4.6
8.4
next_permutation() . . . 144
next_permutation() . . . . . . . . . 144
8.4.3
8.5
Permutations II . . . . . . . . . 144
5.4.7
. . . . . . . . . . 143
123
8.6
. . . . . . . . . . 144
Combinations . . . . . . . . . . 146
8.5.1
. . . . . . . . . . 146
8.5.2
. . . . . . . . . . 147
6.1
Number . . . . . . . . . . . . . 147
6.2
8.6.1
. . . . . . . . . . 148
6.3
8.6.2
. . . . . . . . . . 149
6.4
6.5
6.6
6.7
131
7.1
7.2
7.3
150
9.1
9.2
9.3
9.4
. . . . . . . . . . . . . . . 164
9.4.1
. . . . . . . . 164
9.4.2
. . . . . . 164
9.4.3
. . . . . . . . 165
10
8
8.1
8.2
8.3
135
Subsets . . . . . . . . . . . . . 135
173
8.1.1
. . . . . . . . . . 135
10.2.1
8.1.2
. . . . . . . . . . 137
10.2.2
. . . . . . . . 176
Subsets II . . . . . . . . . . . . 138
10.2.3
. . . . . . . . . . 177
8.2.1
. . . . . . . . . . 138
10.2.4
. . . . . . . . 178
8.2.2
. . . . . . . . . . 141
. . . . . . . . . . 176
Permutations . . . . . . . . . . 142
10.3.1
. . . . . . . . 179
8.3.1
10.3.2
. . . . . . . . . . 180
next_permutation() . . . 142
v
10.4 N-Queens . . . . . . . . . . . . 181
III . . . . . . . . . . . . . . . . 214
10.12
. . . . . . . . . . . . . . 195
10.12.1
. . . . . . . 195
10.12.2
. . . . . . 195
10.12.3
. . . . . . . 197
10.12.4
. 197
10.12.5
. . 197
11
199
14
232
235
201
12
13
209
vi
a==b
fabs(a-b)
1e-9
x % 2 != 0
x % 2 == 1
char
char
unsigned int
unsigned char
STL
vector
C++
Effective STL
string
vector
new
delete
delete
new
int** ary = new int*[row_num];
for(int i = 0; i < row_num; ++i)
ary[i] = new int[col_num];
vector
vector<vector<int> > ary(row_num, vector<int>(col_num, 0));
reserve
BUG
2.1
2.1.1 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].
1
// LeetCode, Remove Duplicates from Sorted Array
//
O(n)
O(1)
class Solution {
public:
int removeDuplicates(vector<int>& nums) {
if (nums.empty()) return 0;
int index = 0;
for (int i = 1; i < nums.size(); i++) {
if (nums[index] != nums[i])
nums[++index] = nums[i];
}
return index + 1;
}
};
2.1
2
// LeetCode, Remove Duplicates from Sorted Array
//
STL
O(n)
O(1)
class Solution {
public:
int removeDuplicates(vector<int>& nums) {
return distance(nums.begin(), unique(nums.begin(), nums.end()));
}
};
2.1.2
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]
hashmap
1
// LeetCode, Remove Duplicates from Sorted Array II
//
O(n)
O(1)
// @author hex108 (https://github.com/hex108)
class Solution {
public:
int removeDuplicates(vector<int>& nums) {
if (nums.size() <= 2) return nums.size();
int index = 2;
for (int i = 2; i < nums.size(); i++){
if (nums[i] != nums[index - 2])
nums[index++] = nums[i];
}
return index;
}
};
2
occur < 2
< 3
occur
2.1.1
2.1
2.1.4
{
/ 2;
< nums[mid])
nums[last-1])
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.
A[m]>=A[l],
[l,m]
[1,3,1,1,1]
A[m]>=A[l]
A[m]>A[l]
A[m]==A[l]
[l,m]
l++
2.1
2.1.3
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)).
O(m + n)
merge
k
pA
m
merge sort
B
pB++
O(1)
pB
pA++
A
m++
m++
O(k)
m+n
O(m + n)
k
k
A
A
k/2
k/2
B[k/2-1]
A[k/2-1]
k/2
k
A[k/2-1] == B[k/2-1]
A[k/2-1] > B[k/2-1]
A[k/2-1] < B[k/2-1]
A[k/2-1] < B[k/2-1]
A
B
A[k/2-1]
AB
top k
k
A[k/2-1] > B[k/2-1]
k/2
k/2
A[k/2-1] == B[k/2-1]
A[0]
AB
A[k/2-1]
A[k/2-1]
A
B
B[k-1]
A[k-1]
k=1
min(A[0], B[0])
A[k/2-1] == B[k/2-1]
A[k/2-1]
B[k/2-1]
B[k/2-1]
Given an unsorted array of integers, find the length of the longest consecutive elements sequence.
For example, Given [100, 4, 200, 1, 3, 2], The longest consecutive elements sequence is [1,
2, 3, 4]. Return its length: 4.
Your algorithm should run in O(n) complexity.
2.1
O(n log n)
O(n)
O(n)
unordered_map<int, bool> used
2
,
.
map<int, int> map
,
.
union,find
.
,
unordered_-
http://discuss.leetcode.com/questions/1070/
10
longest-consecutive-sequence
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.
11
2.1
You may assume that each input would have exactly one solution.
Input: numbers={2, 7, 11, 15}, target=9
Output: index1=1, index2=2
O(n2 )
1
2
O(n).
hash
O(n log n)
O(n)
O(n log n)
3Sum,
2.1.8
3Sum Closest,
4Sum,
2.1.10
2.1.9
12
2.1.8 3Sum
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)
O(n2 )
k-sum
O(max{n log n, n
k1
k2
})
// LeetCode, 3Sum
//
O(n^2)
class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums) {
vector<vector<int>> result;
if (nums.size() < 3) return result;
sort(nums.begin(), nums.end());
const int target = 0;
auto last = nums.end();
for (auto i = nums.begin(); i < last-2; ++i) {
auto j = i+1;
if (i > nums.begin() && *i == *(i-1)) continue;
auto k = last-1;
while (j < k) {
if (*i + *j + *k < target) {
++j;
while(*j == *(j - 1) && j < k) ++j;
} else if (*i + *j + *k > target) {
--k;
while(*k == *(k + 1) && j < k) --k;
} else {
result.push_back({ *i, *j, *k });
++j;
O(1)
13
2.1
--k;
while(*j == *(j - 1) && *k == *(k + 1) && j < k) ++j;
}
}
}
return result;
}
};
Two sum,
2.1.7
3Sum Closest,
4Sum,
2.1.9
2.1.10
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).
O(n2 )
14
Two sum,
2.1.7
3Sum,
2.1.8
4Sum,
2.1.10
2.1.10 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)
O(n3 )
hashmap
O(n3 )
3Sum
15
2.1
// LeetCode, 4Sum
//
O(n^3)
O(1)
class Solution {
public:
vector<vector<int>> fourSum(vector<int>& nums, int target) {
vector<vector<int>> result;
if (nums.size() < 4) return result;
sort(nums.begin(), nums.end());
auto last = nums.end();
for (auto a = nums.begin(); a < prev(last, 3); ++a) {
for (auto b = next(a); b < prev(last, 2); ++b) {
auto c = next(b);
auto d = prev(last);
while (c < d) {
if (*a + *b + *c + *d < target) {
++c;
} else if (*a + *b + *c + *d > target) {
--d;
} else {
result.push_back({ *a, *b, *c, *d });
++c;
--d;
}
}
}
}
sort(result.begin(), result.end());
result.erase(unique(result.begin(), result.end()), result.end());
return result;
}
};
map
// LeetCode, 4Sum
//
hashmap
//
O(n^2)
O(n^4)
O(n^2)
class Solution {
public:
vector<vector<int> > fourSum(vector<int> &nums, int target) {
vector<vector<int>> result;
if (nums.size() < 4) return result;
sort(nums.begin(), nums.end());
unordered_map<int, vector<pair<int, int> > > cache;
for (size_t a = 0; a < nums.size(); ++a) {
for (size_t b = a + 1; b < nums.size(); ++b) {
cache[nums[a] + nums[b]].push_back(pair<int, int>(a, b));
}
}
16
multimap
// LeetCode, 4Sum
//
hashmap
//
O(n^2)
O(n^2)
// @author
(http://weibo.com/luangong)
class Solution {
public:
vector<vector<int>> fourSum(vector<int>& nums, int target) {
vector<vector<int>> result;
if (nums.size() < 4) return result;
sort(nums.begin(), nums.end());
unordered_multimap<int, pair<int, int>> cache;
for (int i = 0; i + 1 < nums.size(); ++i)
for (int j = i + 1; j < nums.size(); ++j)
cache.insert(make_pair(nums[i] + nums[j], make_pair(i, j)));
for (auto i = cache.begin(); i != cache.end(); ++i) {
int x = target - i->first;
auto range = cache.equal_range(x);
for (auto j = range.first; j != range.second; ++j) {
auto a = i->second.first;
auto b = i->second.second;
auto c = j->second.first;
auto d = j->second.second;
if (a != c && a != d && b != c && b != d) {
vector<int> vec = { nums[a], nums[b], nums[c], nums[d] };
sort(vec.begin(), vec.end());
result.push_back(vec);
}
17
2.1
}
}
sort(result.begin(), result.end());
result.erase(unique(result.begin(), result.end()), result.end());
return result;
}
};
4
// LeetCode, 4Sum
//
O(n^3logn)
O(1)
//
1
class Solution {
public:
vector<vector<int>> fourSum(vector<int>& nums, int target) {
vector<vector<int>> result;
if (nums.size() < 4) return result;
sort(nums.begin(), nums.end());
auto last = nums.end();
for (auto a = nums.begin(); a < prev(last, 3);
a = upper_bound(a, prev(last, 3), *a)) {
for (auto b = next(a); b < prev(last, 2);
b = upper_bound(b, prev(last, 2), *b)) {
auto c = next(b);
auto d = prev(last);
while (c < d) {
if (*a + *b + *c + *d < target) {
c = upper_bound(c, d, *c);
} else if (*a + *b + *c + *d > target) {
d = prev(lower_bound(c, d, *d));
} else {
result.push_back({ *a, *b, *c, *d });
c = upper_bound(c, d, *c);
d = prev(lower_bound(c, d, *d));
}
}
}
}
return result;
}
};
Two sum,
3Sum,
2.1.7
2.1.8
3Sum Closest,
2.1.9
18
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 doesnt matter what you leave beyond the new length.
1
// LeetCode, Remove Element
//
O(n)
O(1)
class Solution {
public:
int removeElement(vector<int>& nums, int target) {
int index = 0;
for (int i = 0; i < nums.size(); ++i) {
if (nums[i] != target) {
nums[index++] = nums[i];
}
}
return index;
}
};
2
// LeetCode, Remove Element
//
remove()
O(n)
O(1)
class Solution {
public:
int removeElement(vector<int>& nums, int target) {
return distance(nums.begin(), remove(nums.begin(), nums.end(), target));
}
};
19
2.1
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
2-1
http://sherlei.blogspot.com/2012/12/leetcode-next-permutation.html
2-1
20
Permutation Sequence,
Permutations,
Permutations II,
Combinations,
8.3
8.4
8.5
2.1.13
21
2.1
By listing and labeling all of the permutations in order, We get the following sequence (ie, for n = 3):
"123"
"132"
"213"
"231"
"312"
"321"
Given n and k, return the kth permutation sequence.
Note: Given n will be between 1 and 9 inclusive.
k1
next_permutation()
k
n
a1
k
a2 , a3 , ..., an ,
a1 , a2 , a3 , ..., an
n1
a1 = k/(n 1)!
a2 , a3 , ..., an
k2
k%(n 1)!
a2
k2 /(n 2)!
kn1
kn2 %2!
an1
kn1 /1!
an
next_permutation()
// LeetCode, Permutation Sequence
//
next_permutation() TLE
class Solution {
public:
string getPermutation(int n, int k) {
string s(n, '0');
for (int i = 0; i < n; ++i)
n1
a1
(n 1)!
22
s[i] += i+1;
for (int i = 0; i < k-1; ++i)
next_permutation(s.begin(), s.end());
return s;
}
template<typename BidiIt>
bool next_permutation(BidiIt first, BidiIt last) {
//
Next Permutation
}
};
23
2.1
};
Next Permutation,
Permutations,
2.1.12
8.3
Permutations II,
Combinations,
8.4
8.5
Determine
if
Sudoku
is
valid,
according
to:
Sudoku
Puzzles
The
http://sudoku.com.au/TheRules.aspx .
The Sudoku board could be partially filled, where empty cells are filled with the character '.'.
Rules
24
Sudoku Solver,
10.10
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.
25
2.1
2-3
1.
2.
3.
1
// LeetCode, Trapping Rain Water
//
1
O(n)
O(n)
class Solution {
public:
int trap(const vector<int>& A) {
const int n = A.size();
int *max_left = new int[n]();
int *max_right = new int[n]();
for (int i = 1; i < n; i++) {
max_left[i] = max(max_left[i - 1], A[i - 1]);
max_right[n - 1 - i] = max(max_right[n - i], A[n - i]);
}
int sum = 0;
for (int i = 0; i < n; i++) {
26
2
// LeetCode, Trapping Rain Water
//
2
O(n)
O(1)
class Solution {
public:
int trap(const vector<int>& A) {
const int n = A.size();
int max = 0; //
for (int i = 0; i < n; i++)
if (A[i] > A[max]) max = i;
int water = 0;
for (int i = 0, peak = 0; i < max; i++)
if (A[i] > peak) peak = A[i];
else water += peak - A[i];
for (int i = n - 1, top = 0; i > max; i--)
if (A[i] > top) top = A[i];
else water += top - A[i];
return water;
}
};
27
2.1
int height = 0;
while (!s.empty()) { //
int bar = s.top().first;
int pos = s.top().second;
// bar, height, A[i]
water += (min(bar, A[i]) - height) * (i - pos - 1);
height = bar;
if (A[i] < bar) //
break;
else
s.pop(); //
}
s.push(make_pair(A[i], i));
}
return water;
}
};
12.6
4.1.3
28
1
// LeetCode, Rotate Image
//
1
O(n^2)
O(1)
class Solution {
public:
void rotate(vector<vector<int>>& matrix) {
const int n = matrix.size();
for (int i = 0; i < n; ++i) //
for (int j = 0; j < n - i; ++j)
swap(matrix[i][j], matrix[n - 1 - j][n - 1 - i]);
for (int i = 0; i < n / 2; ++i) //
for (int j = 0; j < n; ++j)
swap(matrix[i][j], matrix[n - 1 - i][j]);
}
};
2
// LeetCode, Rotate Image
//
2
O(n^2)
O(1)
class Solution {
public:
void rotate(vector<vector<int>>& matrix) {
const int n = matrix.size();
for (int i = 0; i < n / 2; ++i) //
for (int j = 0; j < n; ++j)
swap(matrix[i][j], matrix[n - 1 - i][j]);
for (int i = 0; i < n; ++i) //
for (int j = i + 1; j < n; ++j)
swap(matrix[i][j], matrix[j][i]);
}
};
29
2.1
1
// LeetCode, Plus One
//
O(n)
O(1)
class Solution {
public:
vector<int> plusOne(vector<int> &digits) {
add(digits, 1);
return digits;
}
private:
// 0 <= digit <= 9
void add(vector<int> &digits, int digit) {
int c = digit; // carry,
for (auto it = digits.rbegin(); it != digits.rend(); ++it) {
*it += c;
c = *it / 10;
*it %= 10;
}
if (c > 0) digits.insert(digits.begin(), 1);
}
};
2
// LeetCode, Plus One
//
O(n)
O(1)
class Solution {
public:
vector<int> plusOne(vector<int> &digits) {
add(digits, 1);
return digits;
}
private:
// 0 <= digit <= 9
void add(vector<int> &digits, int digit) {
int c = digit; // carry,
for_each(digits.rbegin(), digits.rend(), [&c](int &d){
d += c;
c = d / 10;
d %= 10;
});
if (c > 0) digits.insert(digits.begin(), 1);
30
}
};
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?
f (n)
n1
n1
f (n) = f (n 1) + f (n 2)
1
1
an =
5
[(
)n (
)n ]
1+ 5
1 5
2
2
31
2.1
Decode Ways,
13.10
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
01
11
10
0
1
3
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.
http://en.wikipedia.org/wiki/Gray_code
(Gray Code)
g0 = b0 , gi = bi bi1
1001
1
0
4
0
3
1
3
2
0
1101
b0 = g0 , bi = gi bi1
2
1
32
1000
1
3
4
n (n/2)
0 2n 1
n1
2-5
2-5
1
1
n
1
1111
n
33
2.1
Reflect-and-prefix method
// LeetCode, Gray Code
// reflect-and-prefix method
//
O(2^n)
O(1)
class Solution {
public:
vector<int> grayCode(int n) {
vector<int> result;
result.reserve(1<<n);
result.push_back(0);
for (int i = 0; i < n; i++) {
const int highest_bit = 1 << i;
for (int j = result.size() - 1; j >= 0; j--) //
result.push_back(highest_bit | result[j]);
}
return result;
}
};
Given a m 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?
O(m + n)
bool
1
// LeetCode, Set Matrix Zeroes
//
O(m*n)
O(m+n)
class Solution {
public:
void setZeroes(vector<vector<int> > &matrix) {
const size_t m = matrix.size();
const size_t n = matrix[0].size();
34
0
0
2
// LeetCode, Set Matrix Zeroes
//
O(m*n)
O(1)
class Solution {
public:
void setZeroes(vector<vector<int> > &matrix) {
const size_t m = matrix.size();
const size_t n = matrix[0].size();
bool row_has_zero = false; //
bool col_has_zero = false; //
for (size_t i = 0; i < n; i++)
if (matrix[0][i] == 0) {
row_has_zero = true;
break;
}
for (size_t i = 0; i < m; i++)
if (matrix[i][0] == 0) {
col_has_zero = true;
break;
}
for (size_t i = 1; i < m; i++)
for (size_t j = 1; j < n; j++)
if (matrix[i][j] == 0) {
matrix[0][j] = 0;
0
0
35
2.1
matrix[i][0] = 0;
}
for (size_t i = 1; i < m; i++)
for (size_t j = 1; j < n; j++)
if (matrix[i][0] == 0 || matrix[0][j] == 0)
matrix[i][j] = 0;
if (row_has_zero)
for (size_t i = 0; i < n; i++)
matrix[0][i] = 0;
if (col_has_zero)
for (size_t i = 0; i < m; i++)
matrix[i][0] = 0;
}
};
There are N gas stations along a circular route, where the amount of gas at station i is gas[i].
You have a car with an unlimited gas tank and it costs cost[i] of gas to travel from station i to its next
station (i+1). You begin the journey with an empty tank at one of the gas stations.
Return the starting gas stations index if you can travel around the circuit once, otherwise return -1.
Note: The solution is guaranteed to be unique.
O(N 2 )
O(N )
sum
sum
total
-1
36
if (sum < 0) {
j = i;
sum = 0;
}
}
return total >= 0 ? j + 1 : -1;
}
};
2.1.22 Candy
There are N children standing in a line. Each child is assigned a rating value.
You are giving candies to these children subjected to the following requirements:
Each child must have at least one candy.
Children with a higher rating get more candies than their neighbors.
What is the minimum candies you must give?
// LeetCode, Candy
//
O(n)
O(n)
class Solution {
public:
int candy(vector<int> &ratings) {
const int n = ratings.size();
vector<int> increment(n);
//
for (int i = 1, inc = 1; i < n; i++) {
if (ratings[i] > ratings[i - 1])
increment[i] = max(inc++, increment[i]);
else
inc = 1;
}
for (int i = n - 2, inc = 1; i >= 0; i--) {
if (ratings[i] > ratings[i + 1])
37
2.1
// LeetCode, Candy
//
O(n)
O(n)
// @author fancymouse (http://weibo.com/u/1928162822)
class Solution {
public:
int candy(const vector<int>& ratings) {
vector<int> f(ratings.size());
int sum = 0;
for (int i = 0; i < ratings.size(); ++i)
sum += solve(ratings, f, i);
return sum;
}
int solve(const vector<int>& ratings, vector<int>&
if (f[i] == 0) {
f[i] = 1;
if (i > 0 && ratings[i] > ratings[i - 1])
f[i] = max(f[i], solve(ratings, f, i if (i < ratings.size() - 1 && ratings[i] >
f[i] = max(f[i], solve(ratings, f, i +
}
return f[i];
}
};
f, int i) {
1) + 1);
ratings[i + 1])
1) + 1);
Given an array of integers, every element appears twice except for one. Find that single one.
Note: Your algorithm should have a linear runtime complexity. Could you implement it without using
extra memory?
38
1
// LeetCode, Single Number
//
O(n)
O(1)
class Solution {
public:
int singleNumber(vector<int>& nums) {
int x = 0;
for (auto i : nums) {
x ^= i;
}
return x;
}
};
2
// LeetCode, Single Number
//
O(n)
O(1)
class Solution {
public:
int singleNumber(vector<int>& nums) {
return accumulate(nums.begin(), nums.end(), 0, bit_xor<int>());
}
};
2.1.24
Given an array of integers, every element appears three times except for one. Find that single one.
Note: Your algorithm should have a linear runtime complexity. Could you implement it without using
extra memory?
Single Number
1
sizeof(int)
count[i]
count[sizeof(int)] count[i]
39
2.1
one
two
one
1
two
mod 3
mod 3
one
1
// LeetCode, Single Number II
//
1
O(n)
O(1)
class Solution {
public:
int singleNumber(vector<int>& nums) {
const int W = sizeof(int) * 8; //
int count[W]; // count[i]
i
fill_n(&count[0], W, 0);
for (int i = 0; i < nums.size(); i++) {
for (int j = 0; j < W; j++) {
count[j] += (nums[i] >> j) & 1;
count[j] %= 3;
}
}
int result = 0;
for (int i = 0; i < W; i++) {
result += (count[i] << i);
}
return result;
}
};
2
// LeetCode, Single Number II
//
2
O(n)
O(1)
class Solution {
public:
int singleNumber(vector<int>& nums) {
int one = 0, two = 0, three = 0;
for (auto i : nums) {
two |= (one & i);
one ^= i;
three = ~(one & two);
one &= three;
two &= three;
}
return one;
}
};
bit
1
40
Single Number,
2.1.23
2.2
//
struct ListNode {
int val;
ListNode *next;
ListNode(int x) : val(x), next(nullptr) { }
};
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
Add Binary
3.4
41
2.2
Add Binary,
3.4
15
bug free
42
return dummy.next;
}
};
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.
43
2.2
return left_dummy.next;
}
};
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.
head
recur(&dummy, head);
return dummy.next;
}
private:
static void recur(ListNode *prev, ListNode *cur) {
if (cur == nullptr) return;
if (prev->val == cur->val) { //
prev->next = cur->next;
delete cur;
recur(prev, prev->next);
} else {
recur(prev->next, cur->next);
}
}
};
head
44
2.2.5
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.
45
2.2
ListNode *p = head->next;
if (head->val == p->val) {
while (p && head->val == p->val) {
ListNode *tmp = p;
p = p->next;
delete tmp;
}
delete head;
return deleteDuplicates(p);
} else {
head->next = deleteDuplicates(head->next);
return head;
}
}
};
46
2.2.4
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->nullptr and k = 2, return 4->5->1->2->3->nullptr.
len
len
len k
k% = len
next
47
2.2
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.
p, q
// q
while(q->next) { //
p = p->next;
q = q->next;
}
ListNode *tmp = p->next;
p->next = p->next->next;
delete tmp;
return dummy.next;
}
};
Given a linked list, swap every two adjacent nodes and return its head.
p->next
48
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.
2.2.9
49
2.2
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
50
2.2.8
A linked list is given such that each node contains an additional random pointer which could point to
any node in the list or null.
Return a deep copy of the list.
51
2.2
52
O(N )
O(1)
http://leetcode.com/2010/09/detecting-loop-in-singly-linked-list.html
2.2.12
Given a linked list, return the node where the cycle begins. If there is no cycle, return null.
Follow up: Can you solve it without using extra space?
fast
slow
slow
s
slow
fast
2s
fast
s
fast
2s
s + nr
nr
(1 n)
r
53
2.2
x+a
nr = (n1)r + r = (n 1)r + L x
(n 1)r + (Lxa)
n1
Lxa
head
slow2
2.2.11
54
in-place
O(1)
reverse
55
2.2
Design and implement a data structure for Least Recently Used (LRU) cache. It should support the
following operations: get and set.
get(key) - Get the value (will always be positive) of the key if the key exists in the cache, otherwise
return -1.
set(key, value) - Set or insert the value if the key is not already present. When the cache reached its
capacity, it should invalidate the least recently used item before inserting a new item.
(std::list)
(std::unordered_map)
O(1)
hash
cache
size
capacity
hash
56
57
58
Palindrome Number,
15.2
O(m n)
Rabin-Karp
KMP
Boyer-Mooer
BUG
O(N*M)
O(1)
class Solution {
public:
int strStr(const string& haystack, const string& needle) {
if (needle.empty()) return 0;
const int N = haystack.size() - needle.size() + 1;
for (int i = 0; i < N; i++) {
int j = i;
int k = 0;
while (j < haystack.size() && k < needle.size() && haystack[j] == needle[k]) {
j++;
k++;
}
if (k == needle.size()) return i;
}
return -1;
}
};
KMP
// LeetCode, Implement strStr()
// KMP
O(N+M)
O(M)
class Solution {
public:
int strStr(const string& haystack, const string& needle) {
return kmp(haystack.c_str(), needle.c_str());
}
private:
/*
* @brief
next
.
*
* @param[in] pattern
* @param[out] next next
* @return
*/
static void compute_prefix(const char *pattern, int next[]) {
int i;
int j = -1;
const int m = strlen(pattern);
next[0] = j;
for (i = 1; i < m; i++) {
while (j > -1 && pattern[j + 1] != pattern[i]) j = next[j];
if (pattern[i] == pattern[j + 1]) j++;
next[i] = j;
}
}
/*
* @brief KMP
.
*
* @param[in] text
* @param[in] pattern
* @return
-1
*/
static int kmp(const char *text, const char *pattern) {
int i;
int j = -1;
const int n = strlen(text);
const int m = strlen(pattern);
if (n == 0 && m == 0) return 0; /* "","" */
if (m == 0) return 0; /* "a","" */
int *next = (int*)malloc(sizeof(int) * m);
compute_prefix(pattern, next);
for (i = 0; i < n; i++) {
while (j > -1 && pattern[j + 1] != text[i]) j = next[j];
if (text[i] == pattern[j + 1]) j++;
if (j == m - 1) {
free(next);
return i-j;
}
}
free(next);
return -1;
}
59
60
};
3.3
1.
-3924x8fc
2.
++c, ++1
3.
2147483648
+ 413,
61
public:
int myAtoi(const string &str) {
int num = 0;
int sign = 1;
const int n = str.length();
int i = 0;
while (str[i] == ' ' && i < n) i++;
if (str[i] == '+') {
i++;
} else if (str[i] == '-') {
sign = -1;
i++;
}
for (; i < n; i++) {
if (str[i] < '0' || str[i] > '9')
break;
if (num > INT_MAX / 10 ||
(num == INT_MAX / 10 &&
(str[i] - '0') > INT_MAX % 10)) {
return sign == -1 ? INT_MIN : INT_MAX;
}
num = num * 10 + str[i] - '0';
}
return num * sign;
}
};
Implement strStr()
3.2
62
2.2.1
O(n2 )
O(n2 )
f[i][j]
[i,j]
f[i][j] = if (i == j) S[i]
if (S[i] == S[j] && f[i+1][j-1] == S[i+1][j-1]) S[i][j]
else max(f[i+1][j-1], f[i][j-1], f[i+1][j])
63
f(i,j)
[i,j]
true
O(n)
,i = j
,j = i + 1
,j > i + 1
http://leetcode.com/2011/11/longest-
palindromic-substring-part-ii.html
64
{
// [j, i]
- j < 2 || f[j + 1][i - 1]));
j + 1)) {
}
};
Manacher s Algorithm
// LeetCode, Longest Palindromic Substring
// Manacher s Algorithm
//
O(n)
O(n)
class Solution {
public:
// Transform S into T.
// For example, S = "abba", T = "^#a#b#b#a#$".
// ^ and $ signs are sentinels appended to each end to avoid bounds checking
string preProcess(const string& s) {
int n = s.length();
65
if (n == 0) return "^$";
string ret = "^";
for (int i = 0; i < n; i++) ret += "#" + s.substr(i, 1);
ret += "#$";
return ret;
}
string longestPalindrome(string s) {
string T = preProcess(s);
const int n = T.length();
//
T[i]
/
//
P[i]
int P[n];
int C = 0, R = 0;
T[i]
66
67
}
}
};
Wildcard Matching,
3.7
'*'
'*'
s++
//
O(n!*m!)
class Solution {
public:
O(n)
'*'
68
69
3.6
70
string::[]
strtod()
O(n)
71
SIGN,
DIGIT,
DOT,
EXPONENT,
NUM_INPUTS
//
//
//
//
//
2
3
4
5
6
};
const int transitionTable[][NUM_INPUTS] = {
-1, 0, 3, 1, 2, -1, // next states for state 0
-1, 8, -1, 1, 4, 5,
// next states for state 1
-1, -1, -1, 4, -1, -1,
// next states for state 2
-1, -1, -1, 1, 2, -1,
// next states for state 3
-1, 8, -1, 4, -1, 5,
// next states for state 4
-1, -1, 6, 7, -1, -1,
// next states for state 5
-1, -1, -1, 7, -1, -1,
// next states for state 6
-1, 8, -1, 7, -1, -1,
// next states for state 7
-1, 8, -1, -1, -1, -1,
// next states for state 8
};
int state = 0;
for (auto ch : s) {
InputType inputType = INVALID;
if (isspace(ch))
inputType = SPACE;
else if (ch == '+' || ch == '-')
inputType = SIGN;
else if (isdigit(ch))
inputType = DIGIT;
else if (ch == '.')
inputType = DOT;
else if (ch == 'e' || ch == 'E')
inputType = EXPONENT;
// Get next state from current state and input symbol
state = transitionTable[state][inputType];
// Invalid input
if (state == -1) return false;
}
// If the current state belongs to one of the accepting (final) states,
// then the number is valid
return state == 1 || state == 4 || state == 7 || state == 8;
}
};
strtod()
// LeetCode, Valid Number
// @author
(http://weibo.com/lianchengzju)
//
strtod()
O(n)
class Solution {
public:
bool isNumber (const string& s) {
72
return isNumber(s.c_str());
}
private:
bool isNumber (char const* s) {
char* endptr;
strtod (s, &endptr);
if (endptr == s) return false;
for (; *endptr; ++endptr)
if (!isspace (*endptr)) return false;
return true;
}
};
73
}
return roman;
}
};
Roman to Integer,
3.11
IV = 5 1
VI = 5 + 1, II=1+1
74
result += map(s[i]);
}
}
return result;
}
};
Integer to Roman,
3.10
75
3.13 Anagrams
3.13 Anagrams
Given an array of strings, return all groups of strings that are anagrams.
Note: All inputs will be in lower-case.
"dormitory"
Anagram
"dirty room"
"tea"
"eat"
anagrams
// LeetCode, Anagrams
//
O(n)
O(n)
class Solution {
public:
vector<string> anagrams(vector<string> &strs) {
unordered_map<string, vector<string> > group;
for (const auto &s : strs) {
string key = s;
sort(key.begin(), key.end());
group[key].push_back(s);
}
vector<string> result;
for (auto it = group.cbegin(); it != group.cend(); it++) {
if (it->second.size() > 1)
result.insert(result.end(), it->second.begin(), it->second.end());
}
76
return result;
}
};
'///'
dir
77
} else
dirs.push_back(dir);
}
i = j;
}
stringstream out;
if (dirs.empty()) {
out << "/";
} else {
for (auto dir : dirs)
out << '/' << dir;
}
return out.str();
}
};
STL
// LeetCode, Length of Last Word
//
STL
//
O(n)
O(1)
class Solution {
public:
int lengthOfLastWord(const string& s) {
auto first = find_if(s.rbegin(), s.rend(), ::isalpha);
auto last = find_if_not(first, s.rend(), ::isalpha);
78
4.1
4.1.1 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.
79
80
return stk.empty();
}
};
Generate Parentheses,
10.9
4.1.2
Given a string containing just the characters '(' and ')', find the length of the longest valid (wellformed) parentheses substring.
For "(()", the longest valid parentheses substring is "()", which has length = 2.
Another example is ")()())", where the longest valid parentheses substring is "()()", which has
length = 4.
81
4.1
}
}
}
}
return max_len;
}
};
82
}
}
depth = 0;
start = s.size();
for (int i = s.size() - 1; i >= 0; --i) {
if (s[i] == ')') {
++depth;
} else {
--depth;
if (depth < 0) {
start = i;
depth = 0;
} else if (depth == 0) {
answer = max(answer, start - i);
}
}
}
return answer;
}
};
Valid Parentheses,
Generate Parentheses,
4.1.1
10.9
Given n non-negative integers representing the histograms bar height where the width of each bar is 1,
find the area of largest rectangle in the histogram.
4-1
83
4.1
4-2
The largest rectangle is shown in the shaded area, which has area = 10 unit.
i=4
3
3
3
4
84
}
};
85
4.2
4.2
LeetCode
//
struct TreeNode {
int val;
TreeNode *left;
TreeNode *right;
TreeNode(int x) : val(x), left(nullptr), right(nullptr) { }
};
5.1
(root->left->right) root->right->left
>right->root) right->left->root
(left(left->root->right)
Given a binary tree, return the preorder traversal of its nodes values.
For example: Given binary tree {1,#,2,3},
1
\
2
/
3
return [1,2,3].
Note: Recursive solution is trivial, could you do it iteratively?
86
87
5.1
Morris
Morris
// LeetCode, Binary Tree Preorder Traversal
// Morris
O(n)
O(1)
class Solution {
public:
vector<int> preorderTraversal(TreeNode *root) {
vector<int> result;
TreeNode *cur = root, *prev = nullptr;
while (cur != nullptr) {
if (cur->left == nullptr) {
result.push_back(cur->val);
prev = cur; /* cur
*/
cur = cur->right;
} else {
/*
*/
TreeNode *node = cur->left;
while (node->right != nullptr && node->right != cur)
node = node->right;
if (node->right == nullptr) { /*
result.push_back(cur->val); /*
node->right = cur;
prev = cur; /* cur
*/
*/
*/
88
cur = cur->left;
} else {
/*
node->right = nullptr;
/* prev = cur;
cur = cur->right;
}
*/
cur
}
}
return result;
}
};
5.1.2
5.1.3
5.1.7
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?
Morris
*/
89
5.1
Morris
// LeetCode, Binary Tree Inorder Traversal
// Morris
O(n)
O(1)
class Solution {
public:
vector<int> inorderTraversal(TreeNode *root) {
vector<int> result;
TreeNode *cur = root, *prev = nullptr;
while (cur != nullptr) {
if (cur->left == nullptr) {
result.push_back(cur->val);
prev = cur;
cur = cur->right;
} else {
/*
*/
TreeNode *node = cur->left;
while (node->right != nullptr && node->right != cur)
node = node->right;
if (node->right == nullptr) { /*
node->right = cur;
/* prev = cur;
cur
cur = cur->left;
} else {
/*
result.push_back(cur->val);
node->right = nullptr;
prev = cur;
cur = cur->right;
}
}
}
return result;
}
};
*/
*/
*/
90
5.1.1
5.1.3
5.1.7
Given a binary tree, return the postorder traversal of its nodes values.
For example: Given binary tree {1,#,2,3},
1
\
2
/
3
return [3,2,1].
Note: Recursive solution is trivial, could you do it iteratively?
Morris
*/
*/
91
5.1
result.push_back(p->val);
q = p; /*
} else {
/*
s.push(p);
/*
*/
p = p->right;
break;
}
*/
*/
}
} while (!s.empty());
return result;
}
};
Morris
// LeetCode, Binary Tree Postorder Traversal
// Morris
O(n)
O(1)
class Solution {
public:
vector<int> postorderTraversal(TreeNode *root) {
vector<int> result;
TreeNode dummy(-1);
TreeNode *cur, *prev = nullptr;
std::function < void(const TreeNode*)> visit =
[&result](const TreeNode *node){
result.push_back(node->val);
};
dummy.left = root;
cur = &dummy;
while (cur != nullptr) {
if (cur->left == nullptr) {
prev = cur; /*
*/
cur = cur->right;
} else {
TreeNode *node = cur->left;
while (node->right != nullptr && node->right != cur)
node = node->right;
if (node->right == nullptr) { /*
node->right = cur;
prev = cur; /*
*/
cur = cur->left;
} else { /*
visit_reverse(cur->left, prev, visit);
prev->right = nullptr;
prev = cur; /*
*/
cur = cur->right;
}
}
*/
*/
92
}
return result;
}
private:
//
static void reverse(TreeNode *from, TreeNode *to) {
TreeNode *x = from, *y = from->right, *z;
if (from == to) return;
while (x != to) {
z = y->right;
y->right = x;
x = y;
y = z;
}
}
//
static void visit_reverse(TreeNode* from, TreeNode *to,
std::function< void(const TreeNode*) >& visit) {
TreeNode *p = to;
reverse(from, to);
while (true) {
visit(p);
if (p == from)
break;
p = p->right;
}
reverse(to, from);
}
};
5.1.1
5.1.2
5.1.7
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},
93
5.1
3
/ \
9 20
/ \
15
7
return its level order traversal as:
[
[3],
[9,20],
[15,7]
]
94
if(root == nullptr) {
return result;
} else {
current.push(root);
}
while (!current.empty()) {
vector<int> level; // elments in one level
while (!current.empty()) {
TreeNode* node = current.front();
current.pop();
level.push_back(node->val);
if (node->left != nullptr) next.push(node->left);
if (node->right != nullptr) next.push(node->right);
}
result.push_back(level);
swap(next, current);
}
return result;
}
};
5.1.5
5.1.6
Given a binary tree, return the bottom-up level order traversal of its nodes values. (ie, from left to right,
level by level from leaf to root).
For example: Given binary tree {3,9,20,#,#,15,7},
3
/ \
9 20
/ \
15
7
return its bottom-up level order traversal as:
[
[15,7]
[9,20],
[3],
]
95
5.1
5.1.4
reverse()
return result;
}
void traverse(TreeNode *root, size_t level, vector<vector<int>> &result) {
if (!root) return;
if (level > result.size())
result.push_back(vector<int>());
result[level-1].push_back(root->val);
traverse(root->left, level+1, result);
traverse(root->right, level+1, result);
}
};
96
level.clear();
swap(next, current);
}
reverse(result.begin(), result.end()); //
return result;
}
};
5.1.4
5.1.6
Given a binary tree, return the zigzag level order traversal of its nodes values. (ie, from left to right,
then right to left for the next level and alternate between).
For example: Given binary tree 3,9,20,#,#,15,7,
3
/ \
9 20
/ \
15
7
return its zigzag level order traversal as:
[
[3],
[20,9],
[15,7]
]
bool
97
5.1
}
void traverse(TreeNode *root, size_t level, vector<vector<int>> &result,
bool left_to_right) {
if (!root) return;
if (level > result.size())
result.push_back(vector<int>());
if (left_to_right)
result[level-1].push_back(root->val);
else
result[level-1].insert(result[level-1].begin(), root->val);
traverse(root->left, level+1, result, !left_to_right);
traverse(root->right, level+1, result, !left_to_right);
}
};
98
};
5.1.4
5.1.5
O(n)
O(n)
Morris
O(1)
cur
99
5.1
cur = cur->left;
} else {
detect(broken, prev, cur);
node->right = nullptr;
prev = cur;
cur = cur->right;
}
}
}
swap(broken.first->val, broken.second->val);
}
void detect(pair<TreeNode*, TreeNode*>& broken, TreeNode* prev,
TreeNode* current) {
if (prev != nullptr && prev->val > current->val) {
if (broken.first == nullptr) {
broken.first = prev;
} //
else
{0,1}
swap
second
nullptr
//
Runtime Error
broken.second = current;
}
}
};
5.1.2
Given two binary trees, write a function to check if they are equal or not.
Two binary trees are considered equal if they are structurally identical and the nodes have the same value.
100
Symmetric Tree
5.1.9
Given two binary trees, write a function to check if they are equal or not.
Two binary trees are considered equal if they are structurally identical and the nodes have the same value.
101
5.1
//
//
102
}
};
Same Tree
5.1.8
//
103
5.1
1
// LeetCode, Flatten Binary Tree to Linked List
//
1
O(n)
O(logn)
class Solution {
public:
void flatten(TreeNode *root) {
if (root == nullptr) return; //
flatten(root->left);
flatten(root->right);
if (nullptr == root->left) return;
//
TreeNode *p = root->left;
while(p->right) p = p->right; //
p->right = root->right;
root->right = root->left;
root->left = nullptr;
}
};
root
root->right
104
2
// LeetCode, Flatten Binary Tree to Linked List
//
2
// @author
(http://weibo.com/u/1234984145)
//
O(n)
O(logn)
class Solution {
public:
void flatten(TreeNode *root) {
flatten(root, NULL);
}
private:
//
root
tail
TreeNode *flatten(TreeNode *root, TreeNode *tail) {
if (NULL == root) return tail;
root->right = flatten(root->left, flatten(root->right, tail));
root->left = NULL;
return root;
}
};
105
5.1
106
prev->next = curr->right;
prev = prev->next;
}
}
connect(dummy.next);
}
};
5.4.6
5.2
5.2.1 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.
107
5.2
5.2.2
Given inorder and postorder traversal of a tree, construct the binary tree.
Note: You may assume that duplicates do not exist in the tree.
108
5.2.1
5.3
5.3.1 Unique Binary Search Trees
Given n, how many structurally unique BSTs (binary search trees) that store values 1...n?
For example, Given n = 3, there are a total of 5 unique BSTs.
1
3
\
/
3
2
/
/
2
3
/
1
\
2
2
/ \
1
3
1
\
2
\
3
109
5.3
1
\
\
3
/
2
/ \
2
3
3
3
/
/
1
/
1
\
2
1
1, 2, 3, ..., n
BST
[1, i-1]
[i+1, n]
f (i)
[1, i]
BST
1
f (1) = 1
BST
1,2
1
2
/
\
2
f (2)
f (0) f (1)
f (1) f (0)
BST
f (3)
f (0) f (2)
f (1) f (1)
f (2) f (0)
f
f (i) =
f (k 1) f (i k)
k=1
110
public:
int numTrees(int n) {
vector<int> f(n + 1, 0);
f[0] = 1;
f[1] = 1;
for (int i = 2; i <= n; ++i) {
for (int k = 1; k <= i; ++k)
f[i] += f[k-1] * f[i - k];
}
return f[n];
}
};
5.3.2
Given n, generate all structurally unique BSTs (binary search trees) that store values 1...n.
For example, Given n = 3, your program should return all 5 unique BSTs shown below.
1
3
3
2
1
\
/
/
/ \
\
3
2
1
1
3
2
/
/
\
\
2
1
2
3
111
5.3
subTree.push_back(nullptr);
return subTree;
}
for (int k = start; k <= end; k++) {
vector<TreeNode*> leftSubs = generate(start, k - 1);
vector<TreeNode*> rightSubs = generate(k + 1, end);
for (auto i : leftSubs) {
for (auto j : rightSubs) {
TreeNode *node = new TreeNode(k);
node->left = i;
node->right = j;
subTree.push_back(node);
}
}
}
return subTree;
}
};
5.3.1
112
5.3.3
Given an array where elements are sorted in ascending order, convert it to a height balanced BST.
//
//
auto mid = first + length / 2;
TreeNode* root = new TreeNode (*mid);
root->left = sortedArrayToBST(first, mid);
root->right = sortedArrayToBST(mid + 1, last);
return root;
}
};
113
5.3
5.3.5
Given a singly linked list where elements are sorted in ascending order, convert it to a height balanced
BST.
RandomAccessIt
erator
(bottom-up)
http://leetcode.com/2010/11/convert-sorted-list-to-balanced-
binary.html
O(n log n)
114
}
return n;
}
ListNode* nth_node (ListNode* node, int n) {
while (--n)
node = node->next;
return node;
}
};
5.4
5.3.4
115
5.4
10.12.5
DFS
3! = 6
root->r->l
r->root->l, r->l->root
116
s.push(make_pair(root, 1));
while (!s.empty()) {
auto node = s.top().first;
auto depth = s.top().second;
s.pop();
if (node->left == nullptr && node->right == nullptr)
result = min(result, depth);
if (node->left && result > depth) //
s.push(make_pair(node->left, depth + 1));
if (node->right && result > depth) //
s.push(make_pair(node->right, depth + 1));
}
return result;
}
};
5.4.2
117
5.4
5.4.1
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.
true
false
return
Path Sum II
5.4.4
118
Given a binary tree and a sum, find all root-to-leaf paths where each paths 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]
]
return
119
5.4
cur.pop_back();
}
};
Path Sum
5.4.3
13.2
Array
Binary Tree
Array
Binary Tree
dfs
L
L
R
Binary Tree
L
0
R
120
L->root
R->root
Maximum Subarray
13.2
121
5.4
5.1.12
Given a binary tree containing digits from 0-9 only, each root-to-leaf path could represent a number.
An example is the root-to-leaf path 1->2->3 which represents the number 123.
Find the total sum of all root-to-leaf numbers.
For example,
1
/ \
2
3
The root-to-leaf path 1->2 represents the number 12. The root-to-leaf path 1->3 represents the number
13.
Return the sum = 12 + 13 = 25.
122
6.2
6.3
123
124
6.3
6.2
125
6.2
126
Sort List,
6.5
O(nlogn)
Two Sorted Lists
O(1)
Merge
127
public:
ListNode *sortList(ListNode *head) {
if (head == NULL || head->next == NULL)return head;
//
ListNode *fast = head, *slow = head;
while (fast->next != NULL && fast->next->next != NULL) {
fast = fast->next->next;
slow = slow->next;
}
//
fast = slow;
slow = slow->next;
fast->next = NULL;
ListNode *l1 = sortList(head);
ListNode *l2 = sortList(slow);
return mergeTwoLists(l1, l2);
//
//
}
// Merge Two Sorted Lists
ListNode *mergeTwoLists(ListNode *l1, ListNode *l2) {
ListNode dummy(-1);
for (ListNode* p = &dummy; l1 != nullptr || l2 != nullptr; p = p->next) {
int val1 = l1 == nullptr ? INT_MAX : l1->val;
int val2 = l2 == nullptr ? INT_MAX : l2->val;
if (val1 <= val2) {
p->next = l1;
l1 = l1->next;
} else {
p->next = l2;
l2 = l2->next;
}
}
return dummy.next;
}
};
6.4
128
(bucket sort)
A[i]!= i+1
A[i]
A[A[i]-1]
A[i]== A[A[i]-1]
Sort Colors,
6.7
129
First, iterate the array counting number of 0s, 1s, and 2s, then overwrite array with total number of 0s,
then 1s and followed by 2s.
Could you come up with an one-pass algorithm using only constant space?
0, 1, 2
(counting sort)
index
O(n)
red
index
blue
index
O(1)
partition
1
// LeetCode, Sort Colors
// Counting Sort
//
O(n)
O(1)
class Solution {
public:
void sortColors(vector<int>& A) {
int counts[3] = { 0 }; //
for (int i = 0; i < A.size(); i++)
counts[A[i]]++;
for (int i = 0, index = 0; i < 3; i++)
for (int j = 0; j < counts[i]; j++)
A[index++] = i;
}
};
2
// LeetCode, Sort Colors
//
O(n)
O(1)
class Solution {
public:
void sortColors(vector<int>& A) {
//
red
index
blue
int red = 0, blue = A.size() - 1;
for (int i = 0; i < blue + 1;) {
if (A[i] == 0)
swap(A[i++], A[red++]);
else if (A[i] == 2)
swap(A[i], A[blue--]);
else
index
130
i++;
}
}
};
3
// LeetCode, Sort Colors
// use partition()
//
O(n)
O(1)
class Solution {
public:
void sortColors(vector<int>& nums) {
partition(partition(nums.begin(), nums.end(), bind1st(equal_to<int>(), 0)),
nums.end(), bind1st(equal_to<int>(), 1));
}
};
4
// LeetCode, Sort Colors
//
partition()
//
O(n)
O(1)
class Solution {
public:
void sortColors(vector<int>& nums) {
partition(partition(nums.begin(), nums.end(), bind1st(equal_to<int>(), 0)),
nums.end(), bind1st(equal_to<int>(), 1));
}
private:
template<typename ForwardIterator, typename UnaryPredicate>
ForwardIterator partition(ForwardIterator first, ForwardIterator last,
UnaryPredicate pred) {
auto pos = first;
for (; first != last; ++first)
if (pred(*first))
swap(*first, *pos++);
return pos;
}
};
6.6
STL
lower_bound
upper_bound
131
132
public:
vector<int> searchRange (vector<int>& nums, int target) {
auto lower = lower_bound(nums.begin(), nums.end(), target);
auto uppper = upper_bound(lower, nums.end(), target);
first = ++mid;
last = mid;
}
return first;
}
template<typename ForwardIterator, typename T>
ForwardIterator upper_bound (ForwardIterator first,
ForwardIterator last, T value) {
while (first != last) {
auto mid = next(first, distance (first, last) / 2);
if (value >= *mid)
else
first = ++mid;
last = mid;
//
lower_bound
}
return first;
}
};
7.2
133
std::lower_bound()
first = ++mid;
last = mid;
}
return first;
}
};
7.1
134
8.1 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],
[]
]
8.1.1
// LeetCode, Subsets
//
O(2^n)
O(n)
class Solution {
public:
vector<vector<int> > subsets(vector<int> &S) {
sort(S.begin(), S.end()); //
vector<vector<int> > result;
vector<int> path;
subsets(S, path, 0, result);
return result;
135
136
}
private:
static void subsets(const vector<int> &S, vector<int> &path, int step,
vector<vector<int> > &result) {
if (step == S.size()) {
result.push_back(path);
return;
}
//
S[step]
subsets(S, path, step + 1, result);
//
S[step]
path.push_back(S[step]);
subsets(S, path, step + 1, result);
path.pop_back();
}
};
bool selected[n]
// LeetCode, Subsets
//
O(2^n)
O(n)
class Solution {
public:
vector<vector<int> > subsets(vector<int> &S) {
sort(S.begin(), S.end()); //
vector<vector<int> > result;
vector<bool> selected(S.size(), false);
subsets(S, selected, 0, result);
return result;
}
private:
static void subsets(const vector<int> &S, vector<bool> &selected, int step,
vector<vector<int> > &result) {
if (step == S.size()) {
vector<int> subset;
for (int i = 0; i < S.size(); i++) {
if (selected[i]) subset.push_back(S[i]);
}
result.push_back(subset);
return;
}
//
S[step]
selected[step] = false;
subsets(S, selected, step + 1, result);
//
S[step]
selected[step] = true;
subsets(S, selected, step + 1, result);
137
8.1 Subsets
}
};
8.1.2
// LeetCode, Subsets
//
O(2^n)
O(1)
class Solution {
public:
vector<vector<int> > subsets(vector<int> &S) {
sort(S.begin(), S.end()); //
vector<vector<int> > result(1);
for (auto elem : S) {
result.reserve(result.size() * 2);
auto half = result.begin() + result.size();
copy(result.begin(), half, back_inserter(result));
for_each(half, result.end(), [&elem](decltype(result[0]) &e){
e.push_back(elem);
});
}
return result;
}
};
int
S[i]
S={A,B,C,D}
0
B1
B2
int
0110=6
B1 B2 , B1 B2 , B1 B2
// LeetCode, Subsets
//
O(2^n)
O(1)
class Solution {
public:
vector<vector<int> > subsets(vector<int> &S) {
sort(S.begin(), S.end()); //
vector<vector<int> > result;
const size_t n = S.size();
vector<int> v;
for (size_t i = 0; i < 1 << n; i++) {
for (size_t j = 0; j < n; j++) {
if (i & 1 << j) v.push_back(S[j]);
}
result.push_back(v);
v.clear();
{B,C}
138
}
return result;
}
};
Subsets II
8.2
8.2 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],
[]
]
8.2.1
// LeetCode, Subsets II
//
1
O(2^n)
O(n)
class Solution {
public:
vector<vector<int> > subsetsWithDup(vector<int> &S) {
sort(S.begin(), S.end()); //
vector<vector<int> > result;
vector<int> path;
dfs(S, S.begin(), path, result);
8.2 Subsets II
return result;
}
private:
static void dfs(const vector<int> &S, vector<int>::iterator start,
vector<int> &path, vector<vector<int> > &result) {
result.push_back(path);
for (auto i = start; i < S.end(); i++) {
if (i != start && *i == *(i-1)) continue;
path.push_back(*i);
dfs(S, i + 1, path, result);
path.pop_back();
}
}
};
// LeetCode, Subsets II
//
2
O(2^n)
O(n)
class Solution {
public:
vector<vector<int> > subsetsWithDup(vector<int> &S) {
vector<vector<int> > result;
sort(S.begin(), S.end()); //
unordered_map<int, int> count_map; //
for_each(S.begin(), S.end(), [&count_map](int e) {
if (count_map.find(e) != count_map.end())
count_map[e]++;
else
count_map[e] = 1;
});
//
map
pair
vector
vector<pair<int, int> > elems;
for_each(count_map.begin(), count_map.end(),
[&elems](const pair<int, int> &e) {
elems.push_back(e);
});
sort(elems.begin(), elems.end());
vector<int> path; //
subsets(elems, 0, path, result);
return result;
}
private:
static void subsets(const vector<pair<int, int> > &elems,
size_t step, vector<int> &path, vector<vector<int> > &result) {
if (step == elems.size()) {
result.push_back(path);
return;
}
139
140
// LeetCode, Subsets II
//
O(2^n)
O(n)
class Solution {
public:
vector<vector<int> > subsetsWithDup(vector<int> &S) {
vector<vector<int> > result; //
sort(S.begin(), S.end());
vector<int> count(S.back() - S.front() + 1, 0);
//
for (auto i : S) {
count[i - S[0]]++;
}
//
vector<int> selected(S.back() - S.front() + 1, -1);
subsets(S, count, selected, 0, result);
return result;
}
private:
static void subsets(const vector<int> &S, vector<int> &count,
vector<int> &selected, size_t step, vector<vector<int> > &result) {
if (step == count.size()) {
vector<int> subset;
for(size_t i = 0; i < selected.size(); i++) {
for (int j = 0; j < selected[i]; j++) {
subset.push_back(i+S[0]);
}
}
result.push_back(subset);
return;
}
for (int i = 0; i <= count[step]; i++) {
selected[step] = i;
subsets(S, count, selected, step + 1, result);
}
}
8.2 Subsets II
};
8.2.2
// LeetCode, Subsets II
//
//
O(2^n)
O(1)
class Solution {
public:
vector<vector<int> > subsetsWithDup(vector<int> &S) {
sort(S.begin(), S.end()); //
vector<vector<int> > result(1);
size_t previous_size = 0;
for (size_t i = 0; i < S.size(); ++i) {
const size_t size = result.size();
for (size_t j = 0; j < size; ++j) {
if (i == 0 || S[i] != S[i-1] || j >= previous_size) {
result.push_back(result[j]);
result.back().push_back(S[i]);
}
}
previous_size = size;
}
return result;
}
};
// LeetCode, Subsets II
//
O(2^n)
O(1)
class Solution {
public:
vector<vector<int> > subsetsWithDup(vector<int> &S) {
sort(S.begin(), S.end()); //
//
set
unordered_set
set<vector<int> > result;
const size_t n = S.size();
vector<int> v;
for (size_t i = 0; i < 1U << n; ++i) {
for (size_t j = 0; j < n; ++j) {
if (i & 1 << j)
v.push_back(S[j]);
}
result.insert(v);
v.clear();
}
vector<vector<int> > real_result;
141
142
Subsets
8.1
8.3 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].
8.3.1 next_permutation()
std::next_permutation()
OJ
// LeetCode, Permutations
//
O(n!)
O(1)
class Solution {
public:
vector<vector<int> > permute(vector<int> &num) {
vector<vector<int> > result;
sort(num.begin(), num.end());
do {
result.push_back(num);
} while(next_permutation(num.begin(), num.end()));
return result;
}
};
8.3.2
next_permutation()
2.1.12
API
143
8.3 Permutations
// LeetCode, Permutations
//
next_permutation()
//
O(n!)
O(1)
class Solution {
public:
vector<vector<int> > permute(vector<int> &num) {
vector<vector<int> > result;
sort(num.begin(), num.end());
do {
result.push_back(num);
//
2.1.12
next_permutation()
//
std::next_permutation()
} while(next_permutation(num.begin(), num.end()));
return result;
}
};
8.3.3
// LeetCode, Permutations
//
//
O(n!)
O(n)
class Solution {
public:
vector<vector<int> > permute(vector<int>& num) {
sort(num.begin(), num.end());
vector<vector<int>> result;
vector<int> path; //
dfs(num, path, result);
return result;
}
private:
void dfs(const vector<int>& num, vector<int> &path,
vector<vector<int> > &result) {
if (path.size() == num.size()) { //
result.push_back(path);
return;
}
144
//
for (auto i : num) {
//
i
path
auto pos = find(path.begin(), path.end(), i);
if (pos == path.end()) {
path.push_back(i);
dfs(num, path, result);
path.pop_back();
}
}
}
};
Next Permutation,
2.1.12
Permutation Sequence,
Permutations II,
Combinations,
2.1.13
8.4
8.5
8.4 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].
8.4.1 next_permutation()
std::next_permutation()
8.4.2
next_permutation()
std::next_permutation()
8.4.3
permute()
8.4 Permutations II
// LeetCode, Permutations II
//
O(n!)
O(n)
class Solution {
public:
vector<vector<int> > permuteUnique(vector<int>& num) {
sort(num.begin(), num.end());
unordered_map<int, int> count_map; //
for_each(num.begin(), num.end(), [&count_map](int e) {
if (count_map.find(e) != count_map.end())
count_map[e]++;
else
count_map[e] = 1;
});
//
map
pair
vector
vector<pair<int, int> > elems;
for_each(count_map.begin(), count_map.end(),
[&elems](const pair<int, int> &e) {
elems.push_back(e);
});
vector<vector<int>> result; //
vector<int> p; //
n = num.size();
permute(elems.begin(), elems.end(), p, result);
return result;
}
private:
size_t n;
typedef vector<pair<int, int> >::const_iterator Iter;
void permute(Iter first, Iter last, vector<int> &p,
vector<vector<int> > &result) {
if (n == p.size()) { //
result.push_back(p);
}
//
for (auto i = first; i != last; i++) {
int count = 0; //
*i
p
for (auto j = p.begin(); j != p.end(); j++) {
if (i->first == *j) {
count ++;
}
}
if (count < i->second) {
p.push_back(i->first);
permute(first, last, p, result);
145
146
p.pop_back(); //
}
}
}
};
Next Permutation,
2.1.12
Permutation Sequence,
Permutations,
Combinations,
2.1.13
8.3
8.5
8.5 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],
]
8.5.1
// LeetCode, Combinations
//
//
O(n!)
O(n)
class Solution {
public:
vector<vector<int> > combine(int n, int k) {
vector<vector<int> > result;
vector<int> path;
dfs(n, k, 1, 0, path, result);
return result;
}
private:
// start
, cur
static void dfs(int n, int k, int start, int cur,
vector<int> &path, vector<vector<int> > &result) {
if (cur == k) {
result.push_back(path);
}
for (int i = start; i <= n; ++i) {
path.push_back(i);
dfs(n, k, i + 1, cur + 1, path, result);
path.pop_back();
}
}
};
8.5.2
// LeetCode, Combinations
// use prev_permutation()
//
O((n-k)!)
O(n)
class Solution {
public:
vector<vector<int> > combine(int n, int k) {
vector<int> values(n);
iota(values.begin(), values.end(), 1);
vector<bool> select(n, false);
fill_n(select.begin(), k, true);
vector<vector<int> > result;
do{
vector<int> one(k);
for (int i = 0, index = 0; i < n; ++i)
if (select[i])
one[index++] = values[i];
result.push_back(one);
} while(prev_permutation(select.begin(), select.end()));
return result;
}
};
Next Permutation,
2.1.12
Permutation Sequence,
Permutations,
Permutations II,
2.1.13
8.3
8.4
147
148
8-1
Phone Keyboard
8.6.1
// LeetCode, Letter Combinations of a Phone Number
//
O(3^n)
O(n)
class Solution {
public:
const vector<string> keyboard { " ", "", "abc", "def", // '0','1','2',...
"ghi", "jkl", "mno", "pqrs", "tuv", "wxyz" };
vector<string> letterCombinations (const string &digits) {
vector<string> result;
if (digits.empty()) return result;
dfs(digits, 0, "", result);
return result;
}
void dfs(const string &digits, size_t cur, string path,
vector<string> &result) {
if (cur == digits.size()) {
result.push_back(path);
return;
}
for (auto c : keyboard[digits[cur] - '0']) {
dfs(digits, cur + 1, path + c, result);
}
149
}
};
8.6.2
// LeetCode, Letter Combinations of a Phone Number
//
O(3^n)
O(1)
class Solution {
public:
const vector<string> keyboard { " ", "", "abc", "def", // '0','1','2',...
"ghi", "jkl", "mno", "pqrs", "tuv", "wxyz" };
vector<string> letterCombinations (const string &digits) {
if (digits.empty()) return vector<string>();
vector<string> result(1, "");
for (auto d : digits) {
const size_t n = result.size();
const size_t m = keyboard[d - '0'].size();
result.resize(n * m);
for (size_t i = 0; i < m; ++i)
copy(result.begin(), result.begin() + n, result.begin() + n * i);
for (size_t i = 0; i < m; ++i) {
auto begin = result.begin();
for_each(begin + n * i, begin + n * (i+1), [&](string &s) {
s += keyboard[d - '0'][i];
});
}
}
return result;
}
};
A*
150
151
O(n)
152
if (state_is_valid(new_state) &&
visited.find(new_state) == visited.end()) {
result.insert(new_state);
}
swap(c, new_state.word[i]); //
}
}
return result;
};
state_t start_state(start, 0);
q.push(start_state);
visited.insert(start_state);
while (!q.empty()) {
//
const auto& pop()
//
const auto state = q.front();
q.pop();
if (state_is_target(state)) {
return state.level + 1;
}
const auto& new_states = state_extend(state);
for (const auto& new_state : new_states) {
q.push(new_state);
visited.insert(new_state);
}
}
return 0;
}
};
//
153
Word Ladder II
9.2
154
Word Ladder
BFS
O(n)
155
156
}
}
swap(c, new_state.word[i]); //
}
}
return result;
};
vector<vector<string>> result;
state_t start_state(start, 0);
q.push(start_state);
visited.insert(start_state);
while (!q.empty()) {
//
const auto& pop()
//
const auto state = q.front();
q.pop();
//
//
if (!result.empty() && state.level + 1 > result[0].size()) break;
if (state_is_target(state)) {
vector<string> path;
gen_path(father, start_state, state, path, result);
continue;
}
//
A
B
//
q
// visited.insert(state);
//
const auto& new_states = state_extend(state);
for (const auto& new_state : new_states) {
if (visited.find(new_state) == visited.end()) {
q.push(new_state);
}
visited.insert(new_state);
father[new_state].push_back(state);
}
}
return result;
}
private:
void gen_path(unordered_map<state_t, vector<state_t> > &father,
const state_t &start, const state_t &state, vector<string> &path,
vector<vector<string> > &result) {
path.push_back(state.word);
if (state == start) {
if (!result.empty()) {
if (path.size() < result[0].size()) {
157
result.clear();
result.push_back(path);
reverse(result.back().begin(), result.back().end());
} else if (path.size() == result[0].size()) {
result.push_back(path);
reverse(result.back().begin(), result.back().end());
} else { // not possible
throw std::logic_error("not possible to get here ");
}
} else {
result.push_back(path);
reverse(result.back().begin(), result.back().end());
}
} else {
for (const auto& f : father[state]) {
gen_path(father, start, f, path, result);
}
}
path.pop_back();
}
};
//
158
swap(c, new_word[i]);
if (state_is_valid(new_word) &&
visited.find(new_word) == visited.end()) {
result.insert(new_word);
}
swap(c, new_word[i]); //
}
}
return result;
};
vector<vector<string> > result;
current.insert(start);
while (!current.empty()) {
++ level;
//
//
if (!result.empty() && level+1 > result[0].size()) break;
// 1.
visited,
// 2.
current
visited,
//
for (const auto& state : current)
visited.insert(state);
for (const auto& state : current) {
if (state_is_target(state)) {
vector<string> path;
gen_path(father, path, start, state, result);
continue;
}
const auto new_states = state_extend(state);
for (const auto& new_state : new_states) {
next.insert(new_state);
father[new_state].push_back(state);
}
}
current.clear();
swap(current, next);
}
return result;
}
private:
void gen_path(unordered_map<string, vector<string> > &father,
vector<string> &path, const string &start, const string &word,
vector<vector<string> > &result) {
path.push_back(word);
if (word == start) {
if (!result.empty()) {
159
dict
160
161
Word Ladder
9.1
162
X
O
X
O
X
O
O
X
X
X
X
X
X
X
X
O
X
X
X
X
X
X
X
X
'O'
163
164
9.4
9.4.1
DAG
9.4.2
1.
(a)
(b)
i.
ii.
4
2.
3.
4.
BFS
(a)
(b)
DAG
visited
visited
(c)
i.
unordered_-
ii.
set
head
next
??
165
9.4
iii.
5.
9.4.3
hashset
queue
vector
state_t
1.
level
level
queue
A*
priority_queue
current, next
2.
level
level
level
(bool visited[STATE_MAX]
hashset
visited(STATE_MAX, false))
STL
STL
set
vector<bool>
unordered_set
STATE_MAX
MAX])
bfs_common.h
/**
*/
struct state_t {
int data1; /**
int data2; /**
// dataN;
/**
int action; /**
int level; /**
. */
. */
*/
. */
0
-1
*/
}
};
//
hash
//
1
hash
namespace std {
template<> struct hash<state_t> {
166
}
};
}
//
2
hash
class Hasher {
public:
Hasher(int _m) : m(_m) {};
size_t operator()(const state_t &s) const {
return 0; //
}
private:
int m; //
};
/**
* @brief
.
* @param[in] father
* @param[in] target
* @return
target
*/
vector<state_t> gen_path(const unordered_map<state_t, state_t> &father,
const state_t &target) {
vector<state_t> path;
path.push_back(target);
for (state_t cur = target; father.find(cur) != father.end();
cur = father.at(cur))
path.push_back(cur);
reverse(path.begin(), path.end());
return path;
}
/**
*
.
* @param[in] father
* @param[in] start
* @param[in] state
* @return
*/
void gen_path(unordered_map<state_t, vector<state_t> > &father,
const string &start, const state_t& state, vector<state_t> &path,
vector<vector<state_t> > &result) {
path.push_back(state);
if (state == start) {
if (!result.empty()) {
if (path.size() < result[0].size()) {
result.clear();
result.push_back(path);
167
9.4
bfs_template.cpp
#include "bfs_common.h"
/**
* @brief
.
* @param[in] start
* @param[in] data
* @return
*/
vector<state_t> bfs(state_t &start, const vector<vector<int>> &grid) {
queue<state_t> q; //
unordered_set<state_t> visited; //
unordered_map<state_t, state_t> father; //
//
auto state_is_valid = [&](const state_t &s) { /*...*/ };
//
auto state_is_target = [&](const state_t &s) { /*...*/ };
//
auto state_extend = [&](const state_t &s) {
unordered_set<state_t> result;
for (/*...*/) {
const state_t new_state = /*...*/;
if (state_is_valid(new_state) &&
visited.find(new_state) != visited.end()) {
result.insert(new_state);
}
}
168
return result;
};
assert (start.level == 0);
q.push(start);
while (!q.empty()) {
//
const auto& pop()
//
const state_t state = q.front();
q.pop();
visited.insert(state);
//
if (state_is_target(state)) {
return return gen_path(father, target); //
// return state.level + 1; //
}
//
vector<state_t> new_states = state_extend(state);
for (const auto& new_state : new_states) {
q.push(new_state);
father[new_state] = state; //
// visited.insert(state); //
//
q
//
visited
//
, visited.insert(start)
}
visited
while
}
return vector<state_t>();
//return 0;
}
bfs_template.cpp
bfs_template1.cpp
#include "bfs_common.h"
/**
* @brief
.
* @param[in] start
* @param[in] data
* @return
*/
vector<state_t> bfs(const state_t &start, const type& data) {
queue<state_t> next, current; //
unordered_set<state_t> visited; //
unordered_map<state_t, state_t> father; //
int level = -1;
//
//
169
9.4
while
}
swap(next, current); //!!!
}
return vector<state_t>();
// return 0;
}
bfs_template1.cpp
170
bfs_template.cpp
/**
* @brief
.
* @param[in] start
* @param[in] data
* @return
*/
vector<vector<state_t> > bfs(const state_t &start, const type& data) {
queue<state_t> q;
unordered_set<state_t> visited; //
unordered_map<state_t, vector<state_t> > father; // DAG
auto state_is_valid = [&](const state_t& s) { /*...*/ };
auto state_is_target = [&](const state_t &s) { /*...*/ };
auto state_extend = [&](const state_t &s) {
unordered_set<state_t> result;
for (/*...*/) {
const state_t new_state = /*...*/;
if (state_is_valid(new_state)) {
auto visited_iter = visited.find(new_state);
if (visited_iter != visited.end()) {
if (visited_iter->level < new_state.level) {
// do nothing
} else if (visited_iter->level == new_state.level) {
result.insert(new_state);
} else { // not possible
throw std::logic_error("not possible to get here");
}
} else {
result.insert(new_state);
}
}
}
return result;
};
vector<vector<string>> result;
state_t start_state(start, 0);
q.push(start_state);
visited.insert(start_state);
while (!q.empty()) {
//
const auto& pop()
//
const auto state = q.front();
q.pop();
//
//
171
9.4
bfs_template.cpp
#include "bfs_common.h"
/**
* @brief
.
* @param[in] start
* @param[in] data
* @return
*/
vector<vector<state_t> > bfs(const state_t &start, const type& data) {
//
unordered_set
//
vector,
next
//
father
next
unordered_set<string> current, next;
unordered_set<state_t> visited; //
unordered_map<state_t, vector<state_t> > father; // DAG
int level = -1;
//
//
auto state_is_valid = [&](const state_t &s) { /*...*/ };
//
auto state_is_target = [&](const state_t &s) { /*...*/ };
//
172
10
n1
O(2n1 )
1
//LeetCode, Palindrome Partitioning
//
O(2^n)
O(n)
class Solution {
public:
vector<vector<string>> partition(string s) {
vector<vector<string>> result;
vector<string> path; //
partition
dfs(s, path, result, 0, 1);
return result;
}
// prev
, start
void dfs(string &s, vector<string>& path,
vector<vector<string>> &result, size_t prev, size_t start) {
if (start == s.size()) { //
if (isPalindrome(s, prev, start - 1)) { //
path.push_back(s.substr(prev, start - prev));
173
174
10
result.push_back(path);
path.pop_back();
}
return;
}
//
dfs(s, path, result, prev, start + 1);
//
[prev, start-1]
if (isPalindrome(s, prev, start - 1)) {
//
path.push_back(s.substr(prev, start - prev));
dfs(s, path, result, start, start + 1);
path.pop_back();
}
}
bool isPalindrome(const string &s, int start, int end) {
while (start < end && s[start] == s[end]) {
++start;
--end;
}
return start >= end;
}
};
2
Combination Sum, Combination Sum II
//LeetCode, Palindrome Partitioning
//
O(2^n)
O(n)
class Solution {
public:
vector<vector<string>> partition(string s) {
vector<vector<string>> result;
vector<string> path; //
partition
DFS(s, path, result, 0);
return result;
}
//
s[start]
partition
void DFS(string &s, vector<string>& path,
vector<vector<string>> &result, int start) {
if (start == s.size()) {
result.push_back(path);
return;
}
for (int i = start; i < s.size(); i++) {
if (isPalindrome(s, start, i)) { //
i
path.push_back(s.substr(start, i - start + 1));
DFS(s, path, result, i + 1); //
path.pop_back(); //
}
}
175
}
bool isPalindrome(const string &s, int start, int end) {
while (start < end && s[start] == s[end]) {
++start;
--end;
}
return start >= end;
}
};
Palindrome Partitioning II
13.3
176
10
10-1 Above is a 3 7 grid. How many possible unique paths are there?
Note: m and n will be at most 100.
10.2.1
10.2.2
177
dfs(x, y - 1);
}
};
10.2.3
f[i][j]
(1, 1)
(i, j)
f[i][j]=f[i-1][j]+f[i][j-1]
f[i][j]
f[i-1][j]
178
10
}
return f[n - 1];
}
};
10.2.4
m
m+n2
m1
m+n2
m1
m1
Cm+n2
n >= 1
Unique Paths II
Minimum Path Sum,
10.3
13.8
179
10.3.1
//
// @return
(0, 0)
(x, y)
int dfs(const vector<vector<int> >& obstacleGrid,
int x, int y) {
if (x < 0 || y < 0) return 0; //
// (x,y)
if (obstacleGrid[x][y]) return 0;
if (x == 0 and y == 0) return f[0][0]; //
180
10
if (f[x][y] > 0) {
return f[x][y];
} else {
return f[x][y] = dfs(obstacleGrid, x - 1, y) +
dfs(obstacleGrid, x, y - 1);
}
}
};
10.3.2
Unique Paths
10.2
13.8
181
10.4 N-Queens
10.4 N-Queens
The n-queens puzzle is the problem of placing n queens on an n n chessboard such that no two queens
attack each other.
// Solution 2
182
10
1
// LeetCode, N-Queens
//
+
//
O(n!*n)
O(n)
class Solution {
public:
vector<vector<string> > solveNQueens(int n) {
vector<vector<string> > result;
vector<int> C(n, -1); // C[i]
i
dfs(C, result, 0);
return result;
}
private:
void dfs(vector<int> &C, vector<vector<string> > &result, int row) {
const int N = C.size();
if (row == N) { //
vector<string> solution;
for (int i = 0; i < N; ++i) {
string s(N, '.');
for (int j = 0; j < N; ++j) {
if (j == C[i]) s[j] = 'Q';
}
solution.push_back(s);
}
result.push_back(solution);
return;
}
for (int j = 0; j < N; ++j) { //
const bool ok = isValid(C, row, j);
if (!ok) continue; //
//
C[row] = j;
dfs(C, result, row + 1);
//
// C[row] = -1;
}
}
/**
*
(row, col)
.
*
* @param C
* @param row
* @param col
* @return
*/
bool isValid(const vector<int> &C, int row, int col) {
(i, C[i])
183
10.4 N-Queens
2
// LeetCode, N-Queens
//
+
//
O(n!)
O(n)
class Solution {
public:
vector<vector<string> > solveNQueens(int n) {
this->columns = vector<bool>(n, false);
this->main_diag = vector<bool>(2 * n - 1, false);
this->anti_diag = vector<bool>(2 * n - 1, false);
vector<vector<string> > result;
vector<int> C(n, -1); // C[i]
dfs(C, result, 0);
return result;
}
private:
//
vector<bool> columns; //
vector<bool> main_diag; //
vector<bool> anti_diag; //
void dfs(vector<int> &C, vector<vector<string> > &result, int row) {
const int N = C.size();
if (row == N) { //
vector<string> solution;
for (int i = 0; i < N; ++i) {
string s(N, '.');
for (int j = 0; j < N; ++j) {
if (j == C[i]) s[j] = 'Q';
}
solution.push_back(s);
}
result.push_back(solution);
return;
}
for (int j = 0; j < N; ++j) { //
const bool ok = !columns[j] && !main_diag[row - j + N - 1]
!anti_diag[row + j];
if (!ok) continue; //
//
&&
184
10
C[row] = j;
columns[j] = main_diag[row - j + N - 1] = anti_diag[row + j] = true;
dfs(C, result, row + 1);
//
// C[row] = -1;
columns[j] = main_diag[row - j + N - 1] = anti_diag[row + j] = false;
}
}
};
N-Queens II
10.5
10.5 N-Queens II
Follow up for N-Queens problem.
Now, instead outputting board configurations, return the total number of distinct solutions.
1
// LeetCode, N-Queens II
//
+
//
O(n!*n)
class Solution {
public:
int totalNQueens(int n) {
this->count = 0;
vector<int> C(n, 0);
dfs(C, 0);
return this->count;
O(n)
// C[i]
}
private:
int count; //
void dfs(vector<int> &C, int row) {
const int N = C.size();
if (row == N) { //
++this->count;
return;
185
10.5 N-Queens II
}
for (int j = 0; j < N; ++j) { //
const bool ok = isValid(C, row, j);
if (!ok) continue; //
//
C[row] = j;
dfs(C, row + 1);
//
// C[row] = -1;
}
}
/**
*
(row, col)
.
*
* @param C
* @param row
* @param col
* @return
*/
bool isValid(const vector<int> &C, int row, int col) {
for (int i = 0; i < row; ++i) {
//
if (C[i] == col) return false;
//
if (abs(i - row) == abs(C[i] - col)) return false;
}
return true;
}
};
2
// LeetCode, N-Queens II
//
+
//
O(n!)
O(n)
class Solution {
public:
int totalNQueens(int n) {
this->count = 0;
this->columns = vector<bool>(n, false);
this->main_diag = vector<bool>(2 * n - 1, false);
this->anti_diag = vector<bool>(2 * n - 1, false);
vector<int> C(n, 0);
dfs(C, 0);
return this->count;
// C[i]
}
private:
int count; //
//
vector<bool> columns; //
vector<bool> main_diag; //
186
10
vector<bool> anti_diag;
//
N-Queens
10.4
187
public:
vector<string> restoreIpAddresses(const string& s) {
vector<string> result;
vector<string> ip; //
dfs(s, ip, result, 0);
return result;
}
/**
* @brief
* @param[in] s
* @param[out] ip
* @param[out] result
IP
* @param[in] start
index
* @return
*/
void dfs(string s, vector<string>& ip, vector<string> &result,
size_t start) {
if (ip.size() == 4 && start == s.size()) { //
int num = 0;
for (size_t i = start; i < start + 3; i++) {
num = num * 10 + (s[i] - '0');
if (num < 0 || num > 255) continue;
//
//
188
10
result.push_back(path);
return;
}
for (size_t i = start; i < nums.size(); i++) { //
if (gap < nums[i]) return; //
path.push_back(nums[i]); //
dfs(nums, path, result, gap - nums[i], i);
path.pop_back(); //
}
189
}
};
Combination Sum II
10.8
7]
2, 5]
6]
1, 6]
190
10
result.push_back(path);
return;
}
int previous = -1;
for (size_t i = start; i < nums.size(); i++) {
//
nums[i]
//
nums[i]
if (previous == nums[i]) continue;
if (gap < nums[i]) return;
nums[i]
//
previous = nums[i];
path.push_back(nums[i]);
dfs(nums, path, result, gap - nums[i], i + 1);
path.pop_back(); //
}
}
};
Combination Sum
10.7
<n
1
// LeetCode, Generate Parentheses
//
O(TODO)
O(n)
class Solution {
191
public:
vector<string> generateParenthesis(int n) {
vector<string> result;
string path;
if (n > 0) generate(n, path, result, 0, 0);
return result;
}
// l
(
, r
)
void generate(int n, string& path, vector<string> &result, int l, int r) {
if (l == n) {
string s(path);
result.push_back(s.append(n - r, ')'));
return;
}
path.push_back('(');
generate(n, path, result, l + 1, r);
path.pop_back();
if (l > r) {
path.push_back(')');
generate(n, path, result, l, r + 1);
path.pop_back();
}
}
};
Valid Parentheses,
4.1.1
192
10
4.1.2
193
Valid Sudoku,
2.1.14
194
10
1, x x + 1,
x, y x, y +
1,
y,
1,
1,
y, visited) || //
visited)
|| //
visited)
|| //
visited);
//
195
10.12
return ret;
}
};
10.12
10.12.1
10.12.2
1.
(a)
path[]
(b)
2.
3.
struct
struct
4.
196
10
5.
0
6.
path[]
7.
(a)
DAG
BFS
BFS
DAG
(b)
9.4
DAG
8
8.
(a)
(b)
i.
DAG
=>
DAG=>
ii.
HashMap
C++
map
HashMap
unordered_map
C++ 11
map
8
197
10.12
10.12.3
dfs_template.cpp
/**
* dfs
.
* @param[in] input
* @param[out] path
* @param[out] result
* @param[inout] cur or gap
* @return
*/
void dfs(type &input, type &path, type &result, int cur or gap) {
if (
) return 0;
//
if (cur == input.size()) { //
// if (gap == 0) {
path
result
}
if (
) return;
for(...) { //
path
dfs(input, step + 1 or gap--, result);
path
}
}
dfs_template.cpp
10.12.4
(Depth-first search, DFS)
http://en.wikipedia.org/wiki/Depth_rst_search
http://en.wikipedia.org/wiki/Backtracking
ing)
=
+
(recursion)
10.12.5
(recursion)
(iteration)
(prunning)
(backtrack-
198
10
memorization
memorization
Donald Michie
??
1968
top-down
(iterative)
memorization
rization
memorization
memorization
memorization
memo-
11
11.1 Pow(x,n)
Implement pow(x, n).
//LeetCode, Pow(x, n)
//
$x^n = x^{n/2} * x^{n/2} * x^{n\%2}$
//
O(logn)
O(1)
class Solution {
public:
double myPow(double x, int n) {
if (n < 0) return 1.0 / power(x, -n);
else return power(x, n);
}
private:
double power(double x, int n) {
if (n == 0) return 1;
double v = power(x, n / 2);
if (n % 2 == 0) return v * v;
else return v * v * x;
}
};
Sqrt(x)
11.2
199
200
11
11.2 Sqrt(x)
Implement int sqrt(int x).
Compute and return the square root of x.
// LeetCode, Sqrt(x)
//
//
O(logn)
O(1)
class Solution {
public:
int mySqrt(int x) {
int left = 1, right = x / 2;
int last_mid; //
mid
if (x < 2) return x;
while(left <= right) {
const int mid = left + (right - left) / 2;
if(x / mid > mid) { //
x > mid * mid
left = mid + 1;
last_mid = mid;
} else if(x / mid < mid) {
right = mid - 1;
} else {
return mid;
}
}
return last_mid;
}
};
Pow(x)
11.1
12
A[i]
0
0
f[i]
1
// LeetCode, Jump Game
//
1
O(n)
O(1)
class Solution {
public:
bool canJump(const vector<int>& nums) {
int reach = 1; //
for (int i = 0; i < reach && reach < nums.size(); ++i)
reach = max(reach, i + 1 + nums[i]);
201
A[i]
202
12
2
// LeetCode, Jump Game
//
2
O(n)
O(1)
class Solution {
public:
bool canJump (const vector<int>& nums) {
if (nums.empty()) return true;
//
int left_most = nums.size() - 1;
for (int i = nums.size() - 2; i >= 0; --i)
if (i + nums[i] >= left_most)
left_most = i;
return left_most == 0;
}
};
3
// LeetCode, Jump Game
//
O(n)
O(n)
class Solution {
public:
bool canJump(const vector<int>& nums) {
vector<int> f(nums.size(), 0);
f[0] = 0;
for (int i = 1; i < nums.size(); i++) {
f[i] = max(f[i - 1], nums[i - 1]) - 1;
if (f[i] < 0) return false;;
}
return f[nums.size() - 1] >= 0;
}
};
Jump Game II
12.2
203
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.)
1
// LeetCode, Jump Game II
//
O(n)
O(1)
class Solution {
public:
int jump(const vector<int>& nums) {
int step = 0; //
int left = 0;
int right = 0; // [left, right]
if (nums.size() == 1) return 0;
while (left <= right) { //
++step;
const int old_right = right;
for (int i = left; i <= old_right; ++i) {
int new_right = i + nums[i];
if (new_right >= nums.size() - 1) return step;
if (new_right > right) right = new_right;
}
left = old_right + 1;
}
return 0;
}
};
2
// LeetCode, Jump Game II
//
O(n)
O(1)
class Solution {
public:
int jump(const vector<int>& nums) {
int result = 0;
// the maximum distance that has been reached
int last = 0;
// the maximum distance that can be reached by using "ret+1" steps
int cur = 0;
204
12
Jump Game
12.1
m=1
205
12.4
13.5
12.3
13.5
m=
206
12
index+1
O(n)
12-1
12-1
-1
207
//
"abcd"
}
};
2.1.15
208
12
4.1.3
13
13.1 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.
f (i, j)
(i, j)
f (i, j) = min {f (i + 1, j), f (i + 1, j + 1)} + (i, j)
// LeetCode, Triangle
//
O(n^2)
O(1)
class Solution {
public:
int minimumTotal (vector<vector<int>>& triangle) {
for (int i = triangle.size() - 2; i >= 0; --i)
for (int j = 0; j < i + 1; ++j)
triangle[i][j] += min(triangle[i + 1][j],
triangle[i + 1][j + 1]);
209
210
13
SubArray
2.
SubArray
SubArray
SubArray
SubArray
SubArray
f[j]
S[j]
f [j]
target
max {f [j]} ,
1jn
1jn
f [j 1] +
S[j]
S[j]
S[j]
S[j]
S[j]
O(n3 )
O(n2 )
O(n log n)
2O(n2 )
M=1
O(n)
M
211
5
// LeetCode, Maximum Subarray
//
O(n)
O(n)
class Solution {
public:
int maxSubArray(vector<int>& A) {
return mcss(A.begin(), A.end());
}
private:
//
5
template <typename Iter>
static int mcss(Iter begin, Iter end) {
int result, cur_min;
const int n = distance(begin, end);
int *sum = new int[n + 1]; //
n
sum[0] = 0;
result = INT_MIN;
cur_min = sum[0];
for (int i = 1; i <= n; i++) {
sum[i] = sum[i - 1] + *(begin + i - 1);
}
for (int i = 1; i <= n; i++) {
result = max(result, sum[i] - cur_min);
cur_min = min(cur_min, sum[i]);
}
delete[] sum;
return result;
}
};
5.4.5
212
13
f(i,j)
[i,j]
cut
DP
f(i)=
[i, n-1]
DP
cut
[i,j]
DP
213
}
return f[0];
}
};
Palindrome Partitioning
10.1
= matrix.size();
= matrix[0].size();
H(n, 0);
L(n, 0);
R(n, n);
int ret = 0;
for (int i = 0; i < m; ++i) {
int left = 0, right = n;
// calculate L(i, j) from left to right
for (int j = 0; j < n; ++j) {
if (matrix[i][j] == '1') {
++H[j];
L[j] = max(L[j], left);
} else {
left = j+1;
H[j] = 0; L[j] = 0; R[j] = n;
}
}
214
13
f (i)
g(i)
https://gist.github.com/soulmachine/5906637
215
12.3
12.4
f[i][j]
s3
s1[0,i]
s2[0,j]
f[i][j]=f[i-1][j]
s3[0, i+j]
s2
f[i][j]=f[i][j-1]
f[i][j] = (s1[i - 1] == s3 [i + j - 1] && f[i - 1][j])
|| (s2[j - 1] == s3 [i + j - 1] && f[i][j - 1]);
s1
s3
216
13
class Solution {
public:
bool isInterleave(const string& s1, const string& s2, const string& s3) {
if (s3.length() != s1.length() + s2.length())
return false;
return isInterleave(begin(s1), end(s1), begin(s2), end(s2),
begin(s3), end(s3));
}
template<typename InIt>
bool isInterleave(InIt first1, InIt last1, InIt first2, InIt last2,
InIt first3, InIt last3) {
if (first3 == last3)
return first1 == last1 && first2 == last2;
return (*first1 == *first3
&& isInterleave(next(first1), last1, first2, last2,
next(first3), last3))
|| (*first2 == *first3
&& isInterleave(first1, last1, next(first2), last2,
next(first3), last3));
}
};
217
+
// LeetCode, Interleaving String
//
+
O(n^2)
O(n)
class Solution {
public:
bool isInterleave(const string& s1, const string& s2, const string& s3) {
if (s1.length() + s2.length() != s3.length())
return false;
if (s1.length() < s2.length())
return isInterleave(s2, s1, s3);
vector<bool> f(s2.length() + 1, true);
for (size_t i = 1; i <= s2.length(); ++i)
f[i] = s2[i - 1] == s3[i - 1] && f[i - 1];
for (size_t i = 1; i <= s1.length(); ++i) {
f[0] = s1[i - 1] == s3[i - 1] && f[0];
for (size_t j = 1; j <= s2.length(); ++j)
f[j] = (s1[i - 1] == s3[i + j - 1] && f[j])
|| (s2[j - 1] == s3[i + j - 1] && f[j - 1]);
}
return f[s2.length()];
}
};
218
13
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.
string
memorization
scamble
false
HashMap
HashMap
s1[i]
s2[j]
scramble
//
O(n^6)
class Solution {
map
f[n][i][j]
O(1)
unordered_map
n
public:
bool isScramble(const string& s1, const string& s2) {
return isScramble(s1.begin(), s1.end(), s2.begin());
}
private:
typedef string::iterator Iterator;
bool isScramble(Iterator first1, Iterator last1, Iterator first2) {
auto length = distance(first1, last1);
auto last2 = next(first2, length);
if (length == 1) return *first1 == *first2;
for (int i = 1; i < length; ++i)
if ((isScramble(first1, first1 + i, first2)
&& isScramble(first1 + i, last1, first2 + i))
|| (isScramble(first1, first1 + i, last2 - i)
&& isScramble(first1 + i, last1, first2)))
return true;
return false;
}
};
219
220
13
}
}
return f[N][0][0];
}
};
+
// LeetCode, Scramble String
//
+
//
O(n^6)
O(1)
class Solution {
public:
bool isScramble(const string& s1, const string& s2) {
return isScramble(s1.begin(), s1.end(), s2.begin());
}
private:
typedef string::const_iterator Iterator;
bool isScramble(Iterator first1, Iterator last1, Iterator first2) {
auto length = distance(first1, last1);
auto last2 = next(first2, length);
if (length == 1) return *first1 == *first2;
//
int A[26]; //
fill(A, A + 26, 0);
for(int i = 0; i < length; i++) A[*(first1+i)-'a']++;
for(int i = 0; i < length; i++) A[*(first2+i)-'a']--;
for(int i = 0; i < 26; i++) if (A[i] != 0) return false;
for (int i = 1; i < length; ++i)
if ((isScramble(first1, first1 + i, first2)
&& isScramble(first1 + i, last1, first2 + i))
|| (isScramble(first1, first1 + i, last2 - i)
&& isScramble(first1 + i, last1, first2)))
return true;
return false;
}
};
221
private:
typedef string::const_iterator Iterator;
map<tuple<Iterator, Iterator, Iterator>, bool> cache;
bool isScramble(Iterator first1, Iterator last1, Iterator first2) {
auto length = distance(first1, last1);
auto last2 = next(first2, length);
if (length == 1) return *first1 == *first2;
for (int i = 1; i < length; ++i)
if ((getOrUpdate(first1, first1 + i, first2)
&& getOrUpdate(first1 + i, last1, first2 + i))
|| (getOrUpdate(first1, first1 + i, last2 - i)
&& getOrUpdate(first1 + i, last1, first2)))
return true;
return false;
}
bool getOrUpdate(Iterator first1, Iterator last1, Iterator first2) {
auto key = make_tuple(first1, last1, first2);
auto pos = cache.find(key);
return (pos != cache.end()) ?
pos->second : (cache[key] = isScramble(first1, last1, first2));
}
};
222
13
public:
unordered_map<Key, bool> cache;
bool isScramble(const string& s1, const string& s2) {
cache.clear();
return isScramble(s1.begin(), s1.end(), s2.begin());
}
bool isScramble(Iterator first1, Iterator last1, Iterator first2) {
auto length = distance(first1, last1);
auto last2 = next(first2, length);
if (length == 1)
return *first1 == *first2;
for (int i = 1; i < length; ++i)
if ((getOrUpdate(first1, first1 + i, first2)
&& getOrUpdate(first1 + i, last1, first2 + i))
|| (getOrUpdate(first1, first1 + i, last2 - i)
&& getOrUpdate(first1 + i, last1, first2)))
return true;
return false;
}
bool getOrUpdate(Iterator first1, Iterator last1, Iterator first2) {
auto key = make_tuple(first1, last1, first2);
auto pos = cache.find(key);
return (pos != cache.end()) ?
pos->second : (cache[key] = isScramble(first1, last1, first2));
}
};
Unique Paths (
10.2)
223
f[i][j]
(0, 0)
(i, j)
f[i][j]=min(f[i-1][j], f[i][j-1])+grid[i][j]
{
grid[i][0];
{
grid[0][i];
224
13
}
for (int i = 1; i < m; i++) {
for (int j = 1; j < n; j++) {
f[i][j] = min(f[i - 1][j], f[i][j - 1]) + grid[i][j];
}
}
return f[m - 1][n - 1];
}
};
+
// LeetCode, Minimum Path Sum
//
+
class Solution {
public:
int minPathSum(vector<vector<int> > &grid) {
const int m = grid.size();
const int n = grid[0].size();
int f[n];
fill(f, f+n, INT_MAX); //
f[0] = 0;
INT_MAX
min
Unique Paths,
Unique Paths II,
10.2
10.3
225
Insert a character
Delete a character
Replace a character
f[i][j]
B[0,j]
A[0,i]
B[0,j]
A[0,i]
str2d
1.
c==d
2.
c!=d
f[i][j]=f[i-1][j-1]
(a)
(b)
(c)
f[i][j]=f[i-1][j-1]+1
d
f[i][j]=f[i][j-1]+1
f[i][j]=f[i-1][j]+1
str1c
226
13
+
// LeetCode, Edit Distance
//
+
//
O(n*m)
O(n)
class Solution {
public:
int minDistance(const string &word1, const string &word2) {
if (word1.length() < word2.length())
return minDistance(word2, word1);
int f[word2.length() + 1];
int upper_left = 0; //
f[i-1][j-1]
227
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.
Climbing Stairs (
2.1.18)
Climbing Stairs,
2.1.18
228
13
T[0,j]
f (i, j)
S[i]
S[0,i]
f (i, j) = f (i 1, j)
S[i]
S[i]==T[j]
S[i]
T[j]
f (i, j) =
f (i 1, j) + f (i 1, j 1)
229
f (i)
s[0,i]
f (i) = any_of (f (j)&&s[j + 1, i] dict), 0 j < i
230
13
13.13
231
private:
// DFS
void gen_path(const string &s, const vector<vector<bool> > &prev,
int cur, vector<string> &path, vector<string> &result) {
if (cur == 0) {
string tmp;
for (auto iter = path.crbegin(); iter != path.crend(); ++iter)
tmp += *iter + " ";
tmp.erase(tmp.end() - 1);
result.push_back(tmp);
}
for (size_t i = 0; i < s.size(); ++i) {
if (prev[cur][i]) {
path.push_back(s.substr(i, cur - i));
gen_path(s, prev, i, path, result);
path.pop_back();
}
}
}
};
Word Break,
13.12
14
//
struct UndirectedGraphNode {
int label;
vector<UndirectedGraphNode *> neighbors;
UndirectedGraphNode(int x) : label(x) {};
};
232
DFS
// LeetCode, Clone Graph
// DFS
O(n)
O(n)
class Solution {
public:
UndirectedGraphNode *cloneGraph(const UndirectedGraphNode *node) {
if(node == nullptr) return nullptr;
// key is original node value is copied node
unordered_map<const UndirectedGraphNode *,
UndirectedGraphNode *> copied;
clone(node, copied);
return copied[node];
}
private:
// DFS
static UndirectedGraphNode* clone(const UndirectedGraphNode *node,
unordered_map<const UndirectedGraphNode *,
UndirectedGraphNode *> &copied) {
// a copy already exists
if (copied.find(node) != copied.end()) return copied[node];
UndirectedGraphNode *new_node = new UndirectedGraphNode(node->label);
copied[node] = new_node;
for (auto nbr : node->neighbors)
new_node->neighbors.push_back(clone(nbr, copied));
return new_node;
}
};
BFS
// LeetCode, Clone Graph
// BFS
O(n)
O(n)
class Solution {
public:
UndirectedGraphNode *cloneGraph(const UndirectedGraphNode *node) {
if (node == nullptr) return nullptr;
// key is original node value is copied node
unordered_map<const UndirectedGraphNode *,
UndirectedGraphNode *> copied;
// each node in queue is already copied itself
// but neighbors are not copied yet
queue<const UndirectedGraphNode *> q;
q.push(node);
copied[node] = new UndirectedGraphNode(node->label);
while (!q.empty()) {
const UndirectedGraphNode *cur = q.front();
q.pop();
for (auto nbr : cur->neighbors) {
// a copy already exists
if (copied.find(nbr) != copied.end()) {
copied[cur]->neighbors.push_back(copied[nbr]);
233
234
14
} else {
UndirectedGraphNode *new_node =
new UndirectedGraphNode(nbr->label);
copied[nbr] = new_node;
copied[cur]->neighbors.push_back(new_node);
q.push(nbr);
}
}
}
return copied[node];
}
};
15
O(1)
(
&&
235
x = -2147483648(
-2^31) )
236
15
for (; t; t /= 10)
r = r * 10 + t % 10;
bool sign = x > 0 ? false: true;
if (r > 2147483647 || (sign && r > 2147483648)) {
return 0;
} else {
if (sign) {
return -r;
} else {
return r;
}
}
}
};
Palindrome Number,
15.2
Palindrome
reverse()
10
237
bool isPalindrome(int x) {
if (x < 0) return false;
int d = 1; // divisor
while (x / d >= 10) d *= 10;
while (x > 0) {
int q = x /
int r = x %
if (q != r)
x = x % d /
d /= 100;
}
return true;
d; // quotient
10;
// remainder
return false;
10;
}
};
Reverse Integer,
Valid Palindrome,
15.1
3.1
[1,2],[3,10],[12,16].
This is because the new interval [4,9] overlaps with [3,5],[6,7],[8,10].
struct Interval {
int start;
int end;
Interval() : start(0), end(0) { }
Interval(int s, int e) : start(s), end(e) { }
};
//LeetCode, Insert Interval
238
15
//
O(n)
O(1)
class Solution {
public:
vector<Interval> insert(vector<Interval> &intervals, Interval newInterval) {
vector<Interval>::iterator it = intervals.begin();
while (it != intervals.end()) {
if (newInterval.end < it->start) {
intervals.insert(it, newInterval);
return intervals;
} else if (newInterval.start > it->end) {
it++;
continue;
} else {
newInterval.start = min(newInterval.start, it->start);
newInterval.end = max(newInterval.end, it->end);
it = intervals.erase(it);
}
}
intervals.insert(intervals.end(), newInterval);
return intervals;
}
};
Merge Intervals
15.4
Insert Intervals
interval
interval
struct Interval {
int start;
int end;
Interval() : start(0), end(0) { }
Interval(int s, int e) : start(s), end(e) { }
};
239
//
O(n1+n2+...)
O(1)
class Solution {
public:
vector<Interval> merge(vector<Interval> &intervals) {
vector<Interval> result;
for (int i = 0; i < intervals.size(); i++) {
insert(result, intervals[i]);
}
return result;
}
private:
vector<Interval> insert(vector<Interval> &intervals, Interval newInterval) {
vector<Interval>::iterator it = intervals.begin();
while (it != intervals.end()) {
if (newInterval.end < it->start) {
intervals.insert(it, newInterval);
return intervals;
} else if (newInterval.start > it->end) {
it++;
continue;
} else {
newInterval.start = min(newInterval.start, it->start);
newInterval.end = max(newInterval.end, it->end);
it = intervals.erase(it);
}
}
intervals.insert(intervals.end(), newInterval);
return intervals;
}
};
Insert Interval
15.3
240
15
If there are multiple such windows, you are guaranteed that there will always be only one unique
minimum window in S.
//
}
if (minWidth == INT_MAX) return "";
241
int
2
int32
4
31
int
1 = 2147483647
int64
1
// LeetCode, Multiply Strings
// @author
(http://weibo.com/lianchengzju)
//
int
//
O(n*m)
O(n+m)
typedef vector<int> bigint;
bigint make_bigint(string const& repr) {
bigint n;
transform(repr.rbegin(), repr.rend(), back_inserter(n),
[](char c) { return c - '0'; });
return n;
}
string to_string(bigint const& n)
string str;
transform(find_if(n.rbegin(),
[](char c) { return c
[](char c) { return c
return str;
}
{
prev(n.rend()),
> '\0'; }), n.rend(), back_inserter(str),
+ '0'; });
242
15
2
// LeetCode, Multiply Strings
// 9
int64_t
//
O(n*m/81)
O((n+m)/9)
/**
. */
class BigInt {
public:
/**
* @brief
.
* @param[in] s
* @return
*/
BigInt(string s) {
vector<int64_t> result;
result.reserve(s.size() / RADIX_LEN + 1);
for (int i = s.size(); i > 0; i -= RADIX_LEN) {
int temp = 0;
const int low = max(i - RADIX_LEN, 0);
for (int j = low; j < i; j++) {
temp = temp * 10 + s[j] - '0';
}
result.push_back(temp);
}
elems = result;
// [i-RADIX_LEN, i)
}
/**
* @brief
.
* @return
*/
string toString() {
stringstream result;
bool started = false; //
0
for (auto i = elems.rbegin(); i != elems.rend(); i++) {
243
if (started) { //
0
result << setw(RADIX_LEN) << setfill('0') << *i;
} else {
result << *i;
started = true; //
0
}
}
if (!started) return "0"; //
else return result.str();
}
/**
* @brief
.
* @param[in] x x
* @param[in] y y
* @return
*/
static BigInt multiply(const BigInt &x, const BigInt &y) {
vector<int64_t> z(x.elems.size() + y.elems.size(), 0);
for (size_t i = 0; i < y.elems.size(); i++) {
for (size_t j = 0; j < x.elems.size(); j++) { //
//
i, j
i+j
z[i + j] += y.elems[i] * x.elems[j];
y[i]
//
}
private:
typedef long long int64_t;
/**
9
*
1000000000 * 1000000000
2^63-1
*/
const static int BIGINT_RADIX = 1000000000;
const static int RADIX_LEN = 9;
/**
. */
vector<int64_t> elems;
BigInt(const vector<int64_t> num) : elems(num) {}
};
class Solution {
public:
string multiply(string num1, string num2) {
BigInt x(num1);
244
15
BigInt y(num2);
return BigInt::multiply(x, y).toString();
}
};
245
0
1
246
15
//
Pascals Triangle II
15.9
247
Pascals Triangle
15.8
248
15
Spiral Matrix II
15.11
249
1
// LeetCode, Spiral Matrix II
//
O(n^2)
O(n^2)
class Solution {
public:
vector<vector<int> > generateMatrix(int n) {
vector<vector<int> > matrix(n, vector<int>(n));
int begin = 0, end = n - 1;
int num = 1;
while (begin
for (int
for (int
for (int
for (int
++begin;
--end;
}
<
j
i
j
i
end) {
= begin;
= begin;
= end; j
= end; i
j
i
>
>
< end;
< end;
begin;
begin;
++j)
++i)
--j)
--i)
matrix[begin][j]
matrix[i][end] =
matrix[end][j] =
matrix[i][begin]
= num++;
num++;
num++;
= num++;
2
// LeetCode, Spiral Matrix II
// @author
(http://weibo.com/luangong)
//
O(n^2)
O(n^2)
class Solution {
public:
vector<vector<int> > generateMatrix(int n) {
vector< vector<int> > matrix(n, vector<int>(n));
if (n == 0) return matrix;
int beginX = 0, endX = n - 1;
int beginY = 0, endY = n - 1;
int num = 1;
while (true) {
for (int j = beginX; j <= endX; ++j) matrix[beginY][j] = num++;
if (++beginY > endY) break;
for (int i = beginY; i <= endY; ++i) matrix[i][endX] = num++;
if (beginX > --endX) break;
for (int j = endX; j >= beginX; --j) matrix[endY][j] = num++;
if (beginY > --endY) break;
250
15
Spiral Matrix,
15.10
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
A
N
G
(i, j) = (j + 1) n + i
(i, j) = (j + 1) n i
1
// LeetCode, Divide Two Integers
//
O(logn)
O(1)
class Solution {
public:
int divide(int dividend, int divisor) {
//
dividend = INT_MIN
-dividend
long long
long long a = dividend >= 0 ? dividend : -(long long)dividend;
long long b = divisor >= 0 ? divisor : -(long long)divisor;
251
252
15
//
dividend = INT_MIN
divisor = -1
long long result = 0;
while (a >= b) {
long long c = b;
for (int i = 0; a >= c; ++i, c <<= 1) {
a -= c;
result += 1 << i;
}
}
long long
2
// LeetCode, Divide Two Integers
//
O(logn)
O(1)
class Solution {
public:
int divide(int dividend, int divisor) {
int result = 0; //
dividend = INT_MIN
divisor = -1
const bool sign = (dividend > 0 && divisor < 0) ||
(dividend < 0 && divisor > 0); //
//
dividend = INT_MIN
-dividend
unsigned int
unsigned int a = dividend >= 0 ? dividend : -dividend;
unsigned int b = divisor >= 0 ? divisor : -divisor;
while (a >= b) {
int multi = 1;
unsigned int bb = b;
while (a >= bb) {
a -= bb;
result += multi;
if (bb < INT_MAX >> 1) { //
bb += bb;
multi += multi;
}
}
}
if (sign) return -result;
else return result;
}
};
253
254
15
begin = i;
len = 0;
}
len += words[i].size();
}
//
L
result.push_back(connect(words, begin, n - 1, len, L, true));
return result;
}
/**
* @brief
words[begin, end]
* @param[in] words
* @param[in] begin
* @param[in] end
* @param[in] len words[begin, end]
* @param[in] L
* @param[in] is_last
* @return
*/
string connect(vector<string> &words, int begin, int end,
int len, int L, bool is_last) {
string s;
int n = end - begin + 1;
for (int i = 0; i < n; ++i) {
s += words[begin + i];
addSpaces(s, i, n - 1, L - len, is_last);
}
if (s.size() < L) s.append(L - s.size(), ' ');
return s;
}
/**
* @brief
.
* @param[inout]s
* @param[in] i
* @param[in] n
* @param[in] L
* @param[in] is_last
* @return
*/
void addSpaces(string &s, int i, int n, int L, bool is_last) {
if (n < 1 || i > n - 1) return;
int spaces = is_last ? 1 : (L / n + (i < (L % n) ? 1 : 0));
s.append(spaces, ' ');
}
};
255
1
n(n + 1)
2
n
O(n3 )
key
O(n2 )
value
O(n)
O(1)
256
15