Skip to content

Commit 55b0a2b

Browse files
committed
Add comments to explain the solutions
1 parent 148d039 commit 55b0a2b

File tree

4 files changed

+191
-13
lines changed

4 files changed

+191
-13
lines changed

src/largestRectangleInHistogram/largestRectangleInHistogram.cpp

+71
Original file line numberDiff line numberDiff line change
@@ -22,22 +22,93 @@
2222
#include <vector>
2323
using namespace std;
2424

25+
// As we know, the area = width * height
26+
// For every bar, the 'height' is determined by the loweset bar.
27+
//
28+
// 1) We traverse all bars from left to right, maintain a stack of bars. Every bar is pushed to stack once.
29+
// 2) A bar is popped from stack when a bar of smaller height is seen.
30+
// 3) When a bar is popped, we calculate the area with the popped bar as smallest bar.
31+
// 4) How do we get left and right indexes of the popped bar –
32+
// the current index tells us the ‘right index’ and index of previous item in stack is the ‘left index’.
33+
//
34+
//
35+
// In other word, the stack only stores the incresing bars, let's see some example
36+
//
37+
// Example 1
38+
// ---------
39+
// height = [1,2,3,4]
40+
//
41+
// stack[] = [ 0, 1, 2, 3 ], i=4
42+
//
43+
// 1) pop 3, area = height[3] * 1 = 4
44+
// 2) pop 2, area = height[2] * 2 = 4
45+
// 3) pop 1, area = height[1] * 3 = 6
46+
// 4) pop 0, area = height[0] * 4 = 4
47+
//
48+
//
49+
// Example 2
50+
// ---------
51+
// height = [2,1,2]
52+
//
53+
// stack[] = [ 0 ], i=1
54+
// 1) pop 0, area = height[0] * 1 = 2
55+
//
56+
// stack[] = [ 1,2 ], i=3, meet the end
57+
// 1) pop 2, area = height[2] * 1 = 2
58+
// 2) pop 1, area = height[1] * 3 = 3
59+
//
60+
//
61+
// Example 3
62+
// ---------
63+
// height = [4,2,0,3,2,5]
64+
//
65+
// stack[] = [ 0 ], i=1, height[1] goes down
66+
// 1) pop 0, area = height[0] * 1 = 4
67+
//
68+
// stack[] = [ 1 ], i=2, height[2] goes down
69+
// 1) pop 1, area = height[1] * 2 = 4 // <- how do we know the left?
70+
// start from the 0 ??
71+
//
72+
// stack[] = [ 2, 3 ], i=4, height[4] goes down
73+
// 1) pop 3, area = height[3] * 1 = 3
74+
// 2) pop 2, area = height[2] * ? = 0 // <- how do we know the left?
75+
// start from the 0 ??
76+
//
77+
// stack[] = [ 2,4,5 ], i=6, meet the end
78+
// 1) pop 5, area = height[5] * 1 = 5
79+
// 2) pop 4, area = height[4] * 3 = 6 // <- how do we know the left?
80+
// need check the previous item.
81+
// 3) pop 2, area = height[2] * ? = 4 // <- how do we know the left?
82+
// start from the 0 ??
83+
//
84+
// so, we can see, when the stack pop the top, the area formular is
85+
//
86+
// height[stack_pop] * i - stack[current_top] - 1, if stack is not empty
87+
// height[stack_pop] * i, if stack is empty
88+
//
2589
int largestRectangleArea(vector<int> &height) {
2690
if (height.size()<=0) return 0;
91+
//Create an empty stack.
2792
vector<int> stack;
93+
//add a flag as a trigger if the end bar is met, and need to check the stack is empty of not .
2894
height.push_back(0);
2995
int maxArea = 0;
3096
for(int i=0; i<height.size(); i++){
97+
//If stack is empty or height[i] is higher than the bar at top of stack, then push ‘i’ to stack.
3198
if ( stack.size()<=0 || height[i] >= height[stack.back()] ) {
3299
stack.push_back(i);
33100
continue;
34101
}
102+
//If this bar is smaller than the top of stack, then keep removing the top of stack while top of the stack is greater.
103+
//Let the removed bar be height[top]. Calculate area of rectangle with height[top] as smallest bar.
104+
//For height[top], the ‘left index’ is previous (previous to top) item in stack and ‘right index’ is ‘i’ (current index).
35105
int topIdx = stack.back();
36106
stack.pop_back();
37107
int area = height[topIdx] * (stack.size()==0 ? i : i - stack.back() - 1 );
38108
if ( area > maxArea ) {
39109
maxArea = area;
40110
}
111+
//one more time. Because the stack might still have item.
41112
i--;
42113
}
43114

src/maximalRectangle/maximalRectangle.cpp

+13-5
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,18 @@
1515
#include <vector>
1616
using namespace std;
1717

18+
// The problem can be convert to the problem - "Largest Rectangle in Histogram"
19+
// 1) we can take each row to calculate each row's histogram.
20+
// 2) using the algorithm of "Largest Rectangle in Histogram" to find the largest area histogram.
21+
// 3) tracking the maximal area.
22+
//
23+
// For the 1), it's easy.
24+
// heights[i][j] = 1, if (i==0)
25+
// heights[i][j] = heights[i-1][j] + 1;, if (i>0)
26+
//
27+
// For the 2), please referr to "Largest Rectangle in Histogram"
28+
//
29+
1830
int largestRectangleArea(vector<int> &height) {
1931

2032
if (height.size()<=0) return 0;
@@ -44,11 +56,7 @@ int maximalRectangle(vector<vector<char> > &matrix) {
4456
if (matrix.size()<=0 || matrix[0].size()<=0) return 0;
4557
int row = matrix.size();
4658
int col = matrix[0].size();
47-
vector< vector<int> > heights(row);
48-
for (int i=0; i<row; i++){
49-
vector<int> v(col);
50-
heights[i] = v;
51-
}
59+
vector< vector<int> > heights(row, vector<int> col);
5260

5361
int maxArea = 0;
5462
for(int i=0; i<row; i++){

src/recoverBinarySearchTree/recoverBinarySearchTree.cpp

+18-3
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,23 @@
4242
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
4343
* };
4444
*/
45+
46+
//
47+
// We can convert the BST to a sorted array, then we can find the two nodes which missed the order.
48+
//
49+
// To cover the BST to sorted array, we needn't use an extra array, we just traverse the tree in order.
50+
//
51+
// 8
52+
// _______/ \_______
53+
// / \
54+
// 4 12
55+
// __/ \__ __/ \__
56+
// / \ / \
57+
// 2 6 10 14
58+
// / \ / \ / \ / \
59+
// 1 3 5 7 9 11 13 15
60+
//
61+
//
4562
class Solution {
4663
public:
4764
void recoverTreeHelper(TreeNode *root) {
@@ -53,10 +70,8 @@ class Solution {
5370
if (prev->val > root->val){
5471
if (n1==NULL) {
5572
n1 = prev;
56-
n2 = root;
57-
}else{
58-
n2 = root;
5973
}
74+
n2 = root;
6075
}
6176
}
6277
prev = root;

src/scrambleString/scrambleString.cpp

+89-5
Original file line numberDiff line numberDiff line change
@@ -47,12 +47,23 @@
4747
*
4848
**********************************************************************************/
4949

50+
#include <stdlib.h>
51+
#include <time.h>
5052
#include <iostream>
53+
#include <vector>
5154
#include <string>
5255
#include <algorithm>
5356
using namespace std;
5457

55-
bool isScramble(string s1, string s2) {
58+
// The recursive way is quite simple.
59+
// 1) break the string to two parts:
60+
// s1[0..j] s1[j+1..n]
61+
// s2[0..j] s2[j+1..n]
62+
// 2) then
63+
// isScramble(s1[0..j], s2[0..j]) && isScramble(s1[j+1..n], s2[j+1..n])
64+
// OR
65+
// isScramble(s1[0..j], s2[j+1, n]) && isScramble(s1[j+1..n], s2[0..j])
66+
bool isScramble_recursion(string s1, string s2) {
5667

5768
if (s1.size()!= s2.size() || s1.size()==0 || s2.size()==0) {
5869
return false;
@@ -69,12 +80,12 @@ bool isScramble(string s1, string s2) {
6980
}
7081

7182
for (int i=1; i<s1.size(); i++) {
72-
if ( isScramble(s1.substr(0,i), s2.substr(0,i)) &&
73-
isScramble(s1.substr(i, s1.size()-i), s2.substr(i, s2.size()-i)) ) {
83+
if ( isScramble_recursion(s1.substr(0,i), s2.substr(0,i)) &&
84+
isScramble_recursion(s1.substr(i, s1.size()-i), s2.substr(i, s2.size()-i)) ) {
7485
return true;
7586
}
76-
if ( isScramble(s1.substr(0,i), s2.substr(s2.size()-i, i)) &&
77-
isScramble(s1.substr(i, s1.size()-i), s2.substr(0, s2.size()-i)) ) {
87+
if ( isScramble_recursion(s1.substr(0,i), s2.substr(s2.size()-i, i)) &&
88+
isScramble_recursion(s1.substr(i, s1.size()-i), s2.substr(0, s2.size()-i)) ) {
7889
return true;
7990
}
8091
}
@@ -83,6 +94,79 @@ bool isScramble(string s1, string s2) {
8394

8495
}
8596

97+
/*
98+
* Definition
99+
*
100+
* dp[k][i][j] means:
101+
*
102+
* a) s1[i] start from 'i'
103+
* b) s2[j] start from 'j'
104+
* c) 'k' is the length of substring
105+
*
106+
* Initialization
107+
*
108+
* dp[1][i][j] = (s1[i] == s2[j] ? true : false)
109+
*
110+
* Formula
111+
*
112+
* same as the above recursive method idea
113+
*
114+
* dp[k][i][j] =
115+
* dp[divk][i][j] && dp[k-divk][i+divk][j+divk] ||
116+
* dp[divk][i][j+k-divk] && dp[k-divk][i+divk][j]
117+
*
118+
* `divk` mean split the k to two parts, so 0 <= divk <= k;
119+
*/
120+
bool isScramble_dp(string s1, string s2) {
121+
122+
if (s1.size()!= s2.size() || s1.size()==0 || s2.size()==0) {
123+
return false;
124+
}
125+
if (s1 == s2){
126+
return true;
127+
}
128+
129+
const int len = s1.size();
130+
131+
// dp[len+1][len][len]
132+
vector< vector< vector<bool> > > dp(len+1, vector< vector<bool> >(len, vector<bool>(len) ) );
133+
134+
// ignor the k=0, just for readable code.
135+
136+
// initialization k=1
137+
for (int i=0; i<len; i++){
138+
for (int j=0; j<len; j++) {
139+
dp[1][i][j] = (s1[i] == s2[j]);
140+
}
141+
}
142+
// start from k=2 to len, O(n^4) loop.
143+
for (int k=2; k<=len; k++){
144+
for (int i=0; i<len-k+1; i++){
145+
for (int j=0; j<len-k+1; j++){
146+
dp[k][i][j] = false;
147+
for (int divk = 1; divk < k && dp[k][i][j]==false; divk++){
148+
dp[k][i][j] = ( dp[divk][i][j] && dp[k-divk][i+divk][j+divk] ) ||
149+
( dp[divk][i][j+k-divk] && dp[k-divk][i+divk][j] );
150+
}
151+
}
152+
}
153+
}
154+
155+
return dp[len][0][0];
156+
}
157+
158+
bool isScramble(string s1, string s2) {
159+
160+
srand(time(0));
161+
162+
if (random()%2) {
163+
cout << "---- recursion ---" << endl;
164+
return isScramble_recursion(s1, s2);
165+
}
166+
cout << "---- dynamic programming ---" << endl;
167+
return isScramble_dp(s1, s2);
168+
}
169+
86170
int main(int argc, char** argv)
87171
{
88172
string s1="great", s2="rgtae";

0 commit comments

Comments
 (0)