Leetcode CPP PDF
Leetcode CPP PDF
(soulmachine@gmail.com)
https://github.com/soulmachine/leetcode
2016-1-28
ACM
LeetCode Online Judge(http://leetcode.com/onlinejudge) 题
• OJ
.h .cpp
• Shorter is better STL
• malloc()/new nullptr
¬
C++ Java
GitHub
GitHub https://github.com/soulmachine/leetcode
http://q.weibo.com/1312378
¬ http://book.douban.com/subject/2024655/
Algorithms Robert Sedgewick, Addison-Wesley Professional, http://book.douban.com/subject/4854123/
i
1 1 2.1.20 Set Matrix Zeroes . . . . 33
2.1.21 Gas Station . . . . . . . 35
2 2
2.1.22 Candy . . . . . . . . . . 36
2.1 . . . . . . . . . . . . . . . 2
2.1.23 Single Number . . . . . 37
2.1.1 Remove Duplicates
2.1.24 Single Number II . . . . 38
from Sorted Array . . . 2
2.2 . . . . . . . . . . . . . 40
2.1.2 Remove Duplicates
2.2.1 Add Two Numbers . . . 40
from Sorted Array II . . 3
2.2.2 Reverse Linked List II . 41
2.1.3 Search in Rotated
2.2.3 Partition List . . . . . . 42
Sorted Array . . . . . . 5
2.2.4 Remove Duplicates
2.1.4 Search in Rotated
from Sorted List . . . . 43
Sorted Array II . . . . . 6
2.2.5 Remove Duplicates
2.1.5 Median of Two Sorted
from Sorted List II . . . 44
Arrays . . . . . . . . . . 7
2.2.6 Rotate List . . . . . . . 46
2.1.6 Longest Consecutive
2.2.7 Remove Nth Node
Sequence . . . . . . . . 8
From End of List . . . . 47
2.1.7 Two Sum . . . . . . . . 10
2.2.8 Swap Nodes in Pairs . . 47
2.1.8 3Sum . . . . . . . . . . 12
2.2.9 Reverse Nodes in k-Group 49
2.1.9 3Sum Closest . . . . . . 13
2.2.10 Copy List with Random
2.1.10 4Sum . . . . . . . . . . 14
Pointer . . . . . . . . . 50
2.1.11 Remove Element . . . . 18
2.2.11 Linked List Cycle . . . . 51
2.1.12 Next Permutation . . . . 19
2.2.12 Linked List Cycle II . . 52
2.1.13 Permutation Sequence . 21
2.2.13 Reorder List . . . . . . 53
2.1.14 Valid Sudoku . . . . . . 23
2.2.14 LRU Cache . . . . . . . 55
2.1.15 Trapping Rain Water . . 24
2.1.16 Rotate Image . . . . . . 27 3 57
2.1.17 Plus One . . . . . . . . 28 3.1 Valid Palindrome . . . . . . . . 57
2.1.18 Climbing Stairs . . . . . 30 3.2 Implement strStr() . . . . . . . . 58
2.1.19 Gray Code . . . . . . . 31 3.3 String to Integer (atoi) . . . . . 60
ii
iii
12.6 Container With Most Water . . . 207 15.10 Spiral Matrix . . . . . . . . . . 247
15.11 Spiral Matrix II . . . . . . . . . 248
13 209 15.12 ZigZag Conversion . . . . . . 250
13.1 Triangle . . . . . . . . . . . . . 209 15.13 Divide Two Integers . . . . . . 251
13.2 Maximum Subarray . . . . . . . 210 15.14 Text Justification . . . . . . . . 253
13.3 Palindrome Partitioning II . . . 212 15.15 Max Points on a Line . . . . . 255
vi
1
a b a==b
fabs(a-b) 1e-9
x % 2 != 0 x % 2 == 1 x
char
char unsigned int
unsigned char C++
vector string
vector
vector
vector<vector<int> > ary(row_num, vector<int>(col_num, 0));
reserve
1
2
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
2.1 3
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()));
}
};
3
// LeetCode, Remove Duplicates from Sorted Array
// STL O(n) O(1)
class Solution {
public:
int removeDuplicates(vector<int>& nums) {
return distance(nums.begin(), removeDuplicates(nums.begin(), nums.end(), nums.begin())
}
return output;
}
};
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
4 2
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;
}
};
nums[index++] = nums[i];
}
return index;
}
};
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] [l,m]
• A[m]==A[l] l++
题
• Search in Rotated Sorted Array §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)).
题 题
k
O(m + n) 解 merge k
k
m pA pB A B
merge sort A pA++ m++
B pB++ m++ m k O(k)
O(1) k m+n O(m + n)
k k
k A B
• 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]
8 2
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 9
int longest = 0;
int length = 1;
used[i] = true;
return longest;
}
};
, union,find .
. , , . unordered_-
map<int, int> map . http://discuss.leetcode.com/questions/1070/
10 2
longest-consecutive-sequence
private:
int mergeCluster(unordered_map<int, int> &map, int left, int right) {
int upper = right + map[right] - 1;
int lower = left - map[left] + 1;
int length = upper - lower + 1;
map[upper] = length;
map[lower] = length;
return length;
}
};
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.
2.1 11
You may assume that each input would have exactly one solution.
Input: numbers={2, 7, 11, 15}, target=9
Output: index1=1, index2=2
1 O(n2 )
2 hash O(n).
3 O(n log n) O(n) O(n log n)
题
• 3Sum, §2.1.8
• 3Sum Closest, §2.1.9
• 4Sum, §2.1.10
12 2
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 k−2
O(max{n log n, n k−1
})
// LeetCode, 3Sum
// O(n^2) O(1)
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;
--k;
while(*j == *(j - 1) && *k == *(k + 1) && j < k) ++j;
}
}
}
return result;
}
};
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 )
sort(nums.begin(), nums.end());
while (b < c) {
const int sum = *a + *b + *c;
const int gap = abs(sum - target);
14 2
return result;
}
};
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
2.1 15
// 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());
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());
result.push_back( { nums[vec[k].first],
nums[vec[k].second], nums[c], nums[d] });
}
}
}
sort(result.begin(), result.end());
result.erase(unique(result.begin(), result.end()), result.end());
return result;
}
};
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());
}
}
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());
Given an array and a value, remove all instances of that value in place and return the new length.
The order of elements can be changed. It doesn’t matter what you leave beyond the new length.
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));
}
};
•
2.1 19
Implement next permutation, which rearranges numbers into the lexicographically next greater permu-
tation of numbers.
If such arrangement is not possible, it must rearrange it as the lowest possible order (ie, sorted in ascend-
ing 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://fisherlei.blogspot.com/2012/12/leetcode-next-permutation.html
2-1
20 2
template<typename BidiIt>
bool next_permutation(BidiIt first, BidiIt last) {
// Get a reversed range to simplify reversed traversal.
const auto rfirst = reverse_iterator<BidiIt>(last);
const auto rlast = reverse_iterator<BidiIt>(first);
// Find `pivot`, which is the first element that is no less than its
// successor. `Prev` is used since `pivort` is a `reversed_iterator`.
while (pivot != rlast && *pivot >= *prev(pivot))
++pivot;
// Scan from right to left, find the first element that is greater than
// `pivot`.
auto change = find_if(rfirst, pivot, bind1st(less<int>(), *pivot));
swap(*change, *pivot);
reverse(rfirst, pivot);
return true;
}
};
k−1 next_permutation()
k k
n k a1 , a2 , a3 , ..., an a1
k2 = k%(n − 1)!
a2 = k2 /(n − 2)!
···
kn−1 = kn−2 %2!
an−1 = kn−1 /1!
an = 0
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)
22 2
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
}
};
// seq
template<typename Sequence>
Sequence kth_permutation(const Sequence &seq, int k) {
const int n = seq.size();
Sequence S(seq);
Sequence result;
result.push_back(S[0]); //
return result;
}
2.1 23
};
return true;
}
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.
2.1 25
min(max_left, max_-
right) - height
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]();
int sum = 0;
for (int i = 0; i < n; i++) {
26 2
delete[] max_left;
delete[] max_right;
return sum;
}
};
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;
}
};
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;
s.push(make_pair(A[i], i));
}
return water;
}
};
题
• Container With Most Water, §12.6
• Largest Rectangle in Histogram, §4.1.3
1
// LeetCode, Rotate Image
// 1 O(n^2) O(1)
class Solution {
public:
void rotate(vector<vector<int>>& matrix) {
const int n = matrix.size();
2
// LeetCode, Rotate Image
// 2 O(n^2) O(1)
class Solution {
public:
void rotate(vector<vector<int>>& matrix) {
const int n = matrix.size();
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,
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,
}
};
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) n n
• n−1 1
• n−1 2
f (n) = f (n − 1) + f (n − 2)
1 2 [( √ )n ( √ )n ]
1 1+ 5 1− 5
3 an = √ −
5 2 2
The gray code is a binary numeral system where two successive values differ in only one bit.
Given a non-negative integer n representing the total number of bits in the code, print the sequence of
gray code. A gray code sequence must begin with 0.
For example, given n = 2, return [0,1,3,2]. Its gray code sequence is:
00 - 0
01 - 1
11 - 3
10 - 2
Note:
• For a given n, a gray code sequence is not uniquely defined.
• For example, [0,2,3,1] is also a valid gray code sequence according to the above definition.
• For now, the judge is able to judge based on one instance of gray code sequence. Sorry about that.
1001
1 1 2 0 1 2 2 0 3
0 0 3 3 0 4 1 1
4 1101
b0 = g0 , bi = gi ⊕ bi−1
32 2
1000
1 1 1 2 0
1 2 2 1 3 0 1
3 3 1 4 0 1
4 1111
n n ⊕ (n/2)
题 n
1 0 ∼ 2n − 1
2 n n−1 §2-5
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 0
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 2
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; // 0
bool col_has_zero = false; // 0
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 station’s 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 total
解 sum -1
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;
}
// 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>& f, int i) {
if (f[i] == 0) {
f[i] = 1;
if (i > 0 && ratings[i] > ratings[i - 1])
f[i] = max(f[i], solve(ratings, f, i - 1) + 1);
if (i < ratings.size() - 1 && ratings[i] > ratings[i + 1])
f[i] = max(f[i], solve(ratings, f, i + 1) + 1);
}
return f[i];
}
};
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 2
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>());
}
};
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[sizeof(int)] count[i] i
1 count[i] 3
2.1 39
2 one 1 1 mod 3 1
two 1 2 mod 3 2
one two 1 1 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; // bit
int count[W]; // count[i] i 1
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;
}
};
40 2
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
题 15 bug free
prev = head2->next;
ListNode *cur = prev->next;
for (int i = m; i < n; ++i) {
prev->next = cur->next;
cur->next = head2->next;
head2->next = cur; //
cur = prev->next;
}
42 2
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.
left_cur->next = right_dummy.next;
right_cur->next = nullptr;
2.2 43
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.
recur(&dummy, head);
return dummy.next;
}
private:
static void recur(ListNode *prev, ListNode *cur) {
if (cur == nullptr) return;
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.
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;
}
}
};
ListNode dummy(INT_MIN); //
dummy.next = head;
ListNode *prev = &dummy, *cur = head;
while (cur != nullptr) {
bool duplicated = false;
while (cur->next != nullptr && cur->val == cur->next->val) {
duplicated = true;
ListNode *temp = cur;
cur = cur->next;
delete temp;
}
if (duplicated) { //
ListNode *temp = cur;
cur = cur->next;
delete temp;
continue;
}
prev->next = cur;
prev = prev->next;
cur = cur->next;
}
prev->next = cur;
return dummy.next;
}
};
46 2
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.
int len = 1;
ListNode* p = head;
while (p->next) { //
len++;
p = p->next;
}
k = len - k % len;
p->next = head; //
for(int step = 0; step < k; step++) {
p = p->next; //
}
head = p->next; //
p->next = nullptr; //
return head;
}
};
•
2.2 47
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 n p q q p->next
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.
48 2
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.
题
// LeetCode, Swap Nodes in Pairs
// O(n) O(1)
class Solution {
public:
ListNode* swapPairs(ListNode* head) {
ListNode* p = head;
return head;
}
};
题
• Reverse Nodes in k-Group, §2.2.9
2.2 49
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
return dummy.next;
}
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.
2.2 51
//
RandomListNode dummy(-1);
for (RandomListNode* cur = head, *new_cur = &dummy;
cur != nullptr; ) {
new_cur->next = cur->next;
new_cur = new_cur->next;
cur->next = cur->next->next;
cur = cur->next;
}
return dummy.next;
}
};
http://leetcode.com/2010/09/detecting-loop-in-singly-linked-list.html
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?
2s = s + nr
s = nr
2.2 53
L a x
L–x–a n−1 +
head slow2
题 in-place O(1)
reverse
slow = reverse(slow);
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
// map
cacheList.splice(cacheList.begin(), cacheList, cacheMap[key]);
cacheMap[key] = cacheList.begin();
return cacheMap[key]->value;
}
•
3
Given a string, determine if it is a palindrome, considering only alphanumeric characters and ignoring
cases.
For example,
"A man, a plan, a canal: Panama" is a palindrome.
"race a car" is not a palindrome.
Note: Have you consider that the string might be empty? This is a good question to ask during an
interview.
For the purpose of this problem, we define empty string as valid palindrome.
57
58 3
Implement strStr().
Returns a pointer to the first occurrence of needle in haystack, or null if needle is not part of haystack.
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());
}
3.2 Implement strStr() 59
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];
/*
* @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);
free(next);
return -1;
}
60 3
};
1. ”-3924x8fc” ” + 413”,
2. ” ++c”, ” ++1”
3. ”2147483648”
public:
int myAtoi(const string &str) {
int num = 0;
int sign = 1;
const int n = str.length();
int i = 0;
if (str[i] == '+') {
i++;
} else if (str[i] == '-') {
sign = -1;
i++;
}
Given two binary strings, return their sum (also a binary string).
For example,
a = "11"
b = "1"
Return "100".
62 3
Given a string S, find the longest palindromic substring in S. You may assume that the maximum length
of S is 1000, and there exists one unique longest palindromic substring.
题
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])
3.5 Longest Palindromic Substring 63
true ,i = j
f (i, j) = S[i] = S[j] ,j = i + 1
S[i] = S[j] and f (i + 1, j − 1) ,j > i + 1
Manacher s Algorithm, O(n) 解 http://leetcode.com/2011/11/longest-
palindromic-substring-part-ii.html
namespace std {
template<>
struct hash<pair<Iterator, Iterator>> {
size_t operator()(pair<Iterator, Iterator> const& p) const {
return ((size_t) &(*p.first)) ^ ((size_t) &(*p.second));
}
};
}
class Solution {
public:
string longestPalindrome(string const& s) {
cache.clear();
return cachedLongestPalindrome(s.begin(), s.end());
}
private:
unordered_map<pair<Iterator, Iterator>, string> cache;
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();
3.5 Longest Palindromic Substring 65
if (n == 0) return "^$";
ret += "#$";
return ret;
}
string longestPalindrome(string s) {
string T = preProcess(s);
const int n = T.length();
// T[i] / T[i]
// P[i]
int P[n];
int C = 0, R = 0;
•
66 3
Implement regular expression matching with support for '.' and '*'.
'.' Matches any single character. '*' Matches zero or more of the preceding element.
The matching should cover the entire input string (not partial).
The function prototype should be:
bool isMatch(const char *s, const char *p)
Some examples:
isMatch("aa","a") → false
isMatch("aa","aa") → true
isMatch("aaa","aa") → false
isMatch("aa", "a*") → true
isMatch("aa", ".*") → true
isMatch("ab", ".*") → true
isMatch("aab", "c*a*b") → true
}
}
};
Implement wildcard pattern matching with support for '?' and '*'.
'?' Matches any single character. '*' Matches any sequence of characters (including the empty se-
quence).
The matching should cover the entire input string (not partial).
The function prototype should be:
bool isMatch(const char *s, const char *p)
Some examples:
isMatch("aa","a") → false
isMatch("aa","aa") → true
isMatch("aaa","aa") → false
isMatch("aa", "*") → true
isMatch("aa", "a*") → true
isMatch("ab", "?*") → true
isMatch("aab", "c*a*b") → false
题
'*' 题 p '*' '*' s s
s++
return *s != '\0';
}
else if (*p == '\0' || *s == '\0') return *p == *s;
else if (*p == *s || *p == '?') return isMatch(++s, ++p);
else return false;
}
};
Write a function to find the longest common prefix string amongst an array of strings.
Note: It is intended for the problem statement to be ambiguous. You should gather all requirements up
front before implementing one.
题
题 strtod()
SIGN, // 2
DIGIT, // 3
DOT, // 4
EXPONENT, // 5
NUM_INPUTS // 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;
// 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 3
return isNumber(s.c_str());
}
private:
bool isNumber (char const* s) {
char* endptr;
strtod (s, &endptr);
return true;
}
};
string roman;
for (size_t i = 0; num > 0; ++i) {
int count = num / radix[i];
num %= radix[i];
for (; count > 0; --count) roman += symbol[i];
3.11 Roman to Integer 73
}
return roman;
}
};
IV = 5 – 1
VI = 5 + 1, II=1+1
result += map(s[i]);
}
}
return result;
}
};
while (--n)
s = getNext(s);
return s;
}
return ss.str();
}
};
3.13 Anagrams
Given an array of strings, return all groups of strings that are anagrams.
Note: All inputs will be in lower-case.
Anagram "dormitory"
"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 3
return result;
}
};
Corner Cases:
• Did you consider the case where path = "/../"? In this case, you should return "/".
• Another corner case is the path might contain multiple slashes '/' together, such as "/home//foo/".
In this case, you should ignore redundant slashes and return "/home/foo".
} else
dirs.push_back(dir);
}
i = j;
}
stringstream out;
if (dirs.empty()) {
out << "/";
} else {
for (auto dir : dirs)
out << '/' << dir;
}
return out.str();
}
};
Given a string s consists of upper/lower-case alphabets and empty space characters ' ', return the length
of last word in the string.
If the last word does not exist, return 0.
Note: A word is defined as a character sequence consists of non-space characters only.
For example, Given s = "Hello World", return 5.
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 3
•
4
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.
for (auto c : s) {
if (left.find(c) != string::npos) {
stk.push (c);
} else {
if (stk.empty () || stk.top () != left[right.find (c)])
return false;
else
stk.pop ();
}
}
79
80 4
return stk.empty();
}
};
Given a string containing just the characters '(' and ')', find the length of the longest valid (well-
formed) 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.
}
}
}
}
return max_len;
}
};
}
}
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;
}
};
Given n non-negative integers representing the histogram’s bar height where the width of each bar is 1,
find the area of largest rectangle in the histogram.
4-1 Above is a histogram where width of each bar is 1, given height = [2,1,5,6,2,3].
4.1 83
4-2 The largest rectangle is shown in the shaded area, which has area = 10 unit.
}
};
题
• Trapping Rain Water, §2.1.15
• Container With Most Water, §12.6
4.2
5
LeetCode
//
struct TreeNode {
int val;
TreeNode *left;
TreeNode *right;
TreeNode(int x) : val(x), left(nullptr), right(nullptr) { }
};
5.1
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
5.1 87
Morris
while (!s.empty()) {
const TreeNode *p = s.top();
s.pop();
result.push_back(p->val);
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;
if (node->right == nullptr) { /* */
result.push_back(cur->val); /* */
node->right = cur;
prev = cur; /* cur */
88 5
cur = cur->left;
} else { /* */
node->right = nullptr;
/* prev = cur; cur */
cur = cur->right;
}
}
}
return result;
}
};
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
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;
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
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
do {
while (p != nullptr) { /* */
s.push(p);
p = p->left;
}
q = nullptr;
while (!s.empty()) {
p = s.top();
s.pop();
/* */
if (p->right == q) {
5.1 91
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 5
}
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);
}
};
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},
5.1 93
3
/ \
9 20
/ \
15 7
result[level-1].push_back(root->val);
traverse(root->left, level+1, result);
traverse(root->right, level+1, result);
}
};
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;
}
};
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
题 §5.1.4 reverse()
result[level-1].push_back(root->val);
traverse(root->left, level+1, result);
traverse(root->right, level+1, result);
}
};
current.push(root);
while (!current.empty()) {
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);
96 5
level.clear();
swap(next, current);
}
reverse(result.begin(), result.end()); // 题
return result;
}
};
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
bool
if (left_to_right)
result[level-1].push_back(root->val);
else
result[level-1].insert(result[level-1].begin(), root->val);
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);
}
if (!left_to_right) reverse(level.begin(), level.end());
result.push_back(level);
left_to_right = !left_to_right;
swap(next, current);
}
return result;
}
98 5
};
O(n) 解
O(n) Morris
if (node->right == nullptr) {
node->right = cur;
//prev = cur; cur
5.1 99
cur = cur->left;
} else {
detect(broken, prev, cur);
node->right = nullptr;
prev = cur;
cur = cur->right;
}
}
}
swap(broken.first->val, broken.second->val);
}
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.
while(!s.empty()) {
p = s.top(); s.pop();
q = s.top(); s.pop();
s.push(p->left);
s.push(q->left);
s.push(p->right);
s.push(q->right);
}
return true;
}
};
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.
5.1 101
stack<TreeNode*> s;
s.push(root->left);
s.push(root->right);
s.push(p->left);
s.push(q->right);
s.push(p->right);
s.push(q->left);
}
return true;
102 5
}
};
/**
* Returns the height of `root` if `root` is a balanced tree,
* otherwise, returns `-1`.
*/
int balancedHeight (TreeNode* root) {
if (root == nullptr) return 0; //
•
5.1 103
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);
// root root->right
TreeNode *p = root->left;
while(p->right) p = p->right; //
p->right = root->right;
root->right = root->left;
root->left = nullptr;
}
};
104 5
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;
stack<TreeNode*> s;
s.push(root);
while (!s.empty()) {
auto p = s.top();
s.pop();
if (p->right)
s.push(p->right);
if (p->left)
s.push(p->left);
p->left = nullptr;
if (!s.empty())
p->right = s.top();
}
}
};
5.1 105
题
•
TreeLinkNode dummy(-1);
for (TreeLinkNode *curr = root, *prev = &dummy;
curr; curr = curr->next) {
if (curr->left != nullptr){
prev->next = curr->left;
prev = prev->next;
}
if (curr->right != nullptr){
106 5
prev->next = curr->right;
prev = prev->next;
}
}
connect(dummy.next);
}
};
if (root->left) {
if (prev) prev->next = root->left;
prev = root->left;
}
if (root->right) {
if (prev) prev->next = root->right;
prev = root->right;
}
}
root = next; // turn to next level
}
}
};
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.
5.2 107
template<typename InputIterator>
TreeNode* buildTree(InputIterator pre_first, InputIterator pre_last,
InputIterator in_first, InputIterator in_last) {
if (pre_first == pre_last) return nullptr;
if (in_first == in_last) return nullptr;
return root;
}
};
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
template<typename BidiIt>
TreeNode* buildTree(BidiIt in_first, BidiIt in_last,
BidiIt post_first, BidiIt post_last) {
if (in_first ==in_last) return nullptr;
if (post_first == post_last) return nullptr;
return root;
}
};
5.3
5.3.1 Unique Binary Search Trees
Given n, how many structurally unique BST’s (binary search trees) that store values 1...n?
For example, Given n = 3, there are a total of 5 unique BST’s.
1 3 3 2 1
\ / / / \ \
3 2 1 1 3 2
/ / \ \
2 1 2 3
5.3 109
1 1 2 3 3
\ \ / \ / /
3 2 1 3 2 1
/ \ / \
2 3 1 2
1 0
2 2 1
1
1, 2, 3, ..., n BST i
[1, i-1] [i+1, n]
f (i) [1, i] Unique Binary Search Tree
BST f (0) = 1
1 BST f (1) = 1
1,2
1 2
\ /
2 1
3 BST
∑
i
f (i) = f (k − 1) × f (i − k)
k=1
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];
}
};
Given n, generate all structurally unique BST’s (binary search trees) that store values 1...n.
For example, Given n = 3, your program should return all 5 unique BST’s shown below.
1 3 3 2 1
\ / / / \ \
3 2 1 1 3 2
/ / \ \
2 1 2 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;
}
};
Given an array where elements are sorted in ascending order, convert it to a height balanced BST.
template<typename RandomAccessIterator>
TreeNode* sortedArrayToBST (RandomAccessIterator first,
RandomAccessIterator last) {
const auto length = distance(first, last);
//
auto mid = first + length / 2;
TreeNode* root = new TreeNode (*mid);
root->left = sortedArrayToBST(first, mid);
root->right = sortedArrayToBST(mid + 1, last);
return root;
}
};
5.3 113
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
return root;
}
while(node) {
++n;
node = node->next;
114 5
return n;
}
return node;
}
};
5.4
5.4 115
§10.12.5
题
DFS
3! = 6 3 root->r->l r->root->l, r->l->root
stack<pair<TreeNode*, int>> s;
116 5
s.push(make_pair(root, 1));
while (!s.empty()) {
auto node = s.top().first;
auto depth = s.top().second;
s.pop();
return result;
}
};
题
• Maximum Depth of Binary Tree §5.4.2
题
• Minimum Depth of Binary Tree §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 5
Given a binary tree and a sum, find all root-to-leaf paths where each path’s sum equals the given sum.
For example: Given the below binary tree and sum = 22,
5
/ \
4 8
/ / \
11 13 4
/ \ / \
7 2 5 1
return
[
[5,4,11,2],
[5,8,4,5]
]
题 题 return
cur.push_back(root->val);
cur.pop_back();
}
};
题
• Path Sum §5.4.3
题
题 §13.2 Array
Binary Tree
Array Binary Tree Binary Tree
dfs L R L 0
L R 0 R
return
L->root->R L->root R->root
Populate each next pointer to point to its next right node. If there is no next right node, the next pointer
should be set to NULL.
Initially, all next pointers are set to NULL.
Note:
• You may only use constant extra space.
• You may assume that it is a perfect binary tree (ie, all leaves are at the same level, and every parent
has two children).
For example, Given the following perfect binary tree,
1
/
\
2 3
/ \ / \
4 5 6 7
connect(root->left, root->right);
if (sibling)
connect(root->right, sibling->left);
else
connect(root->right, nullptr);
}
};
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 5
•
6
Given two sorted integer arrays A and B, merge B into A as one sorted array.
Note: You may assume that A has enough space to hold additional elements from B. The number of
elements initialized in A and B are m and n respectively.
123
124 6
Merge two sorted linked lists and return it as a new list. The new list should be made by splicing together
the nodes of the first two lists.
Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity.
ListNode *p = lists[0];
for (int i = 1; i < lists.size(); i++) {
p = mergeTwoLists(p, lists[i]);
}
return p;
}
O(nlogn) 题 ”Merge
Two Sorted Lists”
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;
Given an unsorted integer array, find the first missing positive integer.
For example, Given [1,2,0] return 3, and [3,4,-1,1] return 2.
Your algorithm should run in O(n) time and uses constant space.
128 6
Given an array with n objects colored red, white or blue, sort them so that objects of the same color are
adjacent, with the colors in the order red, white and blue.
Here, we will use the integers 0, 1, and 2 to represent the color red, white, and blue respectively.
Note: You are not suppose to use the library’s sort function for this problem.
Follow up:
A rather straight forward solution is a two-pass algorithm using counting sort.
6.7 Sort Colors 129
First, iterate the array counting number of 0’s, 1’s, and 2’s, then overwrite array with total number of 0’s,
then 1’s and followed by 2’s.
Could you come up with an one-pass algorithm using only constant space?
0, 1, 2 (counting sort) 题
index red index blue index
O(n) O(1)
3 partition 0 1
n
1
// LeetCode, Sort Colors
// Counting Sort
// O(n) O(1)
class Solution {
public:
void sortColors(vector<int>& A) {
int counts[3] = { 0 }; //
}
};
2
// LeetCode, Sort Colors
// O(n) O(1)
class Solution {
public:
void sortColors(vector<int>& A) {
// red index blue index
int red = 0, blue = A.size() - 1;
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;
return pos;
}
};
Given a sorted array of integers, find the starting and ending position of a given target value.
Your algorithm’s runtime complexity must be in the order of O(log n).
If the target is not found in the array, return [-1, -1].
For example, Given [5, 7, 7, 8, 8, 10] and target value 8, return [3, 4].
STL
// LeetCode, Search for a Range
// STL
// O(logn) O(1)
class Solution {
public:
vector<int> searchRange(vector<int>& nums, int target) {
const int l = distance(nums.begin(), lower_bound(nums.begin(), nums.end(), target));
const int u = distance(nums.begin(), prev(upper_bound(nums.begin(), nums.end(), target
if (nums[l] != target) // not found
return vector<int> { -1, -1 };
else
return vector<int> { l, u };
}
};
lower_bound upper_bound
// LeetCode, Search for a Range
// lower_bound upper_bound
// O(logn) O(1)
class Solution {
131
132 7
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);
return first;
}
return first;
}
};
Given a sorted array and a target value, return the index if the target is found. If not, return the index
where it would be if it were inserted in order.
You may assume no duplicates in the array.
7.3 Search a 2D Matrix 133
std::lower_bound()
return first;
}
};
Write an efficient algorithm that searches for a value in an m × n matrix. This matrix has the following
properties:
• Integers in each row are sorted from left to right.
• The first integer of each row is greater than the last integer of the previous row.
134 7
int first = 0;
int last = m * n;
if (value == target)
return true;
else if (value < target)
first = mid + 1;
else
last = mid;
}
return false;
}
};
•
8
8.1 Subsets
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 8
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()); //
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);
8.1 Subsets 137
}
};
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 int i 1
S[i] 0 S={A,B,C,D} 0110=6 {B,C}
B1 B2 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;
}
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],
[]
]
题 题 题
0 1 0
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()); //
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);
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;
}
140 8
// 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);
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;
}
};
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;
• Subsets §8.1
8.3 Permutations
8.3.1 next_permutation()
std::next_permutation() OJ API
// 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
8.3 Permutations 143
// 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; //
//
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();
}
}
}
};
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() p
题
8.4 Permutations II 145
// LeetCode, Permutations II
// O(n!) O(n)
class Solution {
public:
vector<vector<int> > permuteUnique(vector<int>& num) {
sort(num.begin(), num.end());
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;
//
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);
146 8
p.pop_back(); //
}
}
}
};
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);
8.6 Letter Combinations of a Phone Number 147
}
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);
题
• Next Permutation, §2.1.12
• Permutation Sequence, §2.1.13
• Permutations, §8.3
• Permutations II, §8.4
Given a digit string, return all possible letter combinations that the number could represent.
A mapping of digit to letters (just like on the telephone buttons) is given below.
148 8
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" };
}
};
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" };
result.resize(n * m);
for (size_t i = 0; i < m; ++i)
copy(result.begin(), result.begin() + n, result.begin() + n * i);
•
9
题
A*
解 题 题 解
Given two words (start and end), and a dictionary, find the length of shortest transformation sequence
from start to end, such that:
• Only one letter can be changed at a time
• Each intermediate word must exist in the dictionary
For example, Given:
start = "hit"
end = "cog"
dict = ["hot","dot","dog","lot","log"]
As one shortest transformation is "hit" -> "hot" -> "dot" -> "dog" -> "cog", return its length 5.
Note:
• Return 0 if there is no such transformation sequence.
• All words have the same length.
• All words contain only lowercase alphabetic characters.
150
9.1 Word Ladder 151
namespace std {
template<> struct hash<state_t> {
public:
size_t operator()(const state_t& s) const {
return str_hash(s.word);
}
private:
std::hash<std::string> str_hash;
};
}
class Solution {
public:
int ladderLength(const string& start, const string &end,
const unordered_set<string> &dict) {
queue<state_t> q;
unordered_set<state_t> visited; //
swap(c, new_state.word[i]);
152 9
if (state_is_valid(new_state) &&
visited.find(new_state) == visited.end()) {
result.insert(new_state);
}
swap(c, new_state.word[i]); //
}
}
return result;
};
if (state_is_target(state)) {
return state.level + 1;
}
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;
};
current.push(start);
visited.insert(start);
while (!current.empty()) {
++level;
while (!current.empty()) {
// const auto& pop()
//
const auto state = current.front();
current.pop();
if (state_is_target(state)) {
return level + 1;
}
Given two words (start and end), and a dictionary, find all shortest transformation sequence(s) from start
to end, such that:
• Only one letter can be changed at a time
• Each intermediate word must exist in the dictionary
For example, Given:
start = "hit"
end = "cog"
dict = ["hot","dot","dog","lot","log"]
Return
[
["hit","hot","dot","dog","cog"],
["hit","hot","lot","log","cog"]
]
Note:
• All words have the same length.
• All words contain only lowercase alphabetic characters.
namespace std {
template<> struct hash<state_t> {
public:
size_t operator()(const state_t& s) const {
return str_hash(s.word);
}
private:
std::hash<std::string> str_hash;
};
}
class Solution {
public:
vector<vector<string> > findLadders(const string& start,
const string& end, const unordered_set<string> &dict) {
queue<state_t> q;
unordered_set<state_t> visited; //
unordered_map<state_t, vector<state_t> > father; // DAG
swap(c, new_state.word[i]);
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);
156 9
}
}
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()) {
9.2 Word Ladder II 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();
}
};
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;
};
// 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;
}
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()) {
9.2 Word Ladder II 159
题 dict
题
//LeetCode, Word Ladder II
// O(n) O(n)
class Solution {
public:
vector<vector<string> > findLadders(const string& start,
const string &end, const unordered_set<string> &dict) {
const auto& g = build_graph(dict);
vector<state_t*> pool;
queue<state_t*> q; //
// value
unordered_map<string, int> visited;
vector<vector<string>> result;
q.push(create_state(nullptr, start, 0, pool));
while (!q.empty()) {
state_t* state = q.front();
q.pop();
//
//
if (!result.empty() && state->level+1 > result[0].size()) break;
if (state_is_target(state)) {
160 9
//
auto iter = g.find(state->word);
if (iter == g.end()) continue;
private:
struct state_t {
state_t* father;
string word;
int level; // 0
return node;
}
vector<string> gen_path(const state_t* node) {
vector<string> path;
while(node != nullptr) {
path.push_back(node->word);
node = node->father;
}
reverse(path.begin(), path.end());
return path;
}
swap(c, new_word[i]);
if ((dict.find(new_word) != dict.end())) {
auto iter = adjacency_list.find(word);
if (iter != adjacency_list.end()) {
iter->second.insert(new_word);
} else {
adjacency_list.insert(pair<string,
unordered_set<string>>(word, unordered_set<string>()));
adjacency_list[word].insert(new_word);
}
}
swap(c, new_word[i]); //
}
}
}
return adjacency_list;
}
};
Given a 2D board containing 'X' and 'O', capture all regions surrounded by 'X'.
A region is captured by flipping all 'O's into 'X's in that surrounded region .
For example,
X X X X
X O O X
X X O X
X O X X
'O'
return result;
};
state_t start = { i, j };
if (state_is_valid(start)) {
board[i][j] = '+';
q.push(start);
}
while (!q.empty()) {
auto cur = q.front();
q.pop();
auto new_states = state_extend(cur);
for (auto s : new_states) q.push(s);
}
}
};
•
164 9
9.4
9.4.1
DAG
解
9.4.2
1.
(a) +
(b)
i.
ii.
4
2.
3. 2
题
1
4.
BFS
(a)
(b) DAG
visited
visited
(c)
i.
ii. unordered_-
set
head next §?? 2
9.4 165
iii.
5. 题
9.4.3
hashset
queue vector
1. state_t level
level A* queue
priority_queue
bfs_common.h
/** */
struct state_t {
int data1; /** . */
int data2; /** . */
// dataN; /** */
int action; /** . */
int level; /** 0 -1
*/
bool operator==(const state_t &other) const {
return true; // 题
}
};
// hash
// 1 hash
namespace std {
template<> struct hash<state_t> {
166 9
// 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);
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);
9.4 167
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 9
return result;
};
//
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); // visited
// q
// visited while
// , visited.insert(start)
}
}
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; //
//
9.4 169
//
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);
}
}
return result;
};
current.push(start);
while (!current.empty()) {
++level;
while (!current.empty()) {
// const auto& pop()
//
const auto state = current.front();
current.pop();
visited.insert(state);
if (state_is_target(state)) {
return return gen_path(father, state); //
// return state.level + 1; //
}
return vector<state_t>();
// return 0;
}
bfs_template1.cpp
170 9
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
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();
//
//
9.4 171
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;
}
bfs_template.cpp
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
//
auto state_is_valid = [&](const state_t &s) { /*...*/ };
//
auto state_is_target = [&](const state_t &s) { /*...*/ };
//
172 9
// 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;
}
current.clear();
swap(current, next);
}
return result;
}
bfs_template.cpp
10
Given a string s, partition s such that every substring of the partition is a palindrome.
Return all possible palindrome partitioning of s.
For example, given s = "aab", Return
[
["aa","b"],
["a","a","b"]
]
n n−1 O(2n−1 )
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;
}
};
A robot is located at the top-left corner of a m × n grid (marked ’Start’ in the diagram below).
The robot can only move either down or right at any point in time. The robot is trying to reach the
bottom-right corner of the grid (marked ’Finish’ in the diagram below).
How many possible unique paths are there?
10-1 Above is a 3 × 7 grid. How many possible unique paths are there?
10.2.1
if (m == 1 && n == 1) return 1; //
10.2.2
10.2 Unique Paths 177
if (f[x][y] > 0) {
return f[x][y];
} else {
return f[x][y] = dfs(x - 1, y) + 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]
}
return f[n - 1];
}
};
10.2.4
m n m+n−2
m−1 题 m+n−2 m–1
m−1
Cm+n−2
10.3.1
题
// (x,y)
if (obstacleGrid[x][y]) return 0;
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
题 题 1 题
0
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.
["..Q.", // Solution 2
"Q...",
"...Q",
".Q.."]
]
题
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;
}
/**
* (row, col) .
*
* @param C
* @param row
* @param col
* @return
*/
bool isValid(const vector<int> &C, int row, int col) {
10.4 N-Queens 183
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);
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
解 解 题
解 1
1
// LeetCode, N-Queens II
// +
// O(n!*n) O(n)
class Solution {
public:
int totalNQueens(int n) {
this->count = 0;
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<bool> anti_diag; //
• N-Queens §10.4
Given a string containing only digits, restore it by returning all possible valid IP address combinations.
For example: Given "25525511135",
return ["255.255.11.135", "255.255.111.35"]. (Order does not matter)
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()) { // 解
result.push_back(ip[0] + '.' + ip[1] + '.' + ip[2] + '.' + ip[3]);
return;
}
int num = 0;
for (size_t i = start; i < start + 3; i++) {
num = num * 10 + (s[i] - '0');
if (num == 0) break; // 0 0
}
}
};
•
188 10
Given a set of candidate numbers (C) and a target number (T ), find all unique combinations in C where
the candidate numbers sums to T .
The same repeated number may be chosen from C unlimited number of times.
Note:
• All numbers (including target) will be positive integers.
• Elements in a combination (a1 , a2 , ..., ak ) must be in non-descending order. (ie, a1 ≤ a2 ≤ ... ≤ ak ).
• The solution set must not contain duplicate combinations.
For example, given candidate set 2,3,6,7 and target 7, A solution set is:
[7]
[2, 2, 3]
private:
void dfs(vector<int>& nums, vector<int>& path, vector<vector<int> > &result,
int gap, int start) {
if (gap == 0) { // 解
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(); //
}
10.8 Combination Sum II 189
}
};
Given a collection of candidate numbers (C) and a target number (T ), find all unique combinations in
C where the candidate numbers sums to T .
Each number in C may only be used once in the combination.
Note:
• All numbers (including target) will be positive integers.
• Elements in a combination (a1 , a2 , ..., ak ) must be in non-descending order. (ie, a1 > a2 > ... > ak ).
• The solution set must not contain duplicate combinations.
For example, given candidate set 10,1,2,7,6,1,5 and target 8, A solution set is:
[1, 7]
[1, 2, 5]
[2, 6]
[1, 1, 6]
previous = nums[i];
path.push_back(nums[i]);
dfs(nums, path, result, gap - nums[i], i + 1);
path.pop_back(); //
}
}
};
Given n pairs of parentheses, write a function to generate all combinations of well-formed parentheses.
For example, given n = 3, a solution set is:
"((()))", "(()())", "(())()", "()(())", "()()()"
<n
1
// LeetCode, Generate Parentheses
// O(TODO) O(n)
class Solution {
10.9 Generate Parentheses 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();
}
}
};
return result;
}
};
Given a 2D board and a word, find if the word exists in the grid.
The word can be constructed from letters of sequentially adjacent cell, where "adjacent" cells are those
horizontally or vertically neighbouring. The same letter cell may not be used more than once.
194 10
visited[x][y] = true;
bool ret = dfs(board, word, index + 1, x - 1, y, visited) || //
dfs(board, word, index + 1, x + 1, y, visited) || //
dfs(board, word, index + 1, x, y - 1, visited) || //
dfs(board, word, index + 1, x, y + 1, visited); //
visited[x][y] = false;
10.12 195
return ret;
}
};
10.12
10.12.1
解 解
10.12.2
1. 题 解
解 解
(a)
(b) path[]
2. 解 解 解
解 解
题 解
解 题
3.
struct
struct
4.
题
1
196 10
5.
0
6. 解
解 解 解 解
path[] 解
7.
(a)
DAG BFS BFS
DAG
8.
(a)
题
(b)
题 解 8 题
5 8 题
题
题
10.12 197
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_first_search (backtrack-
ing) http://en.wikipedia.org/wiki/Backtracking
= +
(recursion)
10.12.5
(recursion)
(iteration)
(prunning)
198 10
11.1 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)
// 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;
• Pow(x) §11.1
12
Given an array of non-negative integers, you are initially positioned at the first index of the array.
Each element in the array represents your maximum jump length at that position.
Determine if you are able to reach the last index.
For example:
A = [2,3,1,1,4], return true.
A = [3,2,1,0,4], return false.
A[i] 0 1
0
f[i] 0 A[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
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;
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;
}
};
Given an array of non-negative integers, you are initially positioned at the first index of the array.
12.2 Jump Game II 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;
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
return result;
}
};
Say you have an array for which the i-th element is the price of a given stock on day i.
If you were only permitted to complete at most one transaction (ie, buy one and sell one share of the
stock), design an algorithm to find the maximum profit.
题 m m=1
Say you have an array for which the i-th element is the price of a given stock on day i.
Design an algorithm to find the maximum profit. You may complete as many transactions as you like (ie,
buy one and sell one share of the stock multiple times). However, you may not engage in multiple transactions
at the same time (ie, you must sell the stock before you buy again).
题 m m=
Given a string, find the length of the longest substring without repeating characters. For example, the
longest substring without repeating letters for "abcabcbb" is "abc", which the length is 3. For "bbbbb" the
longest substring is "b", with the length of 1.
题 题
题 题 题
index+1
O(n) 12-1
12-1
题
•
Given n non-negative integers a1 , a2 , ..., an , where each represents a point at coordinate (i, ai ). n verti-
cal lines are drawn such that the two endpoints of line i is at (i, ai ) and (i, 0). Find two lines, which together
with x-axis forms a container, such that the container contains the most water.
Note: You may not slant the container.
题
• Trapping Rain Water, §2.1.15
208 12
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]
]
f (i, j) (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
题
•
Find the contiguous subarray within an array (containing at least one number) which has the largest sum.
For example, given the array [−2,1,−3,4,−1,2,1,−5,4], the contiguous subarray [4,−1,2,1] has
the largest sum = 6.
1 SubArray 2. SubArray
SubArray 0
SubArray
SubArray 0 0
0 SubArray
f[j] S[j]
解
• S[j] f [j − 1] +
S[j]
• S[j] S[j] S[j]
• 2 i j O(n3 )
• 3 O(n2 )
• 4 O(n log n)
• 5 2O(n2 ) O(n)
• 6 M=1 M
13.2 Maximum Subarray 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;
}
};
Given a string s, partition s such that every substring of the partition is a palindrome.
Return the minimum cuts needed for a palindrome partitioning of s.
For example, given s = "aab",
Return 1 since the palindrome partitioning ["aa","b"] could be produced using 1 cut.
DP i DP
f(i)= [i, n-1] cut n
题 [i,j] i j
DP 题
P[i][j] = true if [i,j]
P[i][j] = str[i] == str[j] && P[i+1][j-1]
}
return f[0];
}
};
Given a 2D binary matrix filled with 0’s and 1’s, find the largest rectangle containing all ones and return
its area.
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
题
•
Say you have an array for which the i-th element is the price of a given stock on day i.
Design an algorithm to find the maximum profit. You may complete at most two transactions.
Note: You may not engage in multiple transactions at the same time (ie, you must sell the stock before
you buy again).
int max_profit = 0;
for (int i = 0; i < n; ++i)
max_profit = max(max_profit, f[i] + g[i]);
return max_profit;
}
};
题
• Best Time to Buy and Sell Stock §12.3
• Best Time to Buy and Sell Stock II §12.4
Given s1, s2, s3, find whether s3 is formed by the interleaving of s1 and s2.
For example, Given: s1 = "aabcc", s2 = "dbbca",
When s3 = "aadbbcbcac", return true.
When s3 = "aadbbbaccc", return false.
class Solution {
public:
bool isInterleave(const string& s1, const string& s2, const string& s3) {
if (s3.length() != s1.length() + s2.length())
return false;
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;
vector<vector<bool>> f(s1.length() + 1,
vector<bool>(s2.length() + 1, true));
return f[s1.length()][s2.length()];
}
};
13.7 Scramble String 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;
return f[s2.length()];
}
};
Given a string s1, we may represent it as a binary tree by partitioning it to two non-empty substrings
recursively.
Below is one possible representation of s1 = "great":
great
/ \
gr eat
/ \ / \
g r e at
/ \
a t
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
string
memorization
scamble
false
HashMap 题 HashMap map unordered_map
题 f[n][i][j] n
s1[i] s2[j] scramble
f[n][i][j]} = (f[k][i][j] && f[n-k][i+k][j+k])
|| (f[k][i][j+n-k] && f[n-k][i+k][j])
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);
return false;
}
};
// f[n][i][j] n s1[i]
// s2[j] scramble
bool f[N + 1][N][N];
fill_n(&f[0][0][0], (N + 1) * N * N, false);
}
}
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;
return false;
}
};
private:
typedef string::const_iterator Iterator;
map<tuple<Iterator, Iterator, Iterator>, bool> cache;
return false;
}
public:
unordered_map<Key, bool> cache;
if (length == 1)
return *first1 == *first2;
return false;
}
题
•
Given a m × n grid filled with non-negative numbers, find a path from top left to bottom right which
minimizes the sum of all numbers along its path.
Note: You can only move either down or right at any point in time
int f[m][n];
f[0][0] = grid[0][0];
for (int i = 1; i < m; i++) {
f[i][0] = f[i - 1][0] + grid[i][0];
}
for (int i = 1; i < n; i++) {
f[0][i] = f[0][i - 1] + grid[0][i];
224 13
+
// 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); // INT_MAX min
f[0] = 0;
题
• Unique Paths, §10.2
• Unique Paths II, §10.3
Given two words word1 and word2, find the minimum number of steps required to convert word1 to
word2. (each operation is counted as 1 step.)
You have the following 3 operations permitted on a word:
13.9 Edit Distance 225
• Insert a character
• Delete a character
• Replace a character
1. c==d f[i][j]=f[i-1][j-1]
2. c!=d
(a) c d f[i][j]=f[i-1][j-1]+1
(b) c d f[i][j]=f[i][j-1]+1
(c) c f[i][j]=f[i-1][j]+1
+
// 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);
upper_left = upper;
}
}
return f[word2.length()];
}
};
A message containing letters from A-Z is being encoded to numbers using the following mapping:
'A' -> 1
'B' -> 2
...
'Z' -> 26
13.11 Distinct Subsequences 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.
int prev = 0;
int cur = 1;
// n n+1
for (size_t i = 1; i <= s.size(); ++i) {
if (s[i-1] == '0') cur = 0;
题
• Climbing Stairs, §2.1.18
return f[T.size()];
}
};
Given a string s and a dictionary of words dict, determine if s can be segmented into a space-separated
sequence of one or more dictionary words.
For example, given
s = "leetcode",
dict = ["leet", "code"].
Return true because "leetcode" can be segmented as "leet code".
13.12 Word Break 229
f (i) s[0,i]
Given a string s and a dictionary of words dict, add spaces in s to construct a sentence where each word
is a valid dictionary word.
Return all such possible sentences.
For example, given
s = "catsanddog",
dict = ["cat", "cats", "and", "sand", "dog"].
A solution is ["cats and dog", "cat sand dog"].
题 解
}
13.13 Word Break II 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();
}
}
}
};
//
struct UndirectedGraphNode {
int label;
vector<UndirectedGraphNode *> neighbors;
UndirectedGraphNode(int x) : label(x) {};
};
Clone an undirected graph. Each node in the graph contains a label and a list of its neighbours.
OJ’s undirected graph serialization: Nodes are labeled uniquely.
We use # as a separator for each node, and , as a separator for node label and each neighbour of the
node. As an example, consider the serialized graph {0,1,2#1,2#2,2}.
The graph has a total of three nodes, and therefore contains three parts as separated by #.
3. Third node is labeled as 2. Connect node 2 to node 2 (itself), thus forming a self-cycle.
232
14.1 Clone Graph 233
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];
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]);
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
题
235
236 15 题
for (; t; t /= 10)
r = r * 10 + t % 10;
题 Palindrome
reverse()
解 10
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 / d; // quotient
int r = x % 10; // remainder
if (q != r) return false;
x = x % d / 10;
d /= 100;
}
return true;
}
};
Given a set of non-overlapping intervals, insert a new interval into the intervals (merge if necessary).
You may assume that the intervals were initially sorted according to their start times.
Example 1: Given intervals [1,3],[6,9], insert and merge [2,5] in as [1,5],[6,9].
Example 2: Given [1,2],[3,5],[6,7],[8,10],[12,16], insert and merge [4,9] in as
[1,2],[3,10],[12,16].
This is because the new interval [4,9] overlaps with [3,5],[6,7],[8,10].
struct Interval {
int start;
int end;
Interval() : start(0), end(0) { }
Interval(int s, int e) : start(s), end(e) { }
};
// 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;
}
};
struct Interval {
int start;
int end;
Interval() : start(0), end(0) { }
Interval(int s, int e) : start(s), end(e) { }
};
15.5 Minimum Window Substring 239
Given a string S and a string T , find the minimum window in S which will contain all the characters in
T in complexity O(n).
For example, S = "ADOBECODEBANC", T = "ABC"
Minimum window is "BANC".
Note:
• If there is no such window in S that covers all characters in T , return the emtpy string "".
240 15 题
• If there are multiple such windows, you are guaranteed that there will always be only one unique
minimum window in S.
Given two numbers represented as strings, return multiplication of the numbers as a string.
Note: The numbers can be arbitrarily large and are non-negative.
int int
int32 2 31
− 1 = 2147483647 9
4 int64 9
1
// LeetCode, Multiply Strings
// @author (http://weibo.com/lianchengzju)
// int
// O(n*m) O(n+m)
typedef vector<int> bigint;
return z;
}
class Solution {
public:
string multiply(string num1, string num2) {
return to_string(make_bigint(num1) * make_bigint(num2));
}
};
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);
if (started) { // 0
result << setw(RADIX_LEN) << setfill('0') << *i;
} else {
result << *i;
started = true; // 0 0
}
}
/**
* @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);
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();
}
};
You are given a string, S, and a list of words, L, that are all of the same length. Find all starting indices of
substring(s) in S that is a concatenation of each word in L exactly once and without any intervening characters.
For example, given:
S: "barfoothefoobarman"
L: ["foo", "bar"]
You should return the indices: [0,9].(order does not matter).
if (--pos->second == 0) unused.erase(pos);
}
return result;
}
};
题 0
题
• Pascal’s Triangle II §15.9
Given a matrix of m × n elements (m rows, n columns), return all elements of the matrix in spiral order.
For example, Given the following matrix:
[
[ 1, 2, 3 ],
[ 4, 5, 6 ],
[ 7, 8, 9 ]
]
Given an integer n, generate a square matrix filled with elements from 1 to n2 in spiral order.
For example, Given n = 3,
You should return the following matrix:
[
[ 1, 2, 3 ],
[ 8, 9, 4 ],
[ 7, 6, 5 ]
]
15.11 Spiral Matrix II 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;
return matrix;
}
};
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;
The string "PAYPALISHIRING" is written in a zigzag pattern on a given number of rows like this: (you
may want to display this pattern in a fixed font for better legibility)
P A H N
A P L S I I G
Y I R
题
n=4:
P I N
A L S I G
Y A H R
P I
n=5:
P H
A S I
Y I R
P L I G
A N
(i, j) = (j + 1) ∗ n + i
(i, j) = (j + 1) ∗ n − i
15.13 Divide Two Integers 251
Divide two integers without using multiplication, division and mod operator.
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;
252 15 题
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); //
while (a >= b) {
int multi = 1;
unsigned int bb = b;
while (a >= bb) {
a -= bb;
result += multi;
•
15.14 Text Justification 253
Given an array of words and a length L, format the text such that each line has exactly L characters and
is fully (left and right) justified.
You should pack your words in a greedy approach; that is, pack as many words as you can in each line.
Pad extra spaces ' ' when necessary so that each line has exactly L characters.
Extra spaces between words should be distributed as evenly as possible. If the number of spaces on a
line do not divide evenly between words, the empty slots on the left will be assigned more spaces than the
slots on the right.
For the last line of text, it should be left justified and no extra space is inserted between words.
For example,
words: ["This", "is", "an", "example", "of", "text", "justification."]
L: 16.
Return the formatted lines as:
[
"This is an",
"example of text",
"justification. "
]
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);
}
/**
* @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, ' ');
}
};
•
15.15 Max Points on a Line 255
Given n points on a 2D plane, find the maximum number of points that lie on the same straight line.
1
n n(n + 1)
2
n
O(n3 )
key value
O(n2 ) O(n)
int count = 0;
if (slope_count.find(slope) != slope_count.end())
count = ++slope_count[slope];
else {
count = 2;
slope_count[slope] = 2;
}