Skip to content

Commit 33c74f2

Browse files
committed
Add comments to explain the solutions
1 parent 55b0a2b commit 33c74f2

File tree

15 files changed

+246
-35
lines changed

15 files changed

+246
-35
lines changed

src/editDistance/editDistance.cpp

Lines changed: 64 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,29 +22,87 @@
2222
#include <algorithm>
2323
using namespace std;
2424

25+
26+
/*
27+
* Dynamic Programming
28+
*
29+
* Definitaion
30+
*
31+
* m[i][j] is minimal distance from word1[0..i] to word2[0..j]
32+
*
33+
* So,
34+
*
35+
* 1) if word1[i] == word2[j], then m[i][j] == m[i-1][j-1].
36+
*
37+
* 2) if word1[i] != word2[j], then we need to find which one below is minimal:
38+
*
39+
* min( m[i-1][j-1], m[i-1][j], m[i][j-1] )
40+
*
41+
* and +1 - current char need be changed.
42+
*
43+
* Let's take a look m[1][2] : "a" => "ab"
44+
*
45+
* +---+ +---+
46+
* ''=> a | 1 | | 2 | '' => ab
47+
* +---+ +---+
48+
*
49+
* +---+ +---+
50+
* a => a | 0 | | 1 | a => ab
51+
* +---+ +---+
52+
*
53+
* To know the minimal distance `a => ab`, we can get it from one of the following cases:
54+
*
55+
* 1) delete the last char in word1, minDistance( '' => ab ) + 1
56+
* 2) delete the last char in word2, minDistance( a => a ) + 1
57+
* 3) change the last char, minDistance( '' => a ) + 1
58+
*
59+
*
60+
* For Example:
61+
*
62+
* word1="abb", word2="abccb"
63+
*
64+
* 1) Initialize the DP matrix as below:
65+
*
66+
* "" a b c c b
67+
* "" 0 1 2 3 4 5
68+
* a 1
69+
* b 2
70+
* b 3
71+
*
72+
* 2) Dynamic Programming
73+
*
74+
* "" a b c c b
75+
* "" 0 1 2 3 4 5
76+
* a 1 0 1 2 3 4
77+
* b 2 1 0 1 2 3
78+
* b 3 2 1 1 1 2
79+
*
80+
*/
81+
int min(int x, int y, int z) {
82+
return std::min(x, std::min(y,z));
83+
}
84+
2585
int minDistance(string word1, string word2) {
2686
int n1 = word1.size();
2787
int n2 = word2.size();
2888
if (n1==0) return n2;
2989
if (n2==0) return n1;
30-
vector< vector<int> > m(n1+1);
90+
vector< vector<int> > m(n1+1, vector<int>(n2+1));
3191
for(int i=0; i<m.size(); i++){
32-
vector<int> r(n2+1);
33-
r[0] = i;
34-
m[i] = r;
92+
m[i][0] = i;
3593
}
3694
for (int i=0; i<m[0].size(); i++) {
3795
m[0][i]=i;
3896
}
3997

4098
//Dynamic Programming
99+
int row, col;
41100
for (row=1; row<m.size(); row++) {
42101
for(col=1; col<m[row].size(); col++){
43102
if (word1[row-1] == word2[col-1] ){
44103
m[row][col] = m[row-1][col-1];
45104
}else{
46-
int minValue = min(m[row-1][col-1], m[row-1][col]);
47-
minValue = min(minValue, m[row][col-1]);
105+
int minValue = min(m[row-1][col-1], m[row-1][col], m[row][col-1]);
48106
m[row][col] = minValue + 1;
49107
}
50108
}

src/firstMissingPositive/firstMissingPositive.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,22 @@ using namespace std;
2121

2222
#define INT_MAX 2147483647
2323

24+
/*
25+
* The idea is simple:
26+
*
27+
* 1) put all of number into a map.
28+
* 2) for each number a[i] in array, remove its continous number in the map
29+
* 2.1) remove ... a[i]-3, a[i]-2, a[i]-1, a[i]
30+
* 2.2) remove a[i]+1, a[i]+2, a[i]+3,...
31+
* 3) during the removeing process, if some number cannot be found, which means it's missed.
32+
*
33+
* considering a case [-2, -1, 4,5,6],
34+
* [-2, -1] => missed 0
35+
* [4,5,6] => missed 3
36+
*
37+
* However, we missed 1, so, we have to add dummy number 0 whatever.
38+
*
39+
*/
2440
int firstMissingPositive(int A[], int n) {
2541
map<int, int> cache;
2642
for(int i=0; i<n; i++){
@@ -47,12 +63,14 @@ int firstMissingPositive(int A[], int n) {
4763
}
4864

4965
int num ;
66+
// remove the ... x-3, x-2, x-1, x
5067
for( num=x; cache.find(num)!=cache.end(); num--){
5168
cache.erase(cache.find(num));
5269
}
5370
if ( num>0 && num < miss ){
5471
miss = num;
5572
}
73+
// remove the x+1, x+2, x+3 ...
5674
for ( num=x+1; cache.find(num)!=cache.end(); num++){
5775
cache.erase(cache.find(num));
5876
}

src/insertInterval/insertInterval.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ struct Interval {
3131
Interval(int s, int e) : start(s), end(e) {}
3232
};
3333

34+
//Two factors sorting [start:end]
3435
bool compare(const Interval& lhs, const Interval& rhs){
3536
return (lhs.start==rhs.start) ? lhs.end < rhs.end : lhs.start < rhs.start;
3637
}
@@ -40,10 +41,12 @@ vector<Interval> merge(vector<Interval> &intervals) {
4041
vector<Interval> result;
4142

4243
if (intervals.size() <= 0) return result;
43-
44+
//sort the inervals. Note: using the customized comparing function.
4445
sort(intervals.begin(), intervals.end(), compare);
4546
for(int i=0; i<intervals.size(); i++) {
4647
int size = result.size();
48+
// if the current intervals[i] is overlapped with previous interval.
49+
// merge them together
4750
if( size>0 && result[size-1].end >= intervals[i].start) {
4851
result[size-1].end = max(result[size-1].end, intervals[i].end);
4952
}else{
@@ -54,6 +57,7 @@ vector<Interval> merge(vector<Interval> &intervals) {
5457
return result;
5558
}
5659

60+
//just reuse the solution of "Merge Intervals", quite straight forward
5761
vector<Interval> insert(vector<Interval> &intervals, Interval newInterval) {
5862

5963
intervals.push_back(newInterval);

src/jumpGame/jumpGame.II.cpp

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include <iostream>
2323
using namespace std;
2424

25+
//Acutally, using the Greedy algorithm can have the answer
2526
int jump(int A[], int n) {
2627
if (n<=1) return 0;
2728

@@ -36,9 +37,10 @@ int jump(int A[], int n) {
3637
if (coverPos >= n-1){
3738
return steps;
3839
}
40+
//Greedy: find the next place which can have biggest distance
3941
int nextPos=0;
4042
int maxDistance=0;
41-
for(int j=i+1; j<=A[i]+i; j++){
43+
for(int j=i+1; j<=coverPos; j++){
4244
if ( A[j]+j > maxDistance ) {
4345
maxDistance = A[j]+j;
4446
nextPos = j;
@@ -59,7 +61,7 @@ void printArray(int a[], int n){
5961
}
6062
int main()
6163
{
62-
#define TEST(a) printArray(a, sizeof(a)/sizeof(int)); cout<<jump(a, sizeof(a)/sizeof(int))<<endl;
64+
#define TEST(a) printArray(a, sizeof(a)/sizeof(a[0])); cout<<jump(a, sizeof(a)/sizeof(a[0]))<<endl;
6365

6466
int a1[]={0};
6567
TEST(a1);
@@ -76,5 +78,13 @@ int main()
7678
int a5[]={1,2,3};
7779
TEST(a5);
7880

81+
// 0 -> 1 -> 4 -> end
82+
int a6[]={2,3,1,1,4,0,1};
83+
TEST(a6);
84+
85+
// 0 -> 1 -> 3 -> end
86+
int a7[]={2,3,1,2,0,1};
87+
TEST(a7);
88+
7989
return 0;
8090
}

src/jumpGame/jumpGame.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,9 @@ class Solution {
2323
bool canJump(int A[], int n) {
2424
if (n<=0) return false;
2525

26+
// the basic idea is traverse array, maintain the most far can go
2627
int coverPos=0;
28+
// the condition i<=coverPos means traverse all of covered position
2729
for(int i=0; i<=coverPos && i<n; i++){
2830

2931
if (coverPos < A[i] + i){

src/medianOfTwoSortedArrays/medianOfTwoSortedArrays.cpp

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111

1212
#include <stdio.h>
1313

14+
// Classical binary search algorithm, but slightly different
15+
// if cannot find the key, return the position where can insert the key
1416
int binarySearch(int A[], int low, int high, int key){
1517
while(low<=high){
1618
int mid = low + (high - low)/2;
@@ -24,17 +26,33 @@ int binarySearch(int A[], int low, int high, int key){
2426
return low;
2527
}
2628

29+
//Notes:
30+
// I feel the following methods is quite complicated, it should have a better high clear and readable solution
2731
double findMedianSortedArrayHelper(int A[], int m, int B[], int n, int lowA, int highA, int lowB, int highB) {
2832

33+
// Take the A[middle], search its position in B array
2934
int mid = lowA + (highA - lowA)/2;
3035
int pos = binarySearch(B, lowB, highB, A[mid]);
3136
int num = mid + pos;
37+
// If the A[middle] in B is B's middle place, then we can have the result
3238
if (num == (m+n)/2){
39+
// If two arrays total length is odd, just simply return the A[mid]
40+
// Why not return the B[pos] instead ?
41+
// suppose A={ 1,3,5 } B={ 2,4 }, then mid=1, pos=1
42+
// suppose A={ 3,5 } B={1,2,4}, then mid=0, pos=2
43+
// suppose A={ 1,3,4,5 } B={2}, then mid=1, pos=1
44+
// You can see, the `pos` is the place A[mid] can be inserted, so return A[mid]
3345
if ((m+n)%2==1){
3446
return A[mid];
3547
}
48+
49+
// If tow arrys total length is even, then we have to find the next one.
3650
int next;
3751

52+
// If both `mid` and `pos` are not the first postion.
53+
// Then, find max(A[mid-1], B[pos-1]).
54+
// Because the `mid` is the second middle number, we need to find the first middle number
55+
// Be careful about the edge case
3856
if (mid>0 && pos>0){
3957
next = A[mid-1]>B[pos-1] ? A[mid-1] : B[pos-1];
4058
}else if(pos>0){
@@ -45,14 +63,23 @@ double findMedianSortedArrayHelper(int A[], int m, int B[], int n, int lowA, int
4563

4664
return (A[mid] + next)/2.0;
4765
}
66+
// if A[mid] is in the left middle place of the whole two arrays
67+
//
68+
// A(len=16) B(len=10)
69+
// [................] [...........]
70+
// ^ ^
71+
// mid=7 pos=1
72+
//
73+
// move the `low` pointer to the "middle" position, do next iteration.
4874
if (num < (m+n)/2){
4975
lowA = mid + 1;
50-
lowB = pos;
76+
lowB = pos;
5177
if ( highA - lowA > highB - lowB ) {
5278
return findMedianSortedArrayHelper(A, m, B, n, lowA, highA, lowB, highB);
5379
}
5480
return findMedianSortedArrayHelper(B, n, A, m, lowB, highB, lowA, highA);
5581
}
82+
// if A[mid] is in the right middle place of the whole two arrays
5683
if (num > (m+n)/2) {
5784
highA = mid - 1;
5885
highB = pos-1;
@@ -65,11 +92,17 @@ double findMedianSortedArrayHelper(int A[], int m, int B[], int n, int lowA, int
6592
}
6693

6794
double findMedianSortedArrays(int A[], int m, int B[], int n) {
95+
96+
//checking the edge cases
6897
if ( m==0 && n==0 ) return 0.0;
98+
99+
//if the length of array is odd, return the middle one
100+
//if the length of array is even, return the average of the middle two numbers
69101
if ( m==0 ) return n%2==1 ? B[n/2] : (B[n/2-1] + B[n/2])/2.0;
70102
if ( n==0 ) return m%2==1 ? A[m/2] : (A[m/2-1] + A[m/2])/2.0;
71103

72104

105+
//let the longer array be A, and the shoter array be B
73106
if ( m > n ){
74107
return findMedianSortedArrayHelper(A, m, B, n, 0, m-1, 0, n-1);
75108
}

src/mergeIntervals/mergeIntervals.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ struct Interval {
2525
Interval(int s, int e) : start(s), end(e) {}
2626
};
2727

28+
//Two factos sorting [start:end]
2829
bool compare(const Interval& lhs, const Interval& rhs){
2930
return (lhs.start==rhs.start) ? lhs.end < rhs.end : lhs.start < rhs.start;
3031
}
@@ -34,10 +35,12 @@ vector<Interval> merge(vector<Interval> &intervals) {
3435
vector<Interval> result;
3536

3637
if (intervals.size() <= 0) return result;
37-
38+
//sort the inervals. Note: using the customized comparing function.
3839
sort(intervals.begin(), intervals.end(), compare);
3940
for(int i=0; i<intervals.size(); i++) {
4041
int size = result.size();
42+
// if the current intervals[i] is overlapped with previous interval.
43+
// merge them together
4144
if( size>0 && result[size-1].end >= intervals[i].start) {
4245
result[size-1].end = max(result[size-1].end, intervals[i].end);
4346
}else{

src/nQueens/nQueuens.II.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ int totalNQueens(int n) {
3131
return result;
3232
}
3333

34-
34+
// the solution is same as the "N Queens" problem.
3535
void solveNQueensRecursive(int n, int currentRow, vector<int>& solution, int& result) {
3636

3737
for (int i = 0; i < n; i++) {

src/nQueens/nQueuens.cpp

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -50,34 +50,40 @@ vector< vector<string> > solveNQueens(int n) {
5050
return result;
5151
}
5252

53-
53+
//The following recursion is easy to understand. Nothing's tricky.
54+
// 1) recursively find all of possible columns row by row.
55+
// 2) solution[] array only stores the columns index. `solution[row] = col;`
5456
void solveNQueensRecursive(int n, int currentRow, vector<int>& solution, vector< vector<string> >& result) {
57+
//if no more row need to do, shape the result
5558
if (currentRow == n){
5659
vector<string> s;
57-
for (int i = 0; i < n; i++) {
58-
string row;
59-
for (int j = 0; j < n; j++) {
60-
if ( solution[i]== j ) {
61-
row += "Q";
62-
}else{
63-
row += ".";
64-
}
60+
for (int row = 0; row < n; row++) {
61+
string sRow;
62+
for (int col = 0; col < n; col++) {
63+
sRow = sRow + (solution[row] == col ? "Q" :"." );
6564
}
66-
s.push_back(row);
65+
s.push_back(sRow);
6766
}
6867
result.push_back(s);
6968
return;
7069
}
7170

72-
for (int i = 0; i < n; i++) {
73-
if (isValid(i, currentRow, solution) ) {
74-
solution[currentRow] = i;
71+
//for each column
72+
for (int col = 0; col < n; col++) {
73+
//if the current column is valid
74+
if (isValid(col, currentRow, solution) ) {
75+
//place the Queue
76+
solution[currentRow] = col;
77+
//recursively put the Queen in next row
7578
solveNQueensRecursive(n, currentRow+1, solution, result);
7679
}
7780
}
7881
}
7982

80-
83+
//Attempting to put the Queen into [row, col], check it is valid or not
84+
//Notes:
85+
// 1) we just checking the Column not Row, because the row cannot be conflicted
86+
// 2) to check the diagonal, we just check |x'-x| == |y'-y|, (x',y') is a Queen will be placed
8187
bool isValid(int attemptedColumn, int attemptedRow, vector<int> &queenInColumn) {
8288

8389
for(int i=0; i<attemptedRow; i++) {

src/permutations/permutations.II.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@
2121
#include <algorithm>
2222
using namespace std;
2323

24+
// To deal with the duplication number, we need do those modifications:
25+
// 1) sort the array [pos..n].
26+
// 2) skip the same number.
2427
vector<vector<int> > permute(vector<int> &num) {
2528

2629
vector<vector<int> > vv;

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy