├── Solutions ├── Chapter 11 Testing │ └── Chapter 11.md ├── Chapter 13 CPP │ ├── Chapter 13.md │ ├── 13.6.cpp │ ├── 13.1.cpp │ ├── 13.1.in │ ├── 13.9.cpp │ └── 13.8.cpp ├── Chapter 20 Hard │ ├── Chapter 20.md │ ├── 20.12.in │ ├── 20.11.in │ ├── 20.3.cpp │ ├── 20.1.cpp │ ├── 20.2.cpp │ ├── 20.5.cpp │ ├── 20.12.cpp │ ├── hash.h │ ├── 20.7.cpp │ ├── 20.8.cpp │ ├── 20.4.cpp │ ├── 20.11.cpp │ ├── 20.9.cpp │ ├── ac_automation.cpp │ ├── 20.6.cpp │ ├── 20.10.cpp │ └── 20.13.cpp ├── Chapter 8 Recursion │ ├── Chapter 8.md │ ├── 8.2.in │ ├── 8.6.in │ ├── 8.8.cpp │ ├── 8.5.cpp │ ├── 8.4.cpp │ ├── 8.6.cpp │ ├── 8.3.cpp │ ├── 8.1.cpp │ ├── 8.7.cpp │ └── 8.2.cpp ├── Chapter 10 Mathematical │ ├── Chapter 10.md │ ├── 10.4.cpp │ ├── 10.7.cpp │ └── 10.6.cpp ├── Chapter 19 Moderate │ ├── Chapter 19.md │ ├── 19.10.cpp │ ├── 19.1.cpp │ ├── 19.4.cpp │ ├── 19.3.cpp │ ├── 19.11.cpp │ ├── 19.7.cpp │ ├── 19.8.cpp │ ├── 19.2.cpp │ └── 19.5.cpp ├── Chapter 2 Linked Lists │ ├── Chapter 2.md │ ├── 2.2.cpp │ ├── 2.3.cpp │ ├── 2.5.cpp │ ├── 2.1.cpp │ └── 2.4.cpp ├── Chapter 6 Brain Teasers │ └── Chapter 6.md ├── Chapter 1 Arrays and Strings │ ├── Chapter 1.md │ ├── 1.2.cpp │ ├── 1.8.cpp │ ├── 1.4.cpp │ ├── 1.1.cpp │ ├── 1.7.cpp │ ├── 1.6.cpp │ ├── 1.5.cpp │ └── 1.3.cpp ├── Chapter 3 Stacks and Queues │ ├── Chapter 3.md │ ├── 3.6.cpp │ ├── 3.4.cpp │ ├── 3.1.cpp │ ├── 3.5.cpp │ ├── 3.2.cpp │ └── 3.3.cpp ├── Chapter 4 Trees and Graphs │ ├── Chapter 4.md │ ├── BST.in │ ├── 4.2.in │ ├── 4.3.cpp │ ├── 4.2.cpp │ ├── 4.5.cpp │ ├── 4.1.cpp │ ├── 4.7.cpp │ ├── 4.4.cpp │ ├── 4.8.cpp │ ├── 4.6.cpp │ └── BST.cpp ├── Chapter 5 Bit Manipulation │ ├── Chapter 5.md │ ├── 5.5.cpp │ ├── 5.2.cpp │ ├── 5.6.cpp │ ├── 5.1.cpp │ ├── 5.7.cpp │ └── 5.3.cpp ├── Chapter 7 Object Oriented Design │ └── Chapter 7.md ├── Chapter 9 Sorting and Searching │ ├── Chapter 9.md │ ├── 9.2.cpp │ ├── 9.1.0.cpp │ ├── 9.6.cpp │ ├── 9.1.1.cpp │ ├── 9.5.cpp │ ├── 9.3.cpp │ └── 9.7.cpp └── Chapter 12 System Design and Memory Limits │ ├── Chapter 12.md │ ├── 12.4.cpp │ └── 12.3.cpp ├── Book ├── back.jpg ├── front.jpg ├── DSA Guide.pdf ├── DSA Lecture Notes.pdf ├── Algorithms Complete Notes.pdf └── README.md └── README.md /Solutions/Chapter 11 Testing/Chapter 11.md: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /Solutions/Chapter 13 CPP/Chapter 13.md: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /Solutions/Chapter 20 Hard/Chapter 20.md: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /Solutions/Chapter 8 Recursion/Chapter 8.md: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /Solutions/Chapter 10 Mathematical/Chapter 10.md: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /Solutions/Chapter 19 Moderate/Chapter 19.md: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /Solutions/Chapter 2 Linked Lists/Chapter 2.md: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /Solutions/Chapter 6 Brain Teasers/Chapter 6.md: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /Solutions/Chapter 1 Arrays and Strings/Chapter 1.md: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /Solutions/Chapter 3 Stacks and Queues/Chapter 3.md: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /Solutions/Chapter 4 Trees and Graphs/Chapter 4.md: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /Solutions/Chapter 5 Bit Manipulation/Chapter 5.md: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /Solutions/Chapter 7 Object Oriented Design/Chapter 7.md: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /Solutions/Chapter 9 Sorting and Searching/Chapter 9.md: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /Solutions/Chapter 4 Trees and Graphs/BST.in: -------------------------------------------------------------------------------- 1 | 2 4 3 1 9 0 7 6 8 5 2 | -------------------------------------------------------------------------------- /Solutions/Chapter 12 System Design and Memory Limits/Chapter 12.md: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /Solutions/Chapter 8 Recursion/8.2.in: -------------------------------------------------------------------------------- 1 | 3 4 2 | 1 1 1 0 3 | 0 1 1 1 4 | 1 1 1 1 5 | -------------------------------------------------------------------------------- /Solutions/Chapter 20 Hard/20.12.in: -------------------------------------------------------------------------------- 1 | 4 2 | -1 0 -2 1 3 | -4 9 3 2 4 | -1 2 3 -1 5 | 0 11 -2 3 6 | -------------------------------------------------------------------------------- /Book/back.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/black-shadows/Cracking-the-Coding-Interview/HEAD/Book/back.jpg -------------------------------------------------------------------------------- /Book/front.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/black-shadows/Cracking-the-Coding-Interview/HEAD/Book/front.jpg -------------------------------------------------------------------------------- /Book/DSA Guide.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/black-shadows/Cracking-the-Coding-Interview/HEAD/Book/DSA Guide.pdf -------------------------------------------------------------------------------- /Book/DSA Lecture Notes.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/black-shadows/Cracking-the-Coding-Interview/HEAD/Book/DSA Lecture Notes.pdf -------------------------------------------------------------------------------- /Book/Algorithms Complete Notes.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/black-shadows/Cracking-the-Coding-Interview/HEAD/Book/Algorithms Complete Notes.pdf -------------------------------------------------------------------------------- /Solutions/Chapter 8 Recursion/8.6.in: -------------------------------------------------------------------------------- 1 | 5 5 2 | 3 | 0 3 3 2 1 4 | 5 | 3 0 1 3 3 6 | 7 | 3 3 0 2 3 8 | 9 | 0 3 3 3 1 10 | 11 | 0 1 0 2 1 12 | -------------------------------------------------------------------------------- /Solutions/Chapter 20 Hard/20.11.in: -------------------------------------------------------------------------------- 1 | 8 2 | 1 1 1 1 0 1 0 1 3 | 1 0 0 0 0 0 1 1 4 | 1 0 1 1 1 0 1 1 5 | 1 0 0 1 0 0 1 1 6 | 1 0 1 1 1 0 1 0 7 | 1 0 0 0 0 0 0 0 8 | 1 1 1 0 1 0 1 0 9 | 0 1 1 0 0 1 1 1 10 | -------------------------------------------------------------------------------- /Solutions/Chapter 4 Trees and Graphs/4.2.in: -------------------------------------------------------------------------------- 1 | 8 11 2 | 3 | 0 1 4 | 5 | 1 0 6 | 7 | 1 5 8 | 9 | 2 3 10 | 11 | 2 4 12 | 13 | 4 7 14 | 15 | 5 2 16 | 17 | 5 7 18 | 19 | 6 2 20 | 21 | 6 4 22 | 23 | 7 4 24 | -------------------------------------------------------------------------------- /Solutions/Chapter 19 Moderate/19.10.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Q 19.10 Write a method to generate a random number between 1 and 7, 3 | * given a method that generates a random number between 1 and 5(i.e.,implement rand7()using rand5()). 4 | */ 5 | 6 | #include 7 | using namespace std; 8 | 9 | int Rand5(){ 10 | int x = ~(1<<31); // max int 11 | while(x > 5) 12 | x = Rand7(); 13 | return x; 14 | } 15 | int main() 16 | { 17 | return 0; 18 | } 19 | -------------------------------------------------------------------------------- /Book/README.md: -------------------------------------------------------------------------------- 1 | ```sh 2 | Here is the link from where you can download Cracking the Coding Interview, 6th Edition - Gayle Laakmann McDowell. 3 | ``` 4 | [Cracking the Coding Interview 189 Programming Questions and Solutions, 6th Edition - Gayle Laakmann McDowell](https://mega.nz/file/z5ZSHarb#3DTjWmyQpgXSF0IqsLaols-A2oEQ8QQGkIklGzxotP8) 5 | 6 | ```sh 7 | (Bonus) Here is the link from where you can download Data Structures and Algorithms Made Easy - Narasimha Karumanchi. 8 | ``` 9 | 10 | [Data Structures and Algorithms - Narasimha Karumanchi](https://mega.nz/file/20JSBIJD#QJwI5JJCWEoQ_VXSuHRpfqgZnWS7li07PCjONhTX1xc) 11 | -------------------------------------------------------------------------------- /Solutions/Chapter 9 Sorting and Searching/9.2.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Q 9.2 Write a method to sort an array of strings so that all the anagrams are next to each other. 3 | */ 4 | 5 | #include 6 | #include 7 | #include 8 | using namespace std; 9 | 10 | bool cmp(string s1, string s2) 11 | { 12 | sort(&s1[0],&s1[0]+s1.length()); 13 | sort(&s2[0], &s2[0] + s2.length()); 14 | return s1 < s2; 15 | } 16 | 17 | int main() 18 | { 19 | string s[] = { "axyz","zyxa","evil","live","kcuf","fuck" }; 20 | sort(s, s + 7, cmp); 21 | for (int i = 0; i < 7; ++i) 22 | cout << s[i] << endl; 23 | return 0; 24 | } 25 | -------------------------------------------------------------------------------- /Solutions/Chapter 19 Moderate/19.1.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Q 19.1 Write a function to swap a number in place without temporary variables. 3 | */ 4 | 5 | #include 6 | using namespace std; 7 | 8 | void swap1(int &a, int &b) 9 | { 10 | a = a^b; 11 | b = a^b; 12 | a = a^b; 13 | } 14 | 15 | void swap2(int &a, int &b) 16 | { 17 | b = a - b; 18 | a = a - b; 19 | b = a + b; 20 | } 21 | 22 | void swap3(int &a, int &b) 23 | { 24 | int t = a; 25 | a = b; 26 | b = t; 27 | } 28 | 29 | int main() 30 | { 31 | int a = 123; 32 | int b = 456; 33 | swap1(a, b); 34 | cout << a << endl; 35 | cout << b << endl; 36 | } 37 | -------------------------------------------------------------------------------- /Solutions/Chapter 19 Moderate/19.4.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Q 19.4 Write a method which finds the maximum of two numbers. You should not use if-else or any other comparison operator. 3 | */ 4 | 5 | #include 6 | using namespace std; 7 | 8 | int Max1(int a, int b) 9 | { 10 | int c[2] = { a,b }; 11 | int z = a - b; 12 | z = (z >> 31) & 1; 13 | return c[z]; 14 | } 15 | 16 | int Max2(int a, int b) 17 | { 18 | int z = a - b; 19 | int k = (z >> 31) & 1; 20 | return a - k*z; 21 | } 22 | 23 | int main() 24 | { 25 | int a = 5, b = 10; 26 | cout << Max1(a, b) << endl; 27 | cout << Max2(a, b) << endl; 28 | return 0; 29 | } 30 | -------------------------------------------------------------------------------- /Solutions/Chapter 13 CPP/13.6.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Q 13.6 What is name hiding in C++? 3 | */ 4 | 5 | #include 6 | using namespace std; 7 | 8 | class FirstClass { 9 | public: 10 | virtual void MethodA(int) { 11 | cout << "ForstClass::MethodA(int)" << endl; 12 | } 13 | virtual void MethodA(int, int) { 14 | cout << "FirstClass::MethodA(int,int)" << endl; 15 | } 16 | }; 17 | 18 | class SecondClass :public FirstClass { 19 | public: 20 | void MethodA1(int, int, int) { 21 | cout << "SecondClass::MethodA(int)" << endl; 22 | } 23 | }; 24 | 25 | int main() { 26 | SecondClass sc; 27 | sc.MethodA(0,0); 28 | return 0; 29 | } 30 | -------------------------------------------------------------------------------- /Solutions/Chapter 19 Moderate/19.3.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Q 19.3 Write an algorithm which computes the number of trailing zeros in n factorial. 3 | */ 4 | 5 | #include 6 | using namespace std; 7 | 8 | int NumZeros(int n) 9 | { 10 | if (n < 0) return -1; 11 | int num = 0; 12 | while ((n /= 5) > 0) 13 | { 14 | num += n; 15 | } 16 | return num; 17 | } 18 | 19 | int NumZero1(int n) 20 | { 21 | if (n < 0) return -1; 22 | int num = 0; 23 | for (int i = 5; n > i > 0; i *= 5) 24 | num += n / i; 25 | return num; 26 | } 27 | 28 | int main() 29 | { 30 | for (int i = 1; i < 100; ++i) 31 | { 32 | if (NumZeros(i) == NumZero1(i)) 33 | cout << i << endl; 34 | } 35 | return 0; 36 | } 37 | -------------------------------------------------------------------------------- /Solutions/Chapter 5 Bit Manipulation/5.5.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | *Q5.5 Write a function to determine the number of bits required to convert integer A to B. 3 | *Input:31,14 4 | *Output:2 5 | */ 6 | 7 | #include 8 | using namespace std; 9 | 10 | int count_one(int x) 11 | { 12 | x = (x&(0x55555555))+((x>>1)&(0x55555555)); 13 | x = (x&(0x33333333))+((x>>2)&(0x33333333)); 14 | x = (x&(0x0f0f0f0f))+((x>>4)&(0x0f0f0f0f)); 15 | x = (x&(0x00ff00ff))+((x>>8)&(0x00ff00ff)); 16 | x = (x&(0x0000ffff))+((x>>16)&(0x0000ffff)); 17 | return x; 18 | } 19 | int convert_num(int a, int b) 20 | { 21 | return count_one(a^b); 22 | } 23 | int main() 24 | { 25 | int a = 7, b = 14; 26 | cout << convert_num(a, b) << endl; 27 | return 0; 28 | } 29 | -------------------------------------------------------------------------------- /Solutions/Chapter 9 Sorting and Searching/9.1.0.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Q 9.1 You have two sorted arrays,A and B,and A has a large enough buffer at the end to hold B. 3 | * Write a method to merge B into A in sorted order. 4 | */ 5 | 6 | #include 7 | using namespace std; 8 | 9 | void merge(int a[], int b[], int n, int m) 10 | { 11 | int k = n + m - 1; 12 | int i = n - 1, j = m - 1; 13 | while (i <= 0 && j >= 0) 14 | { 15 | if (a[i] > b[j]) a[k--] = a[i--]; 16 | else a[k--] = b[j--]; 17 | } 18 | while (j >= 0) a[k--] = b[j--]; 19 | } 20 | 21 | int main() 22 | { 23 | int a[15] = { 1,3,7,8,9 }; 24 | int b[] = { 2,4,5,6,10 }; 25 | int n = 5, m = 5; 26 | merge(a, b, 5, 5); 27 | for (int i = 0; i < m + n; ++i) 28 | cout << a[i] << " "; 29 | return 0; 30 | } 31 | -------------------------------------------------------------------------------- /Solutions/Chapter 20 Hard/20.3.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Q 20.3 Write a method to randomly generate a set of m integers grom an array of size n.Each element must have probabaility of being chosen. 3 | */ 4 | 5 | #include 6 | #include 7 | #include 8 | using namespace std; 9 | 10 | void Swap(int &a, int &b) 11 | { 12 | int t = a; 13 | a = b; 14 | b = t; 15 | } 16 | void PickMRandomly(int a[], int n, int m) 17 | { 18 | for (int i = 0; i < m; ++i) 19 | { 20 | int j = rand() % (n - i) + i; 21 | Swap(a[i], a[j]); 22 | } 23 | } 24 | int main() 25 | { 26 | srand((unsigned)time(0)); 27 | int n = 9, m = 5; 28 | int a[] = {1,2,3,4,5,6,7,8,9}; 29 | PickMRandomly(a, n, m); 30 | for (int i = 0; i < m; ++i) 31 | cout << a[i] << endl; 32 | return 0; 33 | } 34 | -------------------------------------------------------------------------------- /Solutions/Chapter 1 Arrays and Strings/1.2.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | *Q1.2 Write code to reverse a C-Style String.(S-String means that "abcd" is represented as five charaters,including the null charater.) 3 | */ 4 | 5 | #include 6 | #include 7 | using namespace std; 8 | 9 | void swap(char &a, char &b) 10 | { 11 | a = a^b; 12 | b = a^b; 13 | a = a^b; 14 | } 15 | 16 | void reverse2(char *s) 17 | { 18 | int n = strlen(s); 19 | for (int i = 0; i < n / 2; ++i) 20 | swap(s[i],s[n-i-1]); 21 | } 22 | 23 | void reverse1(char *s) 24 | { 25 | if (!s) return; 26 | char *p = s, *q = s; 27 | while (*q) ++q; 28 | --q; 29 | while (p < q) 30 | swap(*p++, *q--); 31 | } 32 | 33 | int main() 34 | { 35 | char s[] = "1234567890asdfghjkl"; 36 | reverse1(s); 37 | cout << s << endl; 38 | return 0; 39 | } 40 | -------------------------------------------------------------------------------- /Solutions/Chapter 9 Sorting and Searching/9.6.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Q 9.6 Given a matrix in which each row and each column is sorted, write a method to find an element in it. 3 | */ 4 | 5 | #include 6 | #include 7 | using namespace std; 8 | 9 | int d[20][20]; 10 | int search(int m, int n, int x) 11 | { 12 | int r = 0, c = n - 1; 13 | while (r < m&&c >= 0) 14 | { 15 | if (d[r][c] == x) return (r*n +c); 16 | else if (d[r][c] < x) ++r; 17 | else --c; 18 | } 19 | return -1; 20 | } 21 | 22 | int main() 23 | { 24 | freopen("9.6.in","r",stdin); 25 | int m, n; 26 | cin >> m >> n; 27 | for (int i = 0; i < m; ++i) 28 | for (int j = 0; j < n; ++j) 29 | cin >> d[i][j]; 30 | 31 | int k = search(m,n,13); 32 | if (k == -1) cout << "not found" << endl; 33 | fclose(stdin); 34 | return 0; 35 | } 36 | -------------------------------------------------------------------------------- /Solutions/Chapter 1 Arrays and Strings/1.8.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | *Q1.8 Assume you have a method isSubstring which checks if one word is a substring of another. 3 | *Given two things,s1 and s2,write code to check if s2 is a rotation of s1 using only one call 4 | *to isSubstring(i.e.,"waterbottlde"is a rotation of"erbottlewat"). 5 | */ 6 | 7 | #include 8 | #include 9 | using namespace std; 10 | 11 | bool isSubstring(string s1, string s2) 12 | { 13 | if (s1.find(s2) != string::npos) return true; 14 | else return false; 15 | } 16 | 17 | bool isRotation(string s1, string s2) 18 | { 19 | if (s1.length() != s2.length() || s1.length() <= 0) 20 | return false; 21 | return isSubstring(s1+s2,s2); 22 | } 23 | 24 | int main() 25 | { 26 | string s1 = "apple"; 27 | string s2 = "pleap"; 28 | cout << isRotation(s1, s2) << endl; 29 | return 0; 30 | } 31 | -------------------------------------------------------------------------------- /Solutions/Chapter 20 Hard/20.1.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Q 20.1 Write a function that adds two numbers. 3 | * You should not use + or any arithmetic operators. 4 | */ 5 | 6 | #include 7 | using namespace std; 8 | 9 | int Add1(int a, int b) 10 | { 11 | char *c = (char*)a; 12 | return (int)&c[b];// c+sizeof(char)*b=a+b 13 | } 14 | 15 | int Add2(int a, int b) 16 | { 17 | if (b == 0) return a; 18 | int sum = a^b;// 19 | int carry = (a&b) << 1;// 20 | return Add2(sum, carry);// 21 | } 22 | 23 | int Add3(int a, int b) 24 | { 25 | while (b != 0) 26 | { 27 | int sum = a^b; 28 | int carry = (a&b) << 1; 29 | a = sum; 30 | b = carry; 31 | } 32 | return a; 33 | } 34 | 35 | int main() 36 | { 37 | int a = 70, b = -134310; 38 | cout << Add1(a, b) << endl; 39 | cout << Add2(a, b) << endl; 40 | cout << Add3(a, b) << endl; 41 | return 0; 42 | } 43 | -------------------------------------------------------------------------------- /Solutions/Chapter 19 Moderate/19.11.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Q 19.11 Design an algorithm to find all pairs of integers within an array which sum to a specified value. 3 | */ 4 | 5 | #include 6 | #include 7 | using namespace std; 8 | 9 | void PrintPairSum(int a[], int n, int sum){ 10 | if(a==NULL || n<2) return; 11 | 12 | sort(a, a+n); 13 | int low = 0, high = n-1; 14 | while(low < high){ 15 | if(a[low]+a[high] > sum) 16 | --high; 17 | else if(a[low]+a[high] < sum) 18 | ++low; 19 | else{ 20 | cout< 6 | #include 7 | #include 8 | using namespace std; 9 | 10 | void printLastKLines(ifstream &fin, int k) 11 | { 12 | //std::string *line = new line[k]; 13 | std::string line[k]; 14 | int lines = 0; 15 | string tmp; 16 | while (getline(fin, tmp)) 17 | { 18 | line[line%k] = tmp; 19 | ++lines; 20 | } 21 | int start, cnt; 22 | if (lines < k) 23 | { 24 | start = 0; 25 | cnt = lines; 26 | } 27 | else 28 | { 29 | start = lines%k; 30 | cnt = k; 31 | } 32 | for (int i = 0; i < cnt; ++i) 33 | cout << line[(start + i) % k] << endl; 34 | } 35 | int main() 36 | { 37 | ifstream fin("13.3.in"); 38 | int k = 4; 39 | printLastKLines(fin,k); 40 | fin.close(); 41 | return 0; 42 | } 43 | -------------------------------------------------------------------------------- /Solutions/Chapter 20 Hard/20.2.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Q 20.2 Write a method to shuffle a deck of cards.It must be a perfect shuffle - in other words,each 52! permutations of the deck has to be equally likely. 3 | * Assume that you are given a random number generator which is perfect. 4 | */ 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | using namespace std; 11 | 12 | void Swap(int &a, int &b) 13 | { 14 | int t = a; 15 | a = b; 16 | b = t; 17 | } 18 | void RandomShuffle(int a[], int n) 19 | { 20 | for (int i = 0; i < n; ++i) 21 | { 22 | int j = rand() % (n - i) + i; 23 | Swap(a[i], a[j]); 24 | } 25 | } 26 | int main() 27 | { 28 | srand((unsigned)time(0)); 29 | int n = 9; 30 | int a[] = { 1,2,3,4,5,6,7,8,9 }; 31 | RandomShuffle(a, n); 32 | for (int i = 0; i < n; ++i) 33 | cout << a[i] << endl; 34 | return 0; 35 | } 36 | -------------------------------------------------------------------------------- /Solutions/Chapter 9 Sorting and Searching/9.1.1.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Q 9.1 You are given two sorted arrays, A and B, and A has a large enough buffer at the end to hold B. Write a method to merge B into A in sorted order. 3 | */ 4 | 5 | #include 6 | using namespace std; 7 | 8 | void swap(int &a, int &b) 9 | { 10 | a = a^b; 11 | b = a^b; 12 | a = a^b; 13 | } 14 | 15 | void merge(int a[], int begin, int mid, int end) 16 | { 17 | for (int i = begin; i <= mid; ++i) 18 | { 19 | if (a[i] > a[mid + 1]) 20 | { 21 | swap(a[i], a[mid + 1]); 22 | for (int j = mid + 1; j < end; ++j) 23 | { 24 | if (a[j] <= a[j + 1]) break; 25 | swap(a[j], a[j + 1]); 26 | } 27 | } 28 | } 29 | } 30 | 31 | int main() 32 | { 33 | int a[10] = { 8,9,11,15,17,1,3,5,12,18 }; 34 | int b[10] = {1,2,3,4,5,6,7,8,9,10}; 35 | merge(a,0,4,9); 36 | for (int i = 0; i < 10; ++i) 37 | cout << a[i] << " "; 38 | return 0; 39 | } 40 | -------------------------------------------------------------------------------- /Solutions/Chapter 8 Recursion/8.8.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Q 8.8 Eight Queens 3 | * Write an algorithm to print all ways of arranging eight queens on a chess board so that none of them share the same row, column or diagonal. 4 | */ 5 | 6 | #include 7 | using namespace std; 8 | 9 | int c[20], n = 8, cnt = 0; 10 | void print() 11 | { 12 | for(int i=0;i 9 | #include 10 | #include 11 | using namespace std; 12 | 13 | void print_pare(int l, int r, char str[], int cnt) 14 | { 15 | if (l < 0 || r < l) return; 16 | if (l == 0 && r == 0) 17 | { 18 | for (int i = 0;i < cnt; ++i) 19 | { 20 | cout << str[i]; 21 | } 22 | cout << ","; 23 | } 24 | else 25 | { 26 | if (l > 0) 27 | { 28 | str[cnt] = '('; 29 | print_pare(l - 1,r,str,cnt+1); 30 | } 31 | if (r > l) 32 | { 33 | str[cnt] = ')'; 34 | print_pare(l, r - 1, str, cnt + 1); 35 | } 36 | } 37 | } 38 | int main() 39 | { 40 | const int cnt = 3; 41 | char str[2*cnt]; 42 | print_pare(cnt, cnt, str, 0); 43 | return 0; 44 | } 45 | -------------------------------------------------------------------------------- /Solutions/Chapter 19 Moderate/19.7.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Q 19.7 You are given an array of integers (both positive and negative). 3 | * Find the continuous sequence with the largest sum. Return the sum. 4 | * Example: 5 | * Input:{2,-8,3,-2,4,10} 6 | * Output:{i.e.,{3,-2,4}} 7 | */ 8 | 9 | #include 10 | using namespace std; 11 | 12 | bool g_Invalid = false; 13 | 14 | int GetMaxSum(int a[], int n) 15 | { 16 | if (a == NULL || n <= 0) 17 | { 18 | g_Invalid = true; 19 | return 0; 20 | } 21 | g_Invalid = false; 22 | 23 | int max_sum = 11 << 31;//Min iNT 24 | int cur_sum = 0; 25 | for (int i = 0; i < n; ++i) 26 | { 27 | if (cur_sum <= 0) 28 | cur_sum = a[i]; 29 | else 30 | cur_sum += a[i]; 31 | 32 | if (cur_sum > max_sum) 33 | max_sum = cur_sum; 34 | } 35 | 36 | return max_sum; 37 | } 38 | 39 | int main() 40 | { 41 | int a[] = { 2,-8,3,-2,4,-10 }; 42 | int max_sum = GetMaxSum(a, 6); 43 | if (g_Invalid) 44 | cout << "Invalid Input!" << endl; 45 | else 46 | cout << max_sum << endl; 47 | return 0; 48 | } 49 | -------------------------------------------------------------------------------- /Solutions/Chapter 1 Arrays and Strings/1.4.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | *Q1.4 Write a method to decide if two strings are anagrams or not. 3 | */ 4 | 5 | #include 6 | #include 7 | #include 8 | using namespace std; 9 | 10 | bool isAnagram1(string s, string t) 11 | { 12 | if (s == "" || t == "") return false; 13 | if (s.length() != t.length()) return false; 14 | 15 | sort(&s[0],&s[0]+s.length()); 16 | sort(&t[0],&t[0]+t.length()); 17 | if (s == t) return true; 18 | else return false; 19 | } 20 | 21 | bool isAnagram(string s, string t) 22 | { 23 | if (s == "" || t == "") return false; 24 | if (s.length() != t.length()) return false; 25 | 26 | int len = s.length(); 27 | int c[256]; 28 | memset(c,0,sizeof(c)); 29 | for (int i = 0; i < len; ++i) 30 | { 31 | ++c[(int)s[i]]; 32 | --c[(int)t[i]]; 33 | } 34 | 35 | for (int i = 0; i < 256; +i) 36 | if (c[i] != 0) 37 | return false; 38 | return true; 39 | } 40 | int main() 41 | { 42 | string s = "aaabbb"; 43 | string t = "ababab"; 44 | cout << isAnagram(s, t) << endl; 45 | return 0; 46 | } 47 | -------------------------------------------------------------------------------- /Solutions/Chapter 9 Sorting and Searching/9.5.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Q 9.5 Given a sorted array of strings which is interspersed with empty strings, write a method to find the location of a given string. 3 | * Example: find “ball” in [“at”, “”, “”, “”, “ball”, “”, “”, “car”, “”,“”, “dad”, “”, “”] will return 4 4 | * Example: find “ballcar” in [“at”, “”, “”, “”, “”, “ball”, “car”, “”, “”, “dad”, “”, “”] will return -1 5 | */ 6 | 7 | #include 8 | #include 9 | using namespace std; 10 | 11 | int search(string s[], int low, int high, string x) 12 | { 13 | if (x == "") return -1; 14 | while (low < high) 15 | { 16 | int mid = (low + high) >> 1; 17 | int t = mid; 18 | while (s[t] == ""&&t <= high) ++t; 19 | if (t > high) high = mid - 1; 20 | else 21 | { 22 | if (s[t] == x) return t; 23 | else if (s[t] < x) low = t + 1; 24 | else high = mid - 1; 25 | } 26 | } 27 | return -1; 28 | } 29 | 30 | int main() 31 | { 32 | string s[13] = { "at", "", "", "", "ball", "", "", "car", "", "", "dad", "", "" }; 33 | cout << search(s, 0, 12, "ball") << endl; 34 | return 0; 35 | } 36 | -------------------------------------------------------------------------------- /Solutions/Chapter 5 Bit Manipulation/5.2.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | *Q5.2 Given a(decimal - e.g.3.72)number that is passed in as a string,print the binary representation. 3 | *If the number can not be represented accuratedly,print "ERROR". 4 | */ 5 | 6 | #include 7 | #include 8 | #include 9 | using namespace std; 10 | 11 | string print_binary(string val) 12 | { 13 | int pos = val.find('.',0); 14 | int intpart = atoi(val.substr(0,pos).c_str()); 15 | double decpart = atof(val.substr(pos, val.length() - pos).c_str()); 16 | string intstr = "", decstr = ""; 17 | while (intpart > 0) 18 | { 19 | if (intpart & 1)intstr = "1" + intstr; 20 | else intstr = "0" + intstr; 21 | intpart >>= 1; 22 | } 23 | while (decpart > 0) 24 | { 25 | if (decstr.length() > 32) return "ERROR"; 26 | decpart *= 2; 27 | if (decpart >= 1) 28 | { 29 | decstr += "1"; 30 | decpart -= 1; 31 | } 32 | else 33 | decstr += "0"; 34 | } 35 | return intstr + "." + decstr; 36 | } 37 | int main() 38 | { 39 | string val = "19.25"; 40 | cout << print_binary(val) << endl; 41 | return 0; 42 | } 43 | -------------------------------------------------------------------------------- /Solutions/Chapter 19 Moderate/19.8.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * TASK: Given an input stream (e.g. to read from a file), count the number of 3 | * occurrences of each unique word read from the stream. 4 | */ 5 | 6 | #include 7 | #include 8 | 9 | /** 10 | * @brief Returns a map containing the number of occurrences of each unique 11 | * word read from an input stream. 12 | * @note Complexity: O(n*m*log(n)) in time, O(n*m) in space, where n is the 13 | * number of words in the input stream and m is the length of the longest 14 | * word. 15 | */ 16 | std::map count_words(std::istream& stream) 17 | { 18 | std::string word; 19 | 20 | std::map count; 21 | 22 | while (stream >> word) 23 | { 24 | ++count[word]; 25 | } 26 | 27 | return count; 28 | } 29 | 30 | int main() 31 | { 32 | std::map count = count_words(std::cin); 33 | 34 | for (const auto& p : count) 35 | { 36 | std::cout << p.first << ": " << p.second << "\n"; 37 | } 38 | 39 | return EXIT_SUCCESS; 40 | } 41 | -------------------------------------------------------------------------------- /Solutions/Chapter 1 Arrays and Strings/1.1.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | *Q1.1 Implement an algorithm to determine if a string has all unique characters.What if you can not use additional data structures? 3 | */ 4 | 5 | #include 6 | #include 7 | using namespace std; 8 | 9 | bool isUnique1(string s) 10 | { 11 | bool a[256]; 12 | memset(a,0,sizeof(a)); 13 | int len = s.length(); 14 | for (int i = 0; i < len; ++i) 15 | { 16 | int v = (int)s[i]; 17 | if (a[v]) return false; 18 | a[v] = true; 19 | } 20 | return true; 21 | } 22 | 23 | bool isUnique2(string s) 24 | { 25 | int a[8]; 26 | memset(a, 0, sizeof(a)); 27 | int len = s.length(); 28 | for (int i = 0; i < len; ++i) 29 | { 30 | int v = (int)s[i]; 31 | int idx = v / 32, shift = v % 32; 32 | if (a[idx] & (1 << shift)) return false; 33 | a[idx] |= (1 << shift); 34 | } 35 | return true; 36 | } 37 | 38 | int main() 39 | { 40 | string s1 = "Hello World!"; 41 | string s2 = "asdfghjkl1234567890"; 42 | cout << isUnique1(s1) << " " << isUnique1(s2) << endl; 43 | cout << isUnique2(s1) << " " << isUnique2(s2) << endl; 44 | return 0; 45 | } 46 | -------------------------------------------------------------------------------- /Solutions/Chapter 20 Hard/20.5.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Q 20.5 You have a large text file containing words. Given any two words, 3 | * find the shortest distance (in terms of number of words) between them in the file. 4 | * Can you make the searching operation in O(1) time? 5 | * What about the space complexity for your solution? 6 | */ 7 | 8 | #include 9 | using namespace std; 10 | 11 | const int kMaxInt = ~(1 << 31); 12 | 13 | int ShortestDist(string text[], int n, string word1, string word2) 14 | { 15 | int min = kMaxInt / 2; 16 | int pos1 = -min; 17 | int pos2 = -min; 18 | 19 | for (int pos = 0; pos < n; ++pos) 20 | { 21 | if (text[pos] == word1) 22 | { 23 | pos1 = pos; 24 | int dist = pos1 - pos2; 25 | if (dist < min) 26 | min = dist; 27 | } 28 | else if (text[pos] == word2) 29 | { 30 | pos2 = pos; 31 | int dist = pos2 - pos1; 32 | if (dist < min) 33 | min = dist; 34 | } 35 | } 36 | return min; 37 | } 38 | 39 | int main() 40 | { 41 | string text[] = { "To","be","Or","not","to","be","This","is","a","question" }; 42 | int len = 10; 43 | cout << ShortestDist(text, len, "Or", "is") << endl; 44 | return 0; 45 | } 46 | -------------------------------------------------------------------------------- /Solutions/Chapter 9 Sorting and Searching/9.3.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Q 9.3 Given a sorted array of n integers that has been rotated an unknown number of times, give an O(log n) algorithm that finds an element in the array. 3 | * You may assume that the array was originally sorted in increasing order. 4 | * Example: 5 | * Input: find 5 in array (15 16 19 20 25 1 3 4 5 7 10 14) 6 | * Output:8 (the index of 5 in the array) 7 | */ 8 | 9 | #include 10 | using namespace std; 11 | 12 | int search(int a[], int low, int high, int k) 13 | { 14 | while (low <= high) 15 | { 16 | int mid = low + (high - low) / 2; 17 | if (a[mid] == k) return mid; 18 | if (a[mid] >= a[low]) 19 | { 20 | if (k < a[mid] && k >= a[low]) 21 | high = mid - 1; 22 | else 23 | low = mid + 1; 24 | } 25 | else 26 | { 27 | if (k > a[mid] && k < a[low]) 28 | low = mid + 1; 29 | else 30 | high = mid - 1; 31 | } 32 | } 33 | return -1; 34 | } 35 | 36 | int main() 37 | { 38 | int a[12] = { 39 | 15, 16, 19, 20, 25, 1, 3, 4, 5, 7, 10, 14}; 40 | int b[19] = { 41 | 2,2,2,2,2,2,2,2,3,2,2,2,2,2,2,2,2,2,2}; 42 | cout << search(a, 0, 11, 3) << endl; 43 | return 0; 44 | } 45 | -------------------------------------------------------------------------------- /Solutions/Chapter 5 Bit Manipulation/5.6.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | *Q5.6 Write a program to swap odd and even bits in an integer with as few insttuctions as possible 3 | *(e.g.,bit 0 and bit 1 are swapped,bit 2 and bit 3 are swapped,etc) 4 | */ 5 | 6 | #include 7 | #include 8 | using namespace std; 9 | 10 | void print_binary(int x) 11 | { 12 | string s = ""; 13 | for (int i = 0; i < 32 && x != 0; ++i, x >>= 1) 14 | { 15 | if (x & 1) s = "1" + s; 16 | else s = "0" + s; 17 | } 18 | cout << s << endl; 19 | } 20 | 21 | //下面的代码思路和作用都是一样的,不过按照《Hacker’s delight》这本书里的说法, 第一种方法避免了在一个寄存器中生成两个大常量。 22 | //如果计算机没有与非指令, 将导致第二种方法多使用1个指令。总结之,就是第一种方法更好。 23 | 24 | int swap_bits(int x) 25 | { 26 | return ((x & 0x55555555) << 1) | ((x>>1)&0x55555555); 27 | } 28 | 29 | //x & 0xAAAAAAAA得出结果是unsigned,所以最高位为1时,右移1位,最高位是0 30 | 31 | int swap_bits1(int x) 32 | { 33 | return((x&0x55555555)<<1)|((x&0xAAAAAAAA)>>1); 34 | } 35 | int main() 36 | { 37 | int x = 0xFFFFFFFF; 38 | x = x & 0xFFFFFFFF; 39 | cout << (x & 0xFFFFFFFF) << endl; 40 | print_binary((x|0xFFFFFFFF)>>1); 41 | print_binary(x); 42 | print_binary(swap_bits(x)); 43 | print_binary(swap_bits1(x)); 44 | return 0; 45 | } 46 | -------------------------------------------------------------------------------- /Solutions/Chapter 5 Bit Manipulation/5.1.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | *Q5.1 You have given two 32-bit numbers,N and M,and two bit positions,i and j. 3 | *Write a method to set all bits between i and j in N equal to M 4 | *(E.G.,m becomes a subdtring of N located at i and starting at j). 5 | */ 6 | 7 | #include 8 | #include 9 | using namespace std; 10 | 11 | void print_binary(int n) 12 | { 13 | vector v; 14 | int len = 8 * sizeof(int); 15 | int mask = 1; 16 | while (len--) 17 | { 18 | if (n&mask) v.push_back(1); 19 | else v.push_back(0); 20 | mask <<= 1; 21 | } 22 | while (!v.empty()) 23 | { 24 | cout << v.back(); 25 | v.pop_back(); 26 | } 27 | cout << endl; 28 | } 29 | int update_bits(int n, int m, int i, int j) 30 | { 31 | int ret = (1 << i) - 1; 32 | ret &= n; 33 | return ((n >> (j + 1)) << (j + 1)) | (m << i) | ret; 34 | } 35 | int update_bit1(int n, int m, int i, int j) 36 | { 37 | int max = ~0; 38 | int left = max - ((1< 6 | #include 7 | #include 8 | using namespace std; 9 | 10 | void zero(int **a,int m, int n) 11 | { 12 | bool row[m],col[n]; 13 | memset(row,false,sizeof(row)); 14 | memset(col,false,sizeof(col)); 15 | for(int i=0;i> m >> n; 34 | int **a; 35 | a = new int*[m]; 36 | for (int i = 0; i < m; ++i) 37 | for (int j = 0; j < n; ++j) 38 | cin >> a[i][j]; 39 | for (int i = 0; i < m; ++i) 40 | { 41 | for (int j = 0; j < n; ++j) 42 | cout << a[i][j] << " "; 43 | cout << endl; 44 | } 45 | cout << endl; 46 | zero(a, m, n); 47 | for (int i = 0; i < m; ++i) 48 | { 49 | for (int j = 0; j < n; ++j) 50 | cout << a[i][j] << " "; 51 | cout << endl; 52 | } 53 | fclose(stdin); 54 | return 0; 55 | } 56 | -------------------------------------------------------------------------------- /Solutions/Chapter 8 Recursion/8.4.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Q 8.4 Write a method to compute all permutations of a string. 3 | */ 4 | 5 | #include 6 | #include 7 | #include 8 | using namespace std; 9 | 10 | typedef vector vs; 11 | 12 | vs permu(string s) 13 | { 14 | vs result; 15 | if (s == "") 16 | { 17 | result.push_back(""); 18 | return result; 19 | } 20 | string c = c.substr(0,1); 21 | vs res = permu(s.substr(1)); 22 | for (int i = 0; i < res.size(); ++i) 23 | { 24 | string t = res[i]; 25 | for (int j = 0; j <= t.length(); ++j) 26 | { 27 | string u = t; 28 | u.insert(j, c); 29 | result.push_back(u); 30 | } 31 | } 32 | return result;// 33 | } 34 | vs permu1(string s) 35 | { 36 | vs result; 37 | if (s == "") 38 | { 39 | result.push_back(""); 40 | return result; 41 | } 42 | for (int i = 0; i < s.length(); ++i) 43 | { 44 | string c = s.substr(i, 1); 45 | string t = s; 46 | vs res = permu1(t.erase(i, 1)); 47 | for (int j = 0; j < res.size(); ++j) 48 | { 49 | result.push_back(c + res[j]); 50 | } 51 | } 52 | return result; 53 | } 54 | int main() 55 | { 56 | string s = "abc"; 57 | vs res = permu1(s); 58 | for (int i = 0; i < res.size(); ++i) 59 | cout< 6 | #include 7 | #include 8 | #include 9 | using namespace std; 10 | 11 | const int maxn = 100; 12 | struct Node 13 | { 14 | int key; 15 | Node *lchild, *rchild, *parent; 16 | }; 17 | Node *p, node[maxn]; 18 | int cnt; 19 | 20 | void init() 21 | { 22 | p = NULL; 23 | memset(node,'\0',sizeof(node)); 24 | cnt = 0; 25 | } 26 | 27 | void create_minimal_tree(Node* &head,Node *parent,int a[],int start,int end) 28 | { 29 | if (start <= end) 30 | { 31 | int mid = (start + end) >> 1; 32 | node[cnt].key = a[mid]; 33 | node[cnt].parent = parent; 34 | head = &node[cnt++]; 35 | create_minimal_tree(head->lchild, head, a, start, mid - 1); 36 | create_minimal_tree(head->rchild, head, a , mid + 1, end); 37 | } 38 | } 39 | 40 | int height(Node *head) 41 | { 42 | if (head == NULL)return 0; 43 | return max(height(head->lchild), height(head->rchild)) + 1; 44 | } 45 | int main() 46 | { 47 | init(); 48 | int a[] = {0,1,2,3,4,5,6,7,8}; 49 | 50 | Node *head = NULL; 51 | create_minimal_tree(head, NULL, a, 0, 8); 52 | cout << height(head) << endl; 53 | return 0; 54 | } 55 | -------------------------------------------------------------------------------- /Solutions/Chapter 3 Stacks and Queues/3.6.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | *Q3.6 Write a program to sort a stack in ascending order.You should not make any assumptions about how the stack is impletmented. 3 | *The following are the only functions that should be used to write this program:push|pop|peek|isEmpty. 4 | */ 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | using namespace std; 13 | 14 | void Qsort(stack &s) { 15 | priority_queue< int, vector, greater > q; 16 | while (!s.empty()) 17 | { 18 | q.push(s.top()); 19 | s.pop(); 20 | } 21 | while (!q.empty()) 22 | { 23 | s.push(q.top()); 24 | q.pop(); 25 | } 26 | } 27 | 28 | stack Ssort(stacks) 29 | { 30 | stack t; 31 | while (!s.empty()) 32 | { 33 | int data = s.top(); 34 | s.pop(); 35 | while (!t.empty() && t.top() > data) 36 | { 37 | s.push(t.top()); 38 | t.pop(); 39 | } 40 | t.push(data); 41 | } 42 | return t; 43 | } 44 | 45 | int main() 46 | { 47 | srand((unsigned)time(0)); 48 | stack s; 49 | 50 | for (int i = 0; i < 10; ++i) 51 | s.push((rand()%100)); 52 | 53 | Qsort(s); 54 | while (!s.empty()) 55 | { 56 | cout << s.top() << " "; 57 | s.pop(); 58 | } 59 | return 0; 60 | } 61 | -------------------------------------------------------------------------------- /Solutions/Chapter 20 Hard/20.12.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Q 20.12 Given an N*N matrix of positive and negative integers, 3 | * write code to find the submatrix with the largest possible sum. 4 | */ 5 | 6 | #include 7 | #include 8 | using namespace std; 9 | 10 | const int MAX_N = 100; 11 | int p[MAX_N][MAX_N], A[MAX_N][MAX_N]; 12 | 13 | void PreCompute(int n) 14 | { 15 | for (int i = 0; i < n; ++i) 16 | p[0][i] = p[i][0] = 0; 17 | for (int i = 1; i <= n; ++i) 18 | for (int j = 1; j < n; ++j) 19 | p[i][j] = p[i - 1][j] + p[i][j - 1] - p[i - 1][j - 1] + A[i][j]; 20 | } 21 | 22 | int MaxSum(int n) 23 | { 24 | int max_sum = 1 << 31; 25 | for (int i = 1; i <= n; ++i) 26 | for(int j=1;j<=n;++j) 27 | { 28 | int cur_sum = 0; 29 | for (int k = 1; k <= n; ++k) 30 | { 31 | int val = p[j][k] - p[j][k - 1] - p[i - 1][k] + p[i - 1][k - 1]; 32 | if (cur_sum <= 0) 33 | cur_sum = val; 34 | else 35 | cur_sum += val; 36 | 37 | if (cur_sum > max_sum) 38 | max_sum = cur_sum; 39 | } 40 | } 41 | return max_sum; 42 | } 43 | 44 | int main() 45 | { 46 | freopen("20.12.in", "r", stdin); 47 | int n; 48 | cin >> n; 49 | for (int i = 1; i <= n; ++i) 50 | for (int j = 1; j <= n; ++j) 51 | cin >> A[i][j]; 52 | PreCompute(n); 53 | cout << MaxSum(n) << endl; 54 | fclose(stdin); 55 | return 0; 56 | } 57 | -------------------------------------------------------------------------------- /Solutions/Chapter 1 Arrays and Strings/1.6.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | *Q1.6 Given an image represented by an N*N matrix,where each pixel int image is 4 bytes,write a method to rotate the image by90 degrees. 3 | *Can you do this in place? 4 | * 5 | * 1 2 3 4 4 8 12 16 6 | * 5 6 7 8 --> 3 7 11 15 7 | * 9 10 11 12 2 6 10 14 8 | * 13 14 15 16 1 5 9 13 9 | * 10 | */ 11 | 12 | #include 13 | using namespace std; 14 | 15 | void swap(int &a, int &b) 16 | { 17 | int t = a; 18 | a = b; 19 | b = t; 20 | } 21 | 22 | void transpose(int a[][4], int n) 23 | { 24 | for (int i = 0; i < n; ++i) 25 | for (int j = i + 1; j < n; ++j) 26 | swap(a[i][j], a[j][i]); 27 | for (int i = 0; i < n / 2; ++i) 28 | for (int j = 0; j < n; ++j) 29 | swap(a[i][j], a[n - 1 - i][j]); 30 | } 31 | 32 | int main() 33 | { 34 | int a[4][4] = 35 | { 36 | {1,2,3,4}, 37 | {5,6,7,8}, 38 | {9,10,11,12}, 39 | {13,14,15,16} 40 | }; 41 | for (int i = 0; i < 4; ++i) 42 | { 43 | for (int j = 0; j < 4; ++j) 44 | cout << a[i][j] << " "; 45 | cout << endl; 46 | } 47 | cout << endl; 48 | transpose(a, 4); 49 | for (int i = 0; i < 4; ++i) 50 | { 51 | for (int j = 0; j < 4; ++j) 52 | cout << a[i][j] << " "; 53 | cout << endl; 54 | } 55 | return 0; 56 | } 57 | -------------------------------------------------------------------------------- /Solutions/Chapter 2 Linked Lists/2.2.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | *Q2.2 Implement an algorithm to find thr Nth to last element of a singly linked list. 3 | */ 4 | 5 | #include 6 | using namespace std; 7 | 8 | typedef struct node 9 | { 10 | int data; 11 | node *next; 12 | }node; 13 | 14 | node* init(int a[], int n) 15 | { 16 | node *head, *p; 17 | for (int i = 0; i < n; ++i) 18 | { 19 | node *nd = new node(); 20 | nd->data = a[i]; 21 | if (i==0) 22 | { 23 | head = p = nd; 24 | continue; 25 | } 26 | p->next = nd; 27 | p = nd; 28 | } 29 | return head; 30 | } 31 | 32 | node* findNthToLast(node *head, int n) 33 | { 34 | if (head == NULL || n < 1) return NULL; 35 | node *p = head, *q = head; 36 | while (n > 0 && q) 37 | { 38 | p = p->next; 39 | q = q->next; 40 | } 41 | return p; 42 | } 43 | 44 | node *pp; 45 | int nn; 46 | void findNthToLast1(node *head) 47 | { 48 | if (head == NULL) return; 49 | findNthToLast1(head->next); 50 | if (nn == 1) pp = head; 51 | --nn; 52 | } 53 | 54 | int main() 55 | { 56 | int n = 10; 57 | int a[] = {9,2,1,6,5,4,5,7,2,1}; 58 | node *head = init(a,n); 59 | node *p = findNthToLast(head,6); 60 | if (p) cout << p->data << endl; 61 | else cout << "the length of link is not enough" << endl; 62 | nn = 6; 63 | findNthToLast1(head); 64 | if (pp) cout << pp->data << endl; 65 | return 0; 66 | } 67 | -------------------------------------------------------------------------------- /Solutions/Chapter 13 CPP/13.1.in: -------------------------------------------------------------------------------- 1 | 2 | “Even when I was a boy I could never walk in a wood without feeling that at any moment 3 | I might find before me somebody or something I had long looked for without knowing what I looked for. 4 | And now I will at times explore every little nook of some poor coppice with almost anxious footsteps, 5 | so deep a hold has this imagination upon me. 6 | You too meet with a like imagination, doubtless, somewhere, wherever your ruling stars will have it, 7 | Saturn driving you to the woods, or the Moon, it may be, to the edges of the sea. 8 | I will not of a certainty believe that there is nothing in the sunset, 9 | where our forefathers imagined the dead following their shepherd the sun, or nothing but some vague presence as little moving as nothing. 10 | If beauty is not a gateway out of the net we were taken in at our birth, it will not long be beauty, 11 | and we will find it better to sit at home by the fire and fatten a lazy body or to run hither and thither 12 | in some foolish sport than to look at the finest show that light and shadow ever made among green leaves. 13 | I say to myself, when I am well out of that thicket of argument, that they are surely there, the divine people, 14 | for only we who have neither simplicity nor wisdom have denied them, 15 | and the simple of all times and the wise men of ancient times have seen them and even spoken to them.” 16 | ― W.B. Yeats, The Celtic Twilight 17 | -------------------------------------------------------------------------------- /Solutions/Chapter 4 Trees and Graphs/4.2.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | *Q4.2 Given a directed graph,design an algorithm to find out whether there is a route between two nodes. 3 | */ 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | //#pragma warning(disable:4996) 11 | //Visual Studio Project properties -> C/C++ -> Preprocessor -> PreprocessorDefinitions -> Add "_CRT_SECURE_NO_WARNINGS" 12 | using namespace std; 13 | 14 | const int maxn = 100; 15 | bool g[maxn][maxn], visited[maxn]; 16 | int n; 17 | queue q; 18 | 19 | void init() 20 | { 21 | memset(g,false,sizeof(g)); 22 | memset(visited,false,sizeof(visited)); 23 | } 24 | bool route(int src, int dst) 25 | { 26 | q.push(src); 27 | visited[src] = true; 28 | while (!q.empty()) 29 | { 30 | int t = q.front(); 31 | q.pop(); 32 | if (t == dst) return true; 33 | for (int i = 0; i < n; ++i) 34 | if (g[t][i] && !visited[i]) 35 | { 36 | q.push(i); 37 | visited[i] = true; 38 | } 39 | } 40 | return false; 41 | } 42 | int main() 43 | { 44 | freopen("4.2.in","r",stdin); 45 | //Visual Studio Project properties -> C/C++ -> Preprocessor -> PreprocessorDefinitions -> Add "_CRT_SECURE_NO_WARNINGS" 46 | 47 | init(); 48 | int m, u, v; 49 | cin >> n >> m; 50 | for (int i = 0; i < m; ++i) 51 | { 52 | cin >> u >> v; 53 | g[u][v] = true; 54 | } 55 | cout << route(0, 6) << endl; 56 | fclose(stdin); 57 | return 0; 58 | } 59 | -------------------------------------------------------------------------------- /Solutions/Chapter 8 Recursion/8.6.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Q 8.6 Implement the "paint fill" function that one might see on many image editing parograms. 3 | *That is,given a screen (represented by a 2-dimensional array of Colors),a point,and a new color, 4 | *fill in the surrounding area until you hit a border if that color. 5 | */ 6 | 7 | #include 8 | #include 9 | using namespace std; 10 | 11 | enum color 12 | { 13 | red,yellow,blue,green 14 | }; 15 | 16 | bool paint_fill(color **screen, int m, int n, int x, int y, color c) 17 | { 18 | if (x < 0 || x >= m || y < 0 || y >= n) return false; 19 | if (screen[x][y] == c) return false; 20 | else 21 | { 22 | screen[x][y] = c; 23 | paint_fill(screen, m, n, x - 1, y, c); 24 | paint_fill(screen,m,n,x+1,y,c); 25 | paint_fill(screen,m,n,x,y-1,c); 26 | paint_fill(screen,m,n,x,y+1,c); 27 | } 28 | return true; 29 | } 30 | int main() 31 | { 32 | freopen("8.6.in","r",stdin); 33 | int m, n; 34 | cin >> m >> n; 35 | color **screen = new color*[m]; 36 | for (int i = 0; i < m; ++i) 37 | screen[i] = new color[n]; 38 | for (int i = 0; i > t; 43 | screen[i][j] = (color)t; 44 | } 45 | paint_fill(screen, 5, 5, 1, 2, green); 46 | for (int i = 0; i < 5; ++i) 47 | { 48 | for (int j = 0; j < 5; ++j) 49 | cout << screen[i][j] << " "; 50 | cout << endl; 51 | } 52 | fclose(stdin); 53 | return 0; 54 | } 55 | -------------------------------------------------------------------------------- /Solutions/Chapter 20 Hard/hash.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | const int kWordSize = 26 + 5; 4 | const int kNodeSize = 1200 + 5; 5 | const int kHashSize = 10001; //大质数 6 | 7 | struct Node{ 8 | char word[kWordSize]; 9 | Node *next; 10 | }; 11 | 12 | Node node[kNodeSize + 1]; 13 | Node* head[kHashSize + 1]; 14 | 15 | class Hash{ 16 | 17 | public: 18 | Hash(); 19 | unsigned int hash(const char* str); 20 | void insert(const char* str); 21 | bool find(const char* str); 22 | 23 | private: 24 | unsigned int seed; 25 | unsigned int size; 26 | }; 27 | 28 | Hash::Hash():seed(131),size(0){ 29 | memset(head, 0, sizeof(head)); 30 | } 31 | 32 | unsigned int Hash::hash(const char* str){ 33 | unsigned int hash = 0; 34 | while(*str++) 35 | hash = hash * seed + (*str); 36 | return (hash & 0x7FFFFFFF) % kHashSize; 37 | } 38 | 39 | void Hash::insert(const char* str){ 40 | unsigned int id = hash(str); 41 | char *dst = (char*)node[size].word; 42 | while(*dst++ = *str++); 43 | node[size].next = head[id]; 44 | head[id] = &node[size]; 45 | ++size; 46 | } 47 | 48 | bool Hash::find(const char* str){ 49 | unsigned int id = hash(str); 50 | for(Node* p=head[id]; p ; p=p->next){ 51 | char *dst = (char*)p->word; 52 | int i = 0; 53 | while(*(str+i) && *(dst+i)==*(str+i)) 54 | ++i; 55 | if(*(str+i)=='\0' && *(dst+i)=='\0') 56 | return true; 57 | } 58 | return false; 59 | } 60 | -------------------------------------------------------------------------------- /Solutions/Chapter 1 Arrays and Strings/1.5.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | *Q1.5 Write a method to replace all spaces in a string with '%20'. 3 | */ 4 | 5 | #include 6 | #include 7 | using namespace std; 8 | 9 | char* replace1(char *c) 10 | { 11 | if (c == NULL) return NULL; 12 | int len = strlen(c); 13 | if (len == 0) return NULL; 14 | int cnt = 0; 15 | for (int i = 0; i < len; ++i) 16 | { 17 | if (c[i] == ' ') 18 | ++cnt; 19 | } 20 | char *cc = new char[len + 2 * cnt + 1]; 21 | int p = 0; 22 | for (int i = 0; i < len; ++i) 23 | { 24 | if (c[i] == ' ') 25 | { 26 | 27 | cc[p] = '%'; 28 | cc[p + 1] = '2'; 29 | cc[p + 2] = '0'; 30 | p += 3; 31 | } 32 | else 33 | { 34 | cc[p] = c[i]; 35 | return cc; 36 | } 37 | } 38 | cc[p] = '\0'; 39 | return cc; 40 | } 41 | 42 | void replace2(char *c) 43 | { 44 | if (c == NULL) return; 45 | int len = strlen(c); 46 | if (len == 0) return; 47 | int cnt = 0; 48 | for (int i = 0; i < len; ++i) 49 | { 50 | if (c[i] == ' ') 51 | ++cnt; 52 | } 53 | int p = len + 2 * cnt; 54 | c[p--] = '\0';//the space must be allocated first. 55 | for (int i = len - 1; i >= 0; --i) 56 | { 57 | if (c[i] == ' ') 58 | { 59 | c[p] = '0'; 60 | c[p - 1] = '2'; 61 | c[p - 2] = '%'; 62 | p -= 3; 63 | } 64 | else 65 | { 66 | c[p] = c[i]; 67 | --p; 68 | } 69 | } 70 | } 71 | int main() 72 | { 73 | const int len = 100; 74 | char c[len] = ""; 75 | cout << replace1(c) << endl; 76 | replace1(c); 77 | cout << c << endl; 78 | return 0; 79 | } 80 | -------------------------------------------------------------------------------- /Solutions/Chapter 20 Hard/20.7.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Q 20.7 Write a program to find the longest word made of other words. 3 | */ 4 | 5 | #include 6 | #include 7 | #include "hash.h" 8 | using namespace std; 9 | 10 | Hash hash; 11 | 12 | inline bool cmp(string s1, string s2){//按长度从大到小排 13 | return s2.length() < s1.length(); 14 | } 15 | 16 | bool MakeOfWords(string word, int length){ 17 | //cout<<"curr: "< 11 | #include 12 | #include 13 | using namespace std; 14 | 15 | const int maxn = 100; 16 | struct person { 17 | int h, w; 18 | }; 19 | person p[maxn]; 20 | int d[maxn]; 21 | 22 | bool cmp(person p1, person p2) 23 | { 24 | if (p1.h == p2.h) return p1.w < p2.w; 25 | else return p1.h < p2.h; 26 | } 27 | int lis(person p[], int n) 28 | { 29 | int k = 1; 30 | d[0] = p[0].w; 31 | for (int i = 1; i < n; ++i) 32 | { 33 | if (p[i].w >= d[k - 1]) d[k++] = p[i].w; 34 | else 35 | { 36 | int j; 37 | for (j = k - 1; j >= 0 && d[j] > p[i].w; --j) // 38 | d[j + 1] = p[i].w; 39 | } 40 | } 41 | return k; 42 | } 43 | 44 | int main() 45 | { 46 | freopen("9.7.in","r",stdin); 47 | int n; 48 | cin >> n; 49 | for (int i = 0; i < n; ++i) 50 | cin >> p[i].h >> p[i].w; 51 | sort(p,p+n,cmp); 52 | cout << lis(p, n) << endl; 53 | fclose(stdin); 54 | return 0; 55 | } 56 | -------------------------------------------------------------------------------- /Solutions/Chapter 2 Linked Lists/2.3.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | *Q2.3 Implement an algorithm to delete a node in the midddle of a single linked list,given only access to that node. 3 | *Example: 4 | *Input:the node 'c' from the linked list a->b->c->d->e Result:nothing is returned,but the new linked list lokks like a->b->d->e 5 | */ 6 | 7 | #include 8 | using namespace std; 9 | 10 | typedef struct node 11 | { 12 | int data; 13 | node *next; 14 | }node; 15 | 16 | node* init(int a[], int n) 17 | { 18 | node *head, *p; 19 | for (int i = 0; i < n; ++i) 20 | { 21 | node *nd = new node(); 22 | nd->data = a[i]; 23 | if (i == 0) 24 | { 25 | head = p = nd; 26 | continue; 27 | } 28 | p->next = nd; 29 | p = nd; 30 | } 31 | return head; 32 | } 33 | 34 | bool remove(node *c) 35 | { 36 | if (c == NULL || c->next == NULL) return false; 37 | /*if (c->next == NULL) c为最后一个元素时直接删除,不行,最后还是会打印出一个为0的结点,需要特殊处理 38 | { 39 | delete c; 40 | return; 41 | }*/ 42 | node *q = c->next; 43 | c->data = q->data; 44 | c->next = q->next; 45 | delete q; 46 | return true; 47 | 48 | } 49 | 50 | void print(node *head) 51 | { 52 | while (head) 53 | { 54 | cout << head->data << " "; 55 | head = head->next; 56 | } 57 | cout << endl; 58 | } 59 | 60 | int main() 61 | { 62 | int n = 10; 63 | int a[] = {9,2,3,1,5,6,1,2,3,6}; 64 | node *head = init(a,n); 65 | int cc = 3; 66 | node *c = head; 67 | for (int i = 1; i < cc; ++i) c = c->next; 68 | print(head); 69 | if (remove(c)) 70 | print(head); 71 | else 72 | cout << "failure" << endl; 73 | return 0; 74 | } 75 | -------------------------------------------------------------------------------- /Solutions/Chapter 13 CPP/13.9.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Q 13.9 Write a smart pointer class(smart_ptr). 3 | */ 4 | 5 | #include 6 | #include 7 | using namespace std; 8 | 9 | template 10 | class SmartPointer 11 | { 12 | public: 13 | SmartPointer(T* ptr) 14 | { 15 | ref = ptr; 16 | ref_count = (unsigned*)malloc(sizeof(unsigned)); 17 | *ref_count = 1; 18 | } 19 | SmartPointer(SmartPointer &sptr) 20 | { 21 | ref = sptr.ref; 22 | ref_count = sptr.ref_count; 23 | ++*ref_count; 24 | } 25 | 26 | SmartPointer& operator=(SmartPointer&sptr) 27 | { 28 | if (this != &sptr) 29 | { 30 | if (--*ref_count == 0) 31 | { 32 | clear(); 33 | cout << "operator=clear" << endl; 34 | } 35 | 36 | ref = sptr.ref; 37 | ref_count = sptr.ref_count; 38 | ++*ref_count; 39 | } 40 | return *this; 41 | } 42 | 43 | ~SmartPointer() 44 | { 45 | if (--*ref_count == 0) 46 | { 47 | clear(); 48 | cout << "destructor clear" << endl; 49 | } 50 | } 51 | 52 | T getValue() { return *ref; } 53 | 54 | private: 55 | void clear() 56 | { 57 | delete ref; 58 | free(ref_count); 59 | ref = NULL;//avoid making it be a lost pointer 60 | ref_count = NULL; 61 | } 62 | 63 | protected: 64 | T *ref; 65 | unsigned *ref_count; 66 | }; 67 | 68 | int main() 69 | { 70 | int *ip1 = new int(); 71 | *ip1 = 11111; 72 | int *ip2 = new int(); 73 | *ip2 = 22222; 74 | SmartPointer sp1(ip1), sp2(ip2); 75 | SmartPointer spa = sp1; 76 | sp2 = spa;//if comment this line ,it will get different output 77 | return 0; 78 | } 79 | -------------------------------------------------------------------------------- /Solutions/Chapter 8 Recursion/8.3.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | *Q8.3 Write a method that returns all subsets of a set. 3 | */ 4 | 5 | #include 6 | #include 7 | using namespace std; 8 | 9 | typedef vector> vvi; 10 | typedef vector vi; 11 | vvi get_subsets(int a[], int n) 12 | { 13 | vvi subsets; 14 | int max = 1 << n; 15 | for (int i = 0; i < max; ++i) 16 | { 17 | vi subset; 18 | int idx = 0; 19 | int j = i; 20 | while (j > 0) 21 | { 22 | if (j & 1) 23 | { 24 | subset.push_back(a[idx]); 25 | } 26 | j >>= 1; 27 | ++idx; 28 | } 29 | subsets.push_back(subset); 30 | } 31 | return subsets; 32 | } 33 | vvi get_subsets1(int a[], int idx, int n) 34 | { 35 | vvi subsets; 36 | if (idx == n) 37 | { 38 | vi subset; 39 | subsets.push_back(subset);//empty set 40 | } 41 | else 42 | { 43 | vvi rsubsets = get_subsets1(a,idx+1,n); 44 | int v = a[idx]; 45 | for (int i = 0; i < rsubsets.size(); ++i) 46 | { 47 | vi subset = rsubsets[i]; 48 | subsets.push_back(subset); 49 | subset.push_back(v); 50 | subsets.push_back(subset); 51 | } 52 | } 53 | return subsets; 54 | } 55 | void print_subsets(vvi subsets) 56 | { 57 | for (int i = 0; i < subsets.size(); ++i) 58 | { 59 | vi subset = subsets[i]; 60 | for (int j = 0; j < subset.size(); ++j) 61 | { 62 | cout << subset[j] << " "; 63 | } 64 | cout << endl; 65 | } 66 | } 67 | int main() 68 | { 69 | int a[] = {1,2,3,4}; 70 | vvi sub = get_subsets(a, 4); 71 | vvi sub1 = get_subsets1(a, 0, 4); 72 | print_subsets(sub); 73 | print_subsets(sub1); 74 | 75 | return 0; 76 | } 77 | -------------------------------------------------------------------------------- /Solutions/Chapter 20 Hard/20.8.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Q 20.8 Given a string s and an array of smaller strings T,design a method to search s for each small string in T. 3 | */ 4 | 5 | /* 6 | * Q 20.8 Given a string s and an array of smaller strings T,design a method to search s for each small string in T. 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | using namespace std; 13 | 14 | class Trie { 15 | public: 16 | static const int MAX_N = 100 * 100;// 17 | static const int CLD_NUM = 26;// 18 | int size;// 19 | int trie[MAX_N][CLD_NUM]; 20 | 21 | Trie(const char* s); 22 | void insert(const char* s); 23 | bool find(const char* s); 24 | }; 25 | 26 | Trie::Trie(const char*s) { 27 | memset(trie[0], -1, sizeof(trie[0])); 28 | size = 1; 29 | while (*s) 30 | { 31 | insert(s); 32 | ++s; 33 | } 34 | } 35 | 36 | void Trie::insert(const char* s) 37 | { 38 | int p = 0; 39 | while (*s) 40 | { 41 | int i = *s - 'a'; 42 | if (-1 == trie[p][i]) 43 | { 44 | memset(trie[size],-1,sizeof(trie[size])); 45 | trie[p][i] = size++; 46 | } 47 | p = trie[p][i]; 48 | ++s; 49 | } 50 | } 51 | 52 | bool Trie::find(const char* s) 53 | { 54 | int p = 0; 55 | while (*s) 56 | { 57 | int i = *s - 'a'; 58 | if (-1 == trie[p][i]) 59 | return false; 60 | p = trie[p][i]; 61 | ++s; 62 | } 63 | return true; 64 | } 65 | 66 | int main() 67 | { 68 | Trie tree("mississippi"); 69 | string patt[] = {"is","sip","hi","sis","mississippa"}; 70 | int n = 5; 71 | for (int i = 0; i < n; ++i) 72 | cout << tree.find((char*)&patt[i][0]) << endl; 73 | return 0; 74 | } 75 | -------------------------------------------------------------------------------- /Solutions/Chapter 8 Recursion/8.1.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | *Q8.1 Write a method to generate the nth Fibonacci number. 3 | */ 4 | 5 | #include 6 | using namespace std; 7 | 8 | typedef long long ll; 9 | ll fib(ll n) 10 | { 11 | if (n < 1) return -1; 12 | if (n == 1 || n == 2) return 1; 13 | else return fib(n - 1) + fib(n - 2); 14 | } 15 | ll fib1(ll n) 16 | { 17 | if (n < 1) return -1; 18 | if (n == 1 || n == 2) return 1; 19 | ll a = 1, b = 1; 20 | for (ll i = 3; i <= n; ++i) 21 | { 22 | ll c = a + b; 23 | a = b; 24 | b = c; 25 | } 26 | return b; 27 | } 28 | void mul(ll c[2][2], ll a[2][2], ll b[2][2]) 29 | { 30 | ll t[4]; 31 | t[0] = a[0][0] * b[0][0] + a[0][1] * b[1][0]; 32 | t[1] = a[0][0] * b[0][1] + a[0][1] * b[1][1]; 33 | t[2] = a[1][0] * b[0][0] + a[1][1] * b[1][0]; 34 | t[3] = a[1][0] * b[0][1] + a[1][1] * b[1][1]; 35 | c[0][0] = t[0]; 36 | c[0][1] = t[1]; 37 | c[1][0] = t[2]; 38 | c[1][1] = t[3]; 39 | } 40 | void pow(ll s[2][2], ll a[2][2], ll n) 41 | { 42 | while (n > 0) 43 | { 44 | if (n & 1) mul(s,s,a); 45 | mul(a,a,a); 46 | n >>= 1; 47 | } 48 | } 49 | ll fib2(ll n) 50 | { 51 | if (n < 1) return -1; 52 | if (n == 1 || n == 2) return 1; 53 | 54 | ll a[2][2] = {(1,1),(1,0)}; 55 | ll s[2][2] = {(1,0),(0,1)}; 56 | pow(s,a,n-2); 57 | return s[0][0] + s[0][1]; 58 | } 59 | int main() 60 | { 61 | for (int i = 1; i < 20; ++i) 62 | cout << fib(i) << " "; 63 | cout << endl; 64 | for (int i = 1; i < 20; ++i) 65 | cout << fib1(i) << " "; 66 | cout << endl; 67 | for (int i = 1; i < 20; ++i) 68 | cout << fib2(i) << " "; 69 | cout << endl; 70 | return 0; 71 | } 72 | -------------------------------------------------------------------------------- /Solutions/Chapter 3 Stacks and Queues/3.4.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | *Q3.4 In the classic problem of the Towers of Hanoi,you have 3 rods and N disks of different sizes which can slide onto any tower. 3 | *The puzzle starts with disks sorted in ascending order of size from top to bottom(e.g.,each disk sits on top of an even larger one). 4 | *You have the following constrains: 5 | * 1.Only one disk can be moved at a time. 6 | * 2.A disk is slid off the top of one rod onto the next rod. 7 | * 3.A disk can only be placed on top of a large disk. 8 | *Write a program to move the disks from the first rod to the last using Stacks 9 | */ 10 | 11 | #include 12 | #include 13 | using namespace std; 14 | 15 | struct op 16 | { 17 | int begin, end; 18 | char src, bri, dst; 19 | op() 20 | { 21 | 22 | } 23 | op(int pbegin,int pend,int psrc,int pbri,int pdst):begin(pbegin),end(pend),src(psrc),bri(pbri),dst(pdst) 24 | { 25 | 26 | } 27 | }; 28 | 29 | void hanoi(int n, char src, char bri, char dst) 30 | { 31 | stack st; 32 | op tmp; 33 | st.push(op(1, n, src, bri, dst)); 34 | while (!st.empty()) 35 | { 36 | tmp = st.top(); 37 | st.pop(); 38 | if (tmp.begin != tmp.end) 39 | { 40 | st.push(op(tmp.begin, tmp.end - 1, tmp.bri, tmp.src, tmp.dst)); 41 | st.push(op(tmp.end, tmp.end, tmp.src, tmp.bri, tmp.dst)); 42 | st.push(op(tmp.begin, tmp.end - 1, tmp.src, tmp.dst, tmp.bri)); 43 | } 44 | else 45 | { 46 | cout << "Move disk" << tmp.begin << " from" << tmp.src<<" to"<< tmp.dst << endl; 47 | } 48 | } 49 | } 50 | 51 | int main() 52 | { 53 | int n = 3; 54 | hanoi(n,'A','B','C'); 55 | return 0; 56 | } 57 | -------------------------------------------------------------------------------- /Solutions/Chapter 4 Trees and Graphs/4.5.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | *Q4.5 Write an algorithm to find the 'next' node(i.e.,in-order successor)of a given node in a binary search tree where each node has a link to its parent. 3 | */ 4 | 5 | #include 6 | #include 7 | using namespace std; 8 | 9 | const int maxn = 100; 10 | struct Node 11 | { 12 | int key; 13 | Node *lchild, *rchild, *parent; 14 | }; 15 | Node *p, node[maxn]; 16 | int cnt; 17 | 18 | void init() 19 | { 20 | p = NULL; 21 | memset(node,'\0',sizeof(node)); 22 | cnt = 0; 23 | } 24 | void create_minimal_tree(Node* &head, Node *parent, int a[], int start, int end) 25 | { 26 | if (start <= end) 27 | { 28 | int mid = (start + end) >> 1; 29 | node[cnt].key = a[mid]; 30 | node[cnt].parent = parent; 31 | head = &node[cnt++]; 32 | create_minimal_tree(head->lchild, head, a, start, mid - 1); 33 | create_minimal_tree(head->rchild,head,a,mid+1,end); 34 | } 35 | } 36 | Node* minimal(Node* no) 37 | { 38 | if (no == NULL) return NULL; 39 | while (no->lchild) 40 | no = no->lchild; 41 | return no; 42 | } 43 | Node* successor(Node* no) 44 | { 45 | if (no == NULL) return NULL; 46 | if (no ->rchild) return minimal(no->rchild); 47 | Node *y = no->parent; 48 | while (y&&y->parent == no) 49 | { 50 | no = y; 51 | y = y->parent; 52 | } 53 | return y; 54 | } 55 | int main() 56 | { 57 | int a[] = {0,1,2,3,4,5,6,7,8,9}; 58 | init(); 59 | Node *head = NULL; 60 | create_minimal_tree(head,NULL,a,0,9); 61 | cout << "the head is " << head->key << endl; 62 | cout << "the cuccessor of head is: " << (successor(head))->key << endl; 63 | return 0; 64 | } 65 | 66 | -------------------------------------------------------------------------------- /Solutions/Chapter 8 Recursion/8.7.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Q 8.7 Given an infinite number of quarters (25 cents), dimes (10 cents), nickels (5 cents) and pennies (1 cent), 3 | * write code to calculate the number of ways of representing n cents. 4 | */ 5 | 6 | #include 7 | using namespace std; 8 | 9 | int cnt = 0; 10 | void sumN(int sum, int c, int n) 11 | { 12 | if (sum >= n) 13 | { 14 | if (sum == n) ++cnt; 15 | return; 16 | } 17 | else 18 | { 19 | if (c >= 25) 20 | sumN(sum + 25, 25, n); 21 | if (c >= 10) 22 | sumN(sum + 10, 10, n); 23 | if (c >= 5) 24 | sumN(sum + 5, 5, n); 25 | if (c >= 1) 26 | sumN(sum + 1, 1, n); 27 | } 28 | } 29 | int sum_n(int sum, int c, int n) 30 | { 31 | int ways = 0; 32 | if (sum <= n) 33 | { 34 | if (sum == n) return 1; 35 | if (c >= 25) 36 | ways += sum_n(sum + 25, 25, n); 37 | if (c >= 10) 38 | ways += sum_n(sum + 10, 10, n); 39 | if (c >= 5) 40 | ways += sum_n(sum + 5, 5, n); 41 | if (c >= 1) 42 | ways += sum_n(sum + 1, 1, n); 43 | } 44 | return ways; 45 | } 46 | int make_change(int n, int denom) 47 | { 48 | int next_denom = 0; 49 | switch (denom) 50 | { 51 | case 25: 52 | next_denom = 10; 53 | break; 54 | case 10: 55 | next_denom = 5; 56 | break; 57 | case 5: 58 | next_denom = 1; 59 | break; 60 | case 1: 61 | return 1; 62 | } 63 | int ways = 0; 64 | for (int i = 0; i*denom <= n; ++i) 65 | ways += make_change(n - i*denom, next_denom); 66 | return ways; 67 | } 68 | int main() 69 | { 70 | int n = 10; 71 | sumN(0, 25, n); 72 | cout << cnt << endl; 73 | cout << make_change(n, 25) << endl; 74 | cout << sum_n(0, 25, n) << endl; 75 | return 0; 76 | } 77 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Cracking-the-Coding-Interview 2 | 3 |

4 | 5 |

6 | 7 | Cracking the Coding Interview, 6th Edition is here to help you through this process, teaching you what you need to know and enabling you to perform at your very best. 8 | 9 | Learn how to uncover the hints and hidden details in a question, discover how to break down a problem into manageable chunks, develop techniques to unstick yourself when stuck, learn (or re-learn) core computer science concepts, and practice on 189 interview questions and solutions. 10 | 11 | These interview questions are real; they are not pulled out of computer science textbooks. They reflect what's truly being asked at the top companies, so that you can be as prepared as possible. **WHAT'S INSIDE?** 12 | * 189 programming interview questions, ranging from the basics to the trickiest algorithm problems. 13 | * A walk-through of how to derive each solution, so that you can learn how to get there yourself. 14 | * Hints on how to solve each of the 189 questions, just like what you would get in a real interview. 15 | * Five proven strategies to tackle algorithm questions, so that you can solve questions you haven't seen. 16 | * Extensive coverage of essential topics, such as big O time, data structures, and core algorithms. 17 | * A behind the scenes look at how top companies like Google and Facebook hire developers. 18 | * Techniques to prepare for and ace the soft side of the interview: behavioral questions. 19 | * For interviewers and companies: details on what makes a good interview question and hiring process. 20 | 21 |

22 | 23 |

24 | 25 | If you have any questions about the solutions you can find here, feel free to contact me **abhisheksharma.0517@gmail.com**. 26 | -------------------------------------------------------------------------------- /Solutions/Chapter 4 Trees and Graphs/4.1.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | *Q4.1 Implement a function to check if a tree is balanced.For the purpose of this question, 3 | *a balanced tree is defined to be a tree such that no two leaf nodes differ in distance 4 | *from the root by more than one. 5 | */ 6 | 7 | #include 8 | #include 9 | #include 10 | using namespace std; 11 | 12 | const int maxn = 100; 13 | struct Node 14 | { 15 | int key; 16 | Node *lchild, *rchild, *parent; 17 | }; 18 | Node *head, *p,node[maxn]; 19 | int cnt; 20 | 21 | void init() 22 | { 23 | head = p = NULL; 24 | memset(node,'\0',sizeof(node)); 25 | cnt = 0; 26 | } 27 | void insert(Node* &head, int x) 28 | { 29 | if (head == NULL) 30 | { 31 | node[cnt].key = x; 32 | node[cnt].parent = p; 33 | head = &node[cnt++]; 34 | return; 35 | } 36 | p = head; 37 | if (x < head->key) 38 | insert(head->lchild, x); 39 | else 40 | insert(head->rchild, x); 41 | } 42 | int d = 0, num = 0, dep[maxn]; 43 | void getDepth(Node *head) 44 | { 45 | if (head == NULL) return; 46 | ++d; 47 | getDepth(head->lchild); 48 | if (head->lchild == NULL&&head->rchild == NULL) 49 | dep[num++] = d; 50 | getDepth(head->rchild); 51 | --d; 52 | } 53 | bool isBalance(Node *head) 54 | { 55 | if (head == NULL) return true; 56 | getDepth(head); 57 | int max = dep[0], min = dep[0]; 58 | for (int i = 0; i < num; ++i) 59 | { 60 | if (dep[i] > max)max = dep[i]; 61 | if (dep[i] < min)min = dep[i]; 62 | } 63 | if (max - min > 1) return false; 64 | else return true; 65 | } 66 | 67 | int main() 68 | { 69 | init(); 70 | int a[] = { 5,3,8,1,4,7,10,2,6,9,11,12 }; 71 | for (int i = 0; i < 12; ++i) 72 | { 73 | insert(head, a[i]); 74 | } 75 | cout << isBalance(head) << endl; 76 | return 0; 77 | } 78 | -------------------------------------------------------------------------------- /Solutions/Chapter 20 Hard/20.4.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Q 20.4 Write a method to count the number of 2s between 0 and n. 3 | */ 4 | 5 | #include 6 | using namespace std; 7 | 8 | int Count2(int n) 9 | { 10 | int count = 0; 11 | while (n > 0) 12 | { 13 | if (n % 10 == 2) 14 | ++count; 15 | n /= 10; 16 | } 17 | return count; 18 | } 19 | 20 | int Count2s1(int n) 21 | { 22 | int count = 0; 23 | for (int i = 0; i <= n; ++i) 24 | { 25 | count += Count2(i); 26 | } 27 | return count; 28 | } 29 | 30 | int Count2s(int n) 31 | { 32 | int count = 0; 33 | int factor = 1; 34 | int low = 0, cur = 0, high = 0; 35 | 36 | while (n / factor != 0) 37 | { 38 | low = n - (n / factor)*factor; 39 | cur = (n / factor) % 10; 40 | high = n / (factor * 10); 41 | 42 | switch (cur) 43 | { 44 | case 0: 45 | case 1: 46 | count += high*factor; 47 | break; 48 | case 2: 49 | count += high*factor + low + 1; 50 | break; 51 | default: 52 | count += (high + 1)*factor; 53 | break; 54 | } 55 | factor *= 10; 56 | } 57 | return count; 58 | } 59 | 60 | int Countis(int n, int i) 61 | { 62 | if (i < 1 || i>9) return -1; 63 | 64 | int count = 0; 65 | int factor = 1; 66 | int low = 0, cur = 0, high = 0; 67 | 68 | while (n / factor != 0) 69 | { 70 | low = n - (n / factor)*factor; 71 | cur = (n / factor) % 10; 72 | high = n / (factor * 10); 73 | 74 | if (cur < i) 75 | count += high*factor; 76 | else if (cur == i) 77 | count += high*factor + low + 1; 78 | else 79 | count += (high + 1)*factor; 80 | 81 | factor *= 10; 82 | } 83 | return count; 84 | } 85 | 86 | int main() 87 | { 88 | for (int i = 0; i < 1000; ++i) 89 | cout << Count2s1(i) << " " << Count2s(i)<< " " << Countis(i, 2) << endl; 90 | return 0; 91 | } 92 | -------------------------------------------------------------------------------- /Solutions/Chapter 5 Bit Manipulation/5.7.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | *Q5.7 An array A[1…n] contains all the integers from 0 to n except for one number which is missing. 3 | * In this problem, we cannot access an entire integer in A with a single operation.The elements of A are represented in binary, 4 | * and the only operation we can use to access them is “fetch the jth bit of A[i]”, which takes constant time. 5 | *Write code to find the missing integer. Can you do it in O(n) time? 6 | */ 7 | 8 | #include 9 | #include 10 | using namespace std; 11 | 12 | int fetch(int a[], int i, int j) 13 | { 14 | return (a[i] >> j) & 1;//return 0/1 15 | } 16 | int get(int a[], int i) 17 | { 18 | int ret = 0; 19 | for (int j = 31; j >= 0; --j) 20 | ret = (ret << 1) | fetch(a, i, j); 21 | return ret; 22 | } 23 | int missing(int a[], int n) 24 | { 25 | bool *b = new bool[n + 1]; 26 | memset(b, false, (n + 1) * sizeof(bool)); 27 | for (int i = 0; i < n; ++i) 28 | b[get(a, i)] = true; 29 | for (int i = 0; i < n + 1; ++i) 30 | { 31 | if (!b[i]) return 1; 32 | } 33 | delete[] b; 34 | } 35 | int fetch1(int a[], int j) 36 | { 37 | return (a[j/32]>>(j%32))&1; 38 | } 39 | int get1(int a[], int i) 40 | { 41 | int ret = 0; 42 | int base = 32 * i; 43 | for (int j = base + 31; j >= base; --j) 44 | ret = (ret << 1) | fetch1(a, j); 45 | return ret; 46 | } 47 | int missing1(int a[], int n) 48 | { 49 | bool *b = new bool[n + 1]; 50 | memset(b,false,(n+1)*sizeof(bool)); 51 | for (int i = 0; i < n; ++i) 52 | b[get1(a, i)] = true; 53 | for (int i = 0; i < n + 1; ++i) 54 | { 55 | if (!b[i]) return i; 56 | } 57 | delete[] b; 58 | } 59 | 60 | int main() 61 | { 62 | int a[] = {0,1,2,3,4,5,6,7,8,9,10}; 63 | cout << missing(a, 10) << endl; 64 | cout << missing1(a, 10) << endl; 65 | return 0; 66 | } 67 | -------------------------------------------------------------------------------- /Solutions/Chapter 2 Linked Lists/2.5.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | *Q2.5 Given a circular linked list,implement an algorithm which returns node at the beginning of the loop. 3 | *DEFINITION 4 | *Circular linked list: A (corrupt) linked list in which a node’s next pointer points to an earlier node, so as to make a loop in the linked list. 5 | *EXAMPLE 6 | *Input: A -> B -> C -> D -> E -> C [the same C as earlier] 7 | *Output:C 8 | */ 9 | 10 | #include 11 | #include 12 | using namespace std; 13 | 14 | typedef struct node 15 | { 16 | int data; 17 | node *next; 18 | }node; 19 | 20 | node* init(int a[], int n, int m) 21 | { 22 | node *head, *p, *q; 23 | for (int i = 0; i < n; ++i) 24 | { 25 | node *nd = new node(); 26 | nd->data = a[i]; 27 | if (i == m) q = nd; 28 | if (i == 0) 29 | { 30 | head = p = nd; 31 | continue; 32 | } 33 | p->next = nd; 34 | p = nd; 35 | } 36 | p->next = q; 37 | return head; 38 | } 39 | 40 | node* loopstart(node *head) 41 | { 42 | if (head == NULL) return NULL; 43 | node *fast = head, *slow = head; 44 | while (fast&&fast->next) 45 | { 46 | fast = fast->next->next; 47 | slow = slow->next; 48 | if (fast == slow) break; 49 | } 50 | if (!fast || !fast->next) return NULL; 51 | slow = head; 52 | while (fast != slow) 53 | { 54 | fast = fast->next; 55 | slow = slow->next; 56 | } 57 | return fast; 58 | } 59 | 60 | map hash1; 61 | node* loopstart1(node *head) 62 | { 63 | while (head) 64 | { 65 | if (hash1[head]) return head; 66 | else 67 | { 68 | hash1[head] = true; 69 | head = head->next; 70 | } 71 | } 72 | return head; 73 | } 74 | 75 | int main() 76 | { 77 | int n = 10, m = 9; 78 | int a[] = { 3, 2, 1, 3, 5, 6, 2, 6, 3, 1 }; 79 | node *head = init(a,n,m); 80 | node *p = loopstart1(head); 81 | if (p) 82 | cout << p->data << endl; 83 | return 0; 84 | } 85 | 86 | -------------------------------------------------------------------------------- /Solutions/Chapter 13 CPP/13.8.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * TASK: You are given a directed graph. Given a root node of this graph (i.e., 3 | * a node which can reach any other node), clone the original graph. 4 | * 5 | * NOTE: This question is slightly more general than the original one, but the 6 | * added generality does not add significant complexity to the problem. 7 | */ 8 | 9 | #include 10 | #include 11 | #include "node.h" 12 | 13 | /** 14 | * @brief Generates a random graph with n nodes and returns a pointer to the 15 | * first generated node (a root node). 16 | * @note Complexity: O(n) in both time and space. 17 | */ 18 | node* random_graph(const size_t n) 19 | { 20 | if (n == 0) 21 | { 22 | return nullptr; 23 | } 24 | 25 | static std::random_device device; 26 | static std::mt19937 generator(device()); 27 | 28 | /* the first generated node is the root */ 29 | std::vector nodes = {new node(0)}; 30 | 31 | while (nodes.size() < n) 32 | { 33 | std::uniform_int_distribution node_chooser(0, nodes.size() - 1); 34 | 35 | node* new_node = new node(nodes.size()); 36 | 37 | size_t index = node_chooser(generator); 38 | nodes[index]->connect(new_node); 39 | 40 | nodes.push_back(new_node); 41 | } 42 | 43 | return nodes.front(); 44 | } 45 | 46 | int main() 47 | { 48 | for (size_t n = 1; n <= 50; ++n) 49 | { 50 | for (int i = 0; i < 1000; ++i) 51 | { 52 | node* n1 = random_graph(n); 53 | node* n2 = n1->clone(); 54 | 55 | assert(equal(n1, n2) == true); 56 | 57 | delete n1; 58 | delete n2; 59 | } 60 | 61 | std::cout << "passed random tests for graphs of size " << n 62 | << std::endl; 63 | } 64 | 65 | return EXIT_SUCCESS; 66 | } 67 | -------------------------------------------------------------------------------- /Solutions/Chapter 4 Trees and Graphs/4.7.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | *Q4.7 You have two very large binary trees:T1,with millions of nodes,and T2,with hundreds of nodes. 3 | *Create an algorithm to decide if T2 is a subtree of T1. 4 | */ 5 | 6 | #include 7 | #include 8 | using namespace std; 9 | 10 | const int maxn = 100; 11 | struct Node 12 | { 13 | int key; 14 | Node *lchild, *rchild, *parent; 15 | }; 16 | Node node[maxn]; 17 | int cnt; 18 | 19 | void init() 20 | { 21 | memset(node, '\0',sizeof(node)); 22 | cnt = 0; 23 | } 24 | void create_minimal_tree(Node* &head, Node *parent, int a[], int start, int end) 25 | { 26 | if (start <= end) 27 | { 28 | int mid = (start + end) >> 1; 29 | node[cnt].key = a[mid]; 30 | node[cnt].parent = parent; 31 | head = &node[cnt++]; 32 | create_minimal_tree(head->lchild,head,a,start,mid-1); 33 | create_minimal_tree(head->rchild,head,a,mid+1,end); 34 | } 35 | } 36 | bool match(Node* r1, Node* r2) 37 | { 38 | if (r1 == NULL&&r2 == NULL) return true; 39 | else if (r1 == NULL || r2 == NULL) return false; 40 | else if (r1->key != r2->key) return false; 41 | else return match(r1->lchild,r2->lchild)&&match(r1->rchild,r2->rchild); 42 | } 43 | bool subtree(Node* r1, Node* r2) 44 | { 45 | if (r1 == NULL) return false; 46 | else if (r1->key == r2->key) 47 | { 48 | if (match(r1, r2)) return true; 49 | } 50 | else return subtree(r1->lchild, r2) || subtree(r1->rchild, r2); 51 | } 52 | bool contain_tree(Node* r1, Node* r2) 53 | { 54 | if (r2 == NULL) return true; 55 | else return subtree(r1, r2); 56 | } 57 | int main() 58 | { 59 | init(); 60 | int a1[] = {0,1,2,3,4,5,6}; 61 | int a2[] = {0,1,2}; 62 | Node *r1 = NULL, *r2 = NULL; 63 | create_minimal_tree(r1,NULL,a1,0,6); 64 | create_minimal_tree(r2,NULL,a2,0,2); 65 | if (contain_tree(r1, r2)) 66 | cout << "tree r1 contains r2" << endl; 67 | else cout << "tree r1 does not contains r2" << endl; 68 | return 0; 69 | } 70 | -------------------------------------------------------------------------------- /Solutions/Chapter 2 Linked Lists/2.1.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | *Q2.1 Write code to remove duplicates from an unsorted linked list. 3 | *FOOLOW UP 4 | *How would you solve this problem if a temporary buffer is not allowed? 5 | */ 6 | 7 | #include 8 | #include 9 | using namespace std; 10 | 11 | typedef struct node 12 | { 13 | int data; 14 | node *next; 15 | }node; 16 | 17 | bool hash[100]; 18 | 19 | node* init(int a[], int n) 20 | { 21 | node *head, *p; 22 | for (int i = 0; i < n; ++i) 23 | { 24 | node *nd = new node(); 25 | nd->data = a[i]; 26 | if (i == 0) 27 | { 28 | head = p = nd; 29 | continue; 30 | } 31 | p->next = nd; 32 | p = nd; 33 | } 34 | return head; 35 | } 36 | 37 | void removedulicate(node *head) 38 | { 39 | if (head == NULL) return; 40 | node *p = head, *q = head->next; 41 | hash[head->data] = true; 42 | while (q) 43 | { 44 | if (hash[q->data]) 45 | { 46 | node *t = q; 47 | p->next = q->next; 48 | q = p->next; 49 | delete t; 50 | } 51 | else 52 | { 53 | hash[q->data] = true; 54 | p = q; q = q->next; 55 | } 56 | } 57 | } 58 | 59 | void removedulicate1(node *head) 60 | { 61 | if (head == NULL) return; 62 | node *p, *q, *c = head; 63 | while (q) 64 | { 65 | if (q->data == d) 66 | { 67 | node *t = q; 68 | p->next = q->next; 69 | q = p->next; 70 | delete t; 71 | } 72 | else 73 | { 74 | p = q; q = q->next; 75 | } 76 | } 77 | c = c->next; 78 | } 79 | 80 | void print(node *head) 81 | { 82 | while (head) 83 | { 84 | cout << head->data << " "; 85 | head = head->next; 86 | } 87 | cout << endl; 88 | } 89 | 90 | int main() 91 | { 92 | int n = 10; 93 | int a[] = { 3,2,1,3,5,6,2,6,3,1 }; 94 | memset(hash, false, sizeof(hash)); 95 | node *head = init(a,n); 96 | removedulicate1(head); 97 | print(head); 98 | return 0; 99 | } 100 | -------------------------------------------------------------------------------- /Solutions/Chapter 20 Hard/20.11.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Q 20.11 Imagine you have a square matrix, where each cell is filled with either black or white. 3 | * Design an algorithm to find the maximum subsquare such that all four borders are filled with black pixels. 4 | */ 5 | 6 | #include 7 | #include 8 | using namespace std; 9 | 10 | const int MAX_N = 100; 11 | int matrix[MAX_N][MAX_N]; 12 | 13 | struct SubSquare 14 | { 15 | int row, col, size; 16 | }; 17 | 18 | inline int max(int a,int b) 19 | { 20 | return a > b ? a : b; 21 | } 22 | 23 | bool IsSquare(int row, int col, int size) 24 | { 25 | for (int i = 0; i < size; ++i) 26 | { 27 | if (matrix[row][col + 1] == 1) 28 | return false; 29 | if (matrix[row + size - 1][col + i] == 1) 30 | return false; 31 | if (matrix[row + 1][col] == 1) 32 | return false; 33 | if (matrix[row + 1][col + size - 1] == 1) 34 | return false; 35 | } 36 | return true; 37 | } 38 | 39 | SubSquare FindSubSquare(int n) 40 | { 41 | int max_size = 0; 42 | int col = 0; 43 | SubSquare sq; 44 | while (n - col > max_size) 45 | { 46 | for (int row = 0; row < n; ++row) 47 | { 48 | int size = n - max(row, col); 49 | while (size > max_size) 50 | { 51 | if (IsSquare(row, col, size)) 52 | { 53 | max_size = size; 54 | sq.row = row; 55 | sq.col = col; 56 | sq.size = size; 57 | break; 58 | } 59 | --size; 60 | } 61 | } 62 | ++col; 63 | } 64 | return sq; 65 | } 66 | 67 | int main() 68 | { 69 | freopen("20.11.in","r",stdin); 70 | int n; 71 | cin >> n; 72 | for (int i = 0; i < n; ++i) 73 | for (int j = 0; j < n; ++j) 74 | cin >> matrix[i][j]; 75 | SubSquare sq = FindSubSquare(n); 76 | cout << "top: " << sq.row << endl; 77 | cout << "bottom: " << sq.row + sq.size - 1 << endl; 78 | cout << "left: " << sq.col << endl; 79 | cout << "right: " << sq.col + sq.size - 1 << endl; 80 | fclose(stdin); 81 | return 0; 82 | } 83 | 84 | 85 | -------------------------------------------------------------------------------- /Solutions/Chapter 19 Moderate/19.2.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Q 19.2 Design an algorithm to figure out if someone has won in a game of tic-toe. 3 | */ 4 | 5 | #include 6 | using namespace std; 7 | 8 | enum Check 9 | { 10 | ROW,COLUMN,DIAGONAL,REDIAGONAL 11 | }; 12 | 13 | int CheckRowColumn(int board[], int n, Check check) 14 | { 15 | int type = 0; 16 | for (int i = 0; i < n; ++i) 17 | { 18 | bool found = true; 19 | for (int j = 0; j < n; ++j) 20 | { 21 | int k = 0; 22 | if (check == ROW) 23 | k = i*n + j; 24 | else 25 | k = i + j*n; 26 | if (j == 0) 27 | { 28 | type = board[k]; 29 | } 30 | else if (board[k] != type) 31 | { 32 | found = false; 33 | break; 34 | } 35 | } 36 | if (found) return type; 37 | } 38 | return 0; 39 | } 40 | 41 | int CheckDiagonal(int board[], int n, Check check) 42 | { 43 | int type = 0; 44 | bool found = true; 45 | 46 | for (int i = 0; i < n; ++i) 47 | { 48 | int k = 0; 49 | if (check == DIAGONAL) 50 | k = i + i*n; 51 | else 52 | k = i + (n - 1 - i)*n; 53 | if (i == 0) 54 | { 55 | type = board[k]; 56 | } 57 | else if (board[k] != type) 58 | { 59 | found = false; 60 | break; 61 | } 62 | } 63 | if (found) return type; 64 | 65 | return 0; 66 | } 67 | 68 | int HasWon(int board[],int n) 69 | { 70 | int type = 0; 71 | type = CheckRowColumn(board, n, ROW); 72 | if (type != 0) return type; 73 | type = CheckRowColumn(board, n, COLUMN); 74 | if (type != 0) return type; 75 | type = CheckDiagonal(board,n,DIAGONAL); 76 | if (type != 0) return type; 77 | type = CheckDiagonal(board,n,REDIAGONAL); 78 | if (type != 0) return type; 79 | 80 | return 0; 81 | } 82 | 83 | int main() 84 | { 85 | int n = 3; 86 | int board[] = 87 | { 88 | 2,2,1, 89 | 2,1,1, 90 | 1,2,0, 91 | }; 92 | int type = HasWon(board, n); 93 | if (type != 0) 94 | cout << type << " Won!" << endl; 95 | else 96 | cout << "Nobody won!" << endl; 97 | return 0; 98 | } 99 | -------------------------------------------------------------------------------- /Solutions/Chapter 20 Hard/20.9.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Q 20.9 Numbers are randomly generated and passed to a method. 3 | * Write a program to find and maintain the median value as new values are generated. 4 | */ 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | using namespace std; 13 | 14 | class Median{ 15 | private: 16 | priority_queue, less> max_heap; 17 | priority_queue, greater> min_heap; 18 | 19 | public: 20 | void Insert(int v); 21 | int GetValue(); 22 | }; 23 | 24 | void Median::Insert(int v) 25 | { 26 | if (max_heap.empty() && min_heap.empty()) 27 | max_heap.push(v); 28 | else if (!max_heap.empty() && min_heap.empty()) 29 | max_heap.push(v); 30 | else if (max_heap.empty() && !min_heap.empty()) 31 | min_heap.push(v); 32 | else 33 | { 34 | if (v < max_heap.top()) 35 | max_heap.push(v); 36 | else 37 | min_heap.push(v); 38 | } 39 | 40 | while (max_heap.size() > min_heap.size() + 1) 41 | { 42 | int data = max_heap.top(); 43 | min_heap.push(data); 44 | max_heap.pop(); 45 | } 46 | while (min_heap.size() > max_heap.size() + 1) 47 | { 48 | int data = min_heap.top(); 49 | max_heap.push(data); 50 | min_heap.pop(); 51 | } 52 | } 53 | 54 | int Median::GetValue() 55 | { 56 | if (max_heap.empty() && min_heap.empty()) 57 | return (1 << 31); 58 | if (max_heap.size() == min_heap.size()) 59 | return (max_heap.size() + min_heap.size()) / 2; 60 | else if (max_heap.size() > min_heap.size()) 61 | return min_heap.top(); 62 | else 63 | return min_heap.top(); 64 | } 65 | 66 | int main() 67 | { 68 | srand((unsigned)time(0)); 69 | Median md; 70 | vector vi; 71 | int num = rand() % 30; 72 | for (int i = 0; i < num; ++i) 73 | { 74 | int data = rand() % 100; 75 | vi.push_back(data); 76 | md.Insert(data); 77 | } 78 | sort(vi.begin(), vi.end()); 79 | for (int i = 0; i < num; ++i) 80 | cout << vi.at(i) << " "; 81 | cout << endl << md.GetValue() << endl; 82 | return 0; 83 | } 84 | -------------------------------------------------------------------------------- /Solutions/Chapter 4 Trees and Graphs/4.4.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | *Given a binary search tree,design an algorithm which creates a linked list of aall nodes at each depth 3 | *(i.e.,if you have a tree with depth D,you'll have D linked lists). 4 | */ 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | using namespace std; 11 | 12 | const int maxn = 100; 13 | struct Node 14 | { 15 | int key; 16 | Node *lchild, *rchild,*parent; 17 | }; 18 | Node *p, node[maxn]; 19 | int cnt; 20 | 21 | void init() 22 | { 23 | p = NULL; 24 | memset(node,'\0',sizeof(node)); 25 | cnt = 0; 26 | } 27 | void createMinimalTree(Node* &head, Node *parent, int a[], int start, int end) 28 | { 29 | if (start <= end) 30 | { 31 | int mid = (start + end) >> 1; 32 | node[cnt].key = a[mid]; 33 | node[cnt].parent = parent; 34 | head = &node[cnt++]; 35 | createMinimalTree(head->lchild,head,a,start,mid-1); 36 | createMinimalTree(head->rchild,head,a,mid+1,end); 37 | } 38 | } 39 | 40 | vector> find_level_linklists(Node *head) 41 | { 42 | vector> res; 43 | int level = 0; 44 | listli; 45 | li.push_back(head); 46 | res.push_back(li); 47 | while (!res[level].empty()) 48 | { 49 | listl; 50 | list::iterator it; 51 | for (it = res[level].begin(); it != res[level].end(); ++it) 52 | { 53 | Node *n = *it; 54 | if (n->lchild) l.push_back(n->lchild); 55 | if (n->rchild) l.push_back(n->rchild); 56 | } 57 | ++level; 58 | res.push_back(l); 59 | } 60 | return res; 61 | } 62 | void print(vector>res) 63 | { 64 | vector>::iterator vit; 65 | for (vit = res.begin(); vit != res.end(); ++vit) 66 | { 67 | list li = *vit; 68 | list::iterator lit; 69 | for (lit = li.begin(); lit != li.end(); ++lit) 70 | { 71 | Node *n = *lit; 72 | cout << n->key << " "; 73 | } 74 | cout << endl; 75 | } 76 | } 77 | int main() 78 | { 79 | init(); 80 | int a[] = { 0,1,2,3,4,5,6,7,8 }; 81 | Node *head = NULL; 82 | createMinimalTree(head, NULL,a,0,6); 83 | vector> res; 84 | res = find_level_linklists(head); 85 | print(res); 86 | return 0; 87 | } 88 | -------------------------------------------------------------------------------- /Solutions/Chapter 5 Bit Manipulation/5.3.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | *Q5.3 Given an integer,print the next smallest and next largest number that have the same number of 1 bits in their binary representation. 3 | */ 4 | 5 | #include 6 | using namespace std; 7 | 8 | int cout_one0(int x) 9 | { 10 | int cnt = 0; 11 | for (int i = 0; i < 32; ++i) 12 | { 13 | if (x & 1) ++cnt; 14 | x >>= 1; 15 | } 16 | return cnt; 17 | } 18 | int count_one(int x) 19 | { 20 | x = (x&(0x55555555))+((x>>1)&(0x55555555)); 21 | x = (x&(0x33333333))+((x>>2)&(0x33333333)); 22 | x = (x&(0x0f0f0f0f))+((x>>4)&(0x0f0f0f0f)); 23 | x = (x&(0x00ff00ff))+((x>>8)&(0x00ff00ff)); 24 | x = (x&(0x0000ffff))+((x>>16)&(0x0000ffff)); 25 | return x; 26 | } 27 | int next(int x) 28 | { 29 | int max_int = ~(1 << 31); 30 | int num = count_one(x); 31 | if (num == 0 || x == -1) return -1; 32 | for (++x; count_one(x) != num&&x < max_int; ++x); 33 | if (count_one(x) == num) return x; 34 | return -1; 35 | } 36 | int previos(int x) 37 | { 38 | int min_int = ~(1<<31); 39 | int num = count_one(x); 40 | if (num == 0 || x == -1) return -1; 41 | for (--x; count_one(x) != num&&x > min_int; --x) 42 | if (count_one(x) == num) return x; 43 | return -1; 44 | } 45 | int next1(int x) 46 | { 47 | int xx = x, bit = 0; 48 | for (; (x & 1) != 1 && bit < 32; x >> 1, ++bit); 49 | for (; (x & 1) != 0 && bit < 32;x>>=1,++bit); 50 | if (bit == 31) return -1;//011..,none satisify 51 | x |= 1; 52 | x << bit;//...,x<<32!=0,so use next line to make x=0 53 | if (bit == 32) x = 0;//for 111--..00 54 | int num1 = count_one(xx) - count_one(x); 55 | int c = 1; 56 | for (; num1 > 0;x|=c,--num1,c<<=1); 57 | return x; 58 | } 59 | int previous1(int x) 60 | { 61 | int xx = x, bit = 0; 62 | for (; (x & 1) != 0 && bit < 32; x <<= 1, ++bit); 63 | for (; (x & 1) != 1 && bit < 32; x >>= 1, ++bit); 64 | if (bit == 31) return -1;//100..11,none satisify 65 | x -= 1; 66 | x <<= bit; 67 | if (bit == 32) x = 0; 68 | int num1 = count_one(xx) - count_one(x); 69 | x >>= bit; 70 | for (; num1 > 0;x=(x<<1)|1,--num1,--bit); 71 | x <<= bit; 72 | return x; 73 | } 74 | int main() 75 | { 76 | int a = -976756;// 77 | cout << next(a) << " " << previos(a) << endl; 78 | cout << next1(a) << " " << previous1(a) << endl; 79 | return 0; 80 | } 81 | -------------------------------------------------------------------------------- /Solutions/Chapter 8 Recursion/8.2.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | *Q 8.2 Image a robot sitting on the upper lest corner of an N*N grid.The robot can only move in two directions: 3 | *right and down.How many possible paths are there for the robot? 4 | */ 5 | 6 | #include 7 | #include 8 | #include 9 | using namespace std; 10 | 11 | typedef long long ll; 12 | typedef struct point 13 | { 14 | int x, y; 15 | }point; 16 | 17 | stack sp; 18 | const int MAXN = 20; 19 | int g[MAXN][MAXN]; 20 | point vp[MAXN + MAXN]; 21 | 22 | ll path(ll m, ll n) 23 | { 24 | if (m == 1 || n == 1) return 1; 25 | else return path(m - 1, n) + path(m, n - 1); 26 | } 27 | ll fact(ll n) 28 | { 29 | if (n == 0) return 1; 30 | else return n*fact(n - 1); 31 | } 32 | ll path1(ll m, ll n) 33 | { 34 | return fact(m - 1 + n - 1) / (fact(m - 1)*fact(n - 1)); 35 | } 36 | bool get_path(int m, int n) 37 | { 38 | point p; p.x = n; p.y = m; 39 | sp.push(p); 40 | if (n == 1 && m == 1) return true; 41 | bool suc = false; 42 | if (m > 1 && g[m - 1][n]) 43 | suc = get_path(m - 1, n); 44 | if (!suc&&n > 1 && g[m][n - 1]) 45 | suc = get_path(m, n - 1); 46 | if (!suc) sp.pop(); 47 | return suc; 48 | } 49 | void print_paths(int m, int n, int M, int N, int len) 50 | { 51 | if (g[m][n] == 0) return; 52 | point p; p.x = n; p.y = m; 53 | vp[len++] = p; 54 | if (m == M&&n == N) 55 | { 56 | for (int i = 0; i < len; ++i) 57 | cout << "(" << vp[i].y << "," << vp[i].x << ")" << " "; 58 | cout << endl; 59 | } 60 | else 61 | { 62 | print_paths(m,n+1,M,N,len); 63 | print_paths(m+1,n,M,N,len); 64 | } 65 | } 66 | int main() 67 | { 68 | freopen("8.2.in","r",stdin); 69 | for (int i = 1; i < 10; ++i) 70 | cout << path(i, i) << endl; 71 | cout << endl; 72 | for (int i = 1; i < 10; ++i) 73 | cout << path1(i, i) << endl; 74 | cout << endl; 75 | int M, N; 76 | cin >> M >> N; 77 | for (int i = 1; i <= M; ++i) 78 | for (int j = 1; j <= N; ++j) 79 | cin >> g[i][j]; 80 | cout << "one of the paths:" << endl; 81 | get_path(M,N); 82 | while (!sp.empty()) 83 | { 84 | point p = sp.top(); 85 | cout << "(" << p.y << "," << p.x<<")" << " "; 86 | sp.pop(); 87 | } 88 | cout << endl << "all paths:" << endl; 89 | print_paths(1,1,M,N,0); 90 | fclose(stdin); 91 | return 0; 92 | } 93 | -------------------------------------------------------------------------------- /Solutions/Chapter 2 Linked Lists/2.4.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | *Q2.4 You have two numbers represented by a linked list,where each node contains a single digit. 3 | *The digit are stored in reverse order,such that the 1's digit is at the head of the list. 4 | *Write a function that adds the two numbers thr sum as a linked list. 5 | *Example: 6 | *Input:(3->1->5),(5->9->2) 7 | *Output:8->0->8 8 | */ 9 | 10 | #include 11 | using namespace std; 12 | 13 | typedef struct node 14 | { 15 | int data; 16 | node *next; 17 | }node; 18 | 19 | node* init(int a[], int n) 20 | { 21 | node *head = NULL, *p; 22 | for (int i = 0; i < n; ++i) 23 | { 24 | node *nd = new node(); 25 | nd->data = a[i]; 26 | if (i == 0) 27 | { 28 | head = p = nd; 29 | continue; 30 | } 31 | p->next = nd; 32 | p = nd; 33 | } 34 | return head; 35 | } 36 | 37 | node* addlink(node *p, node *q) 38 | { 39 | if (p == NULL) return q; 40 | if (q == NULL) return p; 41 | node *res, *pre = NULL; 42 | int c = 0; 43 | while (p&&q) 44 | { 45 | int t = p->data + q->data + c; 46 | node *r = new node(); 47 | r->data = t % 10; 48 | if (pre) 49 | { 50 | pre->next = r; 51 | pre = r; 52 | } 53 | else pre = res = r; 54 | c = t % 10; 55 | p = p->next; q = q->next; 56 | } 57 | while (p) 58 | { 59 | int t = p->data + c; 60 | node *r = new node(); 61 | r->data = t % 10; 62 | pre->next = r; 63 | pre = r; 64 | c = t / 10; 65 | p = p->next; 66 | } 67 | while (q) 68 | { 69 | int t = q->data + c; 70 | node *r = new node(); 71 | r->data = t % 10; 72 | pre->next = r; 73 | pre = r; 74 | c = t / 10; 75 | q = q->next; 76 | } 77 | if (c > 0) 78 | { 79 | node *r = new node(); 80 | r->data = c; 81 | pre->next = r; 82 | } 83 | return res; 84 | } 85 | 86 | void print(node *head) 87 | { 88 | while (head) 89 | { 90 | cout << head->data << " "; 91 | head = head->next; 92 | } 93 | cout << endl; 94 | } 95 | 96 | int main() 97 | { 98 | int n = 4; 99 | int a[] = {1,2,9,3}; 100 | int m = 3; 101 | int b[] = { 8,8,4 }; 102 | 103 | node *p = init(a, n); 104 | node *q = init(b, m); 105 | node *res = addlink(p,q); 106 | if (p) print(p); 107 | if (q) print(q); 108 | if (res) print(res); 109 | return 0; 110 | } 111 | -------------------------------------------------------------------------------- /Solutions/Chapter 3 Stacks and Queues/3.1.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | *Q3.1 Describe how you could use a single array to implement three stacks. 3 | */ 4 | 5 | #include 6 | using namespace std; 7 | 8 | class stack3 { 9 | public: 10 | stack3(int size = 300) { 11 | buf = new int[size * 3]; 12 | ptop[0] = ptop[1] = ptop[2] = -1; 13 | this->size = size; 14 | } 15 | ~stack3() { 16 | delete[]buf; 17 | } 18 | void push(int stackNum, int val) { 19 | int idx = stackNum*size + ptop[stackNum] + 1; 20 | buf[idx] = val; 21 | ++ptop[stackNum]; 22 | } 23 | void pop(int stackNum) { 24 | --ptop[stackNum]; 25 | } 26 | int top(int stackNum) { 27 | int idx = stackNum*size + ptop[stackNum]; 28 | return buf[idx]; 29 | } 30 | bool empty(int stackNum) { 31 | return ptop[stackNum] == -1; 32 | } 33 | 34 | private: 35 | int *buf; 36 | int ptop[3]; 37 | int size; 38 | }; 39 | 40 | typedef struct node { 41 | int val, preIdx; 42 | }node; 43 | 44 | class stack3_1 { 45 | public: 46 | stack3_1(int totalSize = 900) { 47 | buf = new node[totalSize]; 48 | ptop[0] = ptop[1] = ptop[2] = -1; 49 | this->totalSize = totalSize; 50 | cur = 0; 51 | } 52 | ~stack3_1() { 53 | delete[] buf; 54 | } 55 | void push(int stackNum, int val) { 56 | buf[cur].val = val; 57 | buf[cur].preIdx = ptop[stackNum]; 58 | ptop[stackNum] = cur; 59 | ++cur; 60 | } 61 | void pop(int stackNum) { 62 | ptop[stackNum] = buf[ptop[stackNum]].preIdx; 63 | } 64 | int top(int stackNum) { 65 | return buf[ptop[stackNum]].val; 66 | } 67 | bool empty(int stackNum) { 68 | return ptop[stackNum] == -1; 69 | } 70 | 71 | private: 72 | node *buf; 73 | int ptop[3]; 74 | int totalSize; 75 | int cur; 76 | }; 77 | 78 | int main() 79 | { 80 | stack3_1 mystack; 81 | for (int i = 0; i < 10; ++i) 82 | mystack.push(0,i); 83 | for (int i = 0; i < 20; ++i) 84 | mystack.push(1,i); 85 | for (int i = 0; i < 110; ++i) 86 | mystack.push(2,i); 87 | for (int i = 0; i < 3; ++i) 88 | cout << mystack.top(i) << " "; 89 | 90 | cout << endl; 91 | for (int i = 0; i < 3; ++i) 92 | { 93 | mystack.pop(i); 94 | cout << mystack.top(i) << " "; 95 | } 96 | mystack.push(0,111); 97 | mystack.push(1,222); 98 | mystack.push(2,333); 99 | for (int i = 0; i < 3; ++i) 100 | cout << mystack.top(i) << " "; 101 | return 0; 102 | } 103 | -------------------------------------------------------------------------------- /Solutions/Chapter 4 Trees and Graphs/4.8.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | *Q4.8 You are given a binary tree which each node contains a value. 3 | *Design an algorithm to print all paths which sum up to that value. 4 | *Node that it can be any path int the tree-it does not have to start at the root. 5 | */ 6 | 7 | #include 8 | #include 9 | #include 10 | using namespace std; 11 | 12 | const int maxn = 100; 13 | struct Node 14 | { 15 | int key; 16 | Node *lchild, *rchild, *parent; 17 | }; 18 | Node node[maxn]; 19 | int cnt; 20 | 21 | void init() 22 | { 23 | memset(node,'\0',sizeof(node)); 24 | cnt = 0; 25 | } 26 | void create_minimal_tree(Node* &head, Node *parent, int a[], int start, int end) 27 | { 28 | if (start <= end) 29 | { 30 | int mid = (start + end) >> 1; 31 | node[cnt].key = a[mid]; 32 | node[cnt].parent = parent; 33 | head = &node[cnt++]; 34 | create_minimal_tree(head->lchild,head,a,start,mid-1); 35 | create_minimal_tree(head->rchild, head, a, mid + 1, end); 36 | } 37 | } 38 | void print(Node* head, int level) 39 | { 40 | vector v; 41 | for (int i = 0; i < level; ++i) 42 | { 43 | v.push_back(head->key); 44 | head = head->parent; 45 | } 46 | while (!v.empty()) 47 | { 48 | cout << v.back() << " "; 49 | v.pop_back(); 50 | } 51 | cout << endl; 52 | } 53 | void find_sum(Node* head, int sum) 54 | { 55 | if (head == NULL) return; 56 | Node *no = head; 57 | int tmp = 0; 58 | for (int i = 1; no != NULL; ++i) 59 | { 60 | tmp += no->key; 61 | if (tmp == sum) 62 | print(head, i); 63 | no = no->parent; 64 | } 65 | find_sum(head->lchild,sum); 66 | find_sum(head->rchild,sum); 67 | } 68 | void print2(vectorv, int level) 69 | { 70 | for (int i = level; i < v.size(); ++i) 71 | cout << v.at(i) << " "; 72 | cout << endl; 73 | } 74 | void find_sum2(Node* head, int sum, vector v, int level) 75 | { 76 | if (head == NULL) return; 77 | v.push_back(head->key); 78 | int tmp = 0; 79 | for (int i = level; i > -1; --i) 80 | { 81 | tmp += v.at(i); 82 | if (tmp == sum) 83 | print2(v, i); 84 | } 85 | vector v1(v), v2(v); 86 | find_sum2(head->lchild,sum,v1,level+1); 87 | find_sum2(head->rchild,sum,v2,level+1); 88 | } 89 | int main() 90 | { 91 | init(); 92 | int a[] = {4,3,8,5,2,1,6}; 93 | Node *head = NULL; 94 | create_minimal_tree(head, NULL, a, 0, 6); 95 | vector v; 96 | find_sum2(head,8,v,0); 97 | return 0; 98 | } 99 | -------------------------------------------------------------------------------- /Solutions/Chapter 20 Hard/ac_automation.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * AC automation 3 | */ 4 | 5 | #include 6 | #include 7 | #include 8 | using namespace std; 9 | 10 | class ACAutomation { 11 | public: 12 | static const int MAX_N = 1000 * 50; 13 | static const int CLD_NUM = 26; 14 | 15 | int size; 16 | int fail[MAX_N]; 17 | int tag[MAX_N]; 18 | int trie[MAX_N][CLD_NUM]; 19 | 20 | void reset(); 21 | void insert(const char* s); 22 | void construct(); 23 | int query(const char* s); 24 | }; 25 | 26 | void ACAutomation::reset() 27 | { 28 | memset(trie[0],-1,sizeof(trie[0])); 29 | tag[0] = 0; 30 | size = 1; 31 | } 32 | 33 | void ACAutomation::insert(const char* s) 34 | { 35 | int p = 0; 36 | while (*s) 37 | { 38 | int i = *s - 'a'; 39 | if (-1 == trie[p][i]) 40 | { 41 | memset(trie[size],-1,sizeof(trie[size])); 42 | tag[size] = 0; 43 | trie[p][i] = size++; 44 | } 45 | p = trie[p][i]; 46 | ++s; 47 | } 48 | ++tag[p]; 49 | } 50 | 51 | void ACAutomation::construct() 52 | { 53 | queue q; 54 | fail[0] = 0; 55 | for (int i = 0; i < CLD_NUM; ++i) 56 | { 57 | if (-1 != trie[0][i]) 58 | { 59 | fail[trie[0][i]] = 0; 60 | q.push(trie[0][i]); 61 | } 62 | else 63 | trie[0][i] = 0; 64 | } 65 | while (!q.empty()) 66 | { 67 | int u = q.front(); 68 | q.pop(); 69 | for (int i = 0; i < CLD_NUM; ++i) 70 | { 71 | int &v = trie[u][i]; 72 | if (-1 != v) 73 | { 74 | q.push(v); 75 | fail[v] = trie[fail[u]][i]; 76 | } 77 | else 78 | v = trie[fail[u]][i]; 79 | } 80 | } 81 | } 82 | 83 | int ACAutomation::query(const char* s) 84 | { 85 | int p = 0, cnt = 0; 86 | while (*s) 87 | { 88 | int i = *s - 'a'; 89 | while (-1 == trie[p][i] && p != 0) 90 | p = fail[p]; 91 | p = trie[p][i]; 92 | p = p == -1 ? 0 : p; 93 | int t = p; 94 | while (t != 0 && tag[t] != -1) 95 | { 96 | cnt += tag[t]; 97 | tag[t] = -1; 98 | t = fail[t]; 99 | } 100 | ++s; 101 | } 102 | return cnt; 103 | } 104 | 105 | int main() 106 | { 107 | ACAutomation ac; 108 | ac.reset(); 109 | string patt[] = {"is","sip","is","sis","mississip"}; 110 | int n = 5; 111 | for (int i = 0; i < n; ++i) 112 | ac.insert((char*)&patt[i][0]); 113 | ac.construct(); 114 | cout << ac.query("mississippi") << endl; 115 | return 0; 116 | } 117 | -------------------------------------------------------------------------------- /Solutions/Chapter 3 Stacks and Queues/3.5.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | *Q3.5 Implement a MyQueue(FIFO) class which implements a queue using two stacks(FILO). 3 | */ 4 | 5 | #include 6 | #include 7 | using namespace std; 8 | 9 | template 10 | class MyQueue { 11 | public: 12 | MyQueue() { 13 | } 14 | ~MyQueue() { 15 | } 16 | void push(T val) { 17 | move(sout, sin); 18 | sin.push(val); 19 | } 20 | void pop() { 21 | move(sin,sout); 22 | sout.pop(); 23 | } 24 | T front() { 25 | move(sin,sout); 26 | return sout.top(); 27 | } 28 | T back() { 29 | move(sout, sin); 30 | return sin.top(); 31 | } 32 | int size() { 33 | return sin.size() + sout.size(); 34 | } 35 | bool empty() { 36 | return sin.empty() && sout.empty(); 37 | } 38 | void move(stack&src, stack&dst) { 39 | while (!src.empty()) { 40 | dst.push(src.top()); 41 | src.pop(); 42 | } 43 | } 44 | 45 | private: 46 | stack sin, sout; 47 | }; 48 | 49 | template 50 | class MyQueue1 { 51 | public: 52 | MyQueue1() { 53 | } 54 | ~MyQueue1() { 55 | } 56 | void push(T val) { 57 | sin.push(val); 58 | } 59 | void pop() { 60 | move(sin,sout); 61 | sout.pop(); 62 | } 63 | T front() { 64 | move(sin,sout); 65 | return sout.top(); 66 | } 67 | T back() { 68 | move(sout, sin); 69 | return sin.top(); 70 | } 71 | int size() { 72 | return sin.size() + sout.size(); 73 | } 74 | bool empty() { 75 | return sin.empty() && sout.empty(); 76 | } 77 | void move(stack&src, stack&dst) { 78 | if (dst.empty()) { 79 | while (!src.empty()) { 80 | dst.push(src.top()); 81 | src.pop(); 82 | } 83 | } 84 | } 85 | 86 | private: 87 | stack sin, sout; 88 | }; 89 | 90 | int main() { 91 | MyQueue q; 92 | MyQueueq1; 93 | for (int i = 0; i < 10; ++i) 94 | { 95 | q.push(i); 96 | q1.push(i); 97 | } 98 | 99 | cout << q.front() << " " << q.back() << endl; 100 | cout << q1.front() << " " << q1.back() << endl; 101 | cout << endl; 102 | q.pop(); 103 | q1.pop(); 104 | q.push(10); 105 | q1.push(10); 106 | cout << q.front() << " " << q.back() << endl; 107 | cout << q1.front() << " " << q1.back() << endl; 108 | cout << endl; 109 | cout << q.size() << " " << q.empty() << endl; 110 | cout << q1.size() << " " << q1.empty() << endl; 111 | return 0; 112 | } 113 | -------------------------------------------------------------------------------- /Solutions/Chapter 3 Stacks and Queues/3.2.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | *Q3.2 How would you design a stack which,in addition to push and pop,also has a function min which returns the minimum element? 3 | *Push,pop and min should all oprate in O(1) time. 4 | */ 5 | 6 | #include 7 | using namespace std; 8 | 9 | const int MAX_INT = ~(1 << 31); 10 | 11 | typedef struct node{ 12 | int val, min; 13 | }node; 14 | 15 | class StackWithMin { 16 | public: 17 | StackWithMin(int size = 1000) { 18 | buf = new node[size]; 19 | buf[0].min = MAX_INT; 20 | cur = 0; 21 | } 22 | ~StackWithMin() { 23 | delete[] buf; 24 | } 25 | void push(int val) { 26 | buf[++cur].val = val; 27 | if (val < buf[cur - 1].min) buf[cur].min = val; 28 | else buf[cur].min = buf[cur - 1].min; 29 | } 30 | void pop() { 31 | --cur; 32 | } 33 | int top() { 34 | return buf[cur].val; 35 | } 36 | bool empty() { 37 | return cur == 0; 38 | } 39 | int min() { 40 | return buf[cur].min; 41 | } 42 | private: 43 | node *buf; 44 | int cur; 45 | }; 46 | 47 | class stack { 48 | public: 49 | stack(int size = 1000) { 50 | buf = new int[size]; 51 | cur = -1; 52 | } 53 | ~stack() { 54 | delete[] buf; 55 | } 56 | void push(int val) { 57 | buf[++cur] = val; 58 | } 59 | void pop() { 60 | --cur; 61 | } 62 | int top() { 63 | return buf[cur]; 64 | } 65 | bool empty() { 66 | return cur == -1; 67 | } 68 | private: 69 | int *buf; 70 | int cur; 71 | }; 72 | 73 | class StackWithMin1 { 74 | public: 75 | StackWithMin1() { 76 | } 77 | ~StackWithMin1() { 78 | } 79 | void push(int val) { 80 | s1.push(val); 81 | if (val <= min()) 82 | s2.push(val); 83 | } 84 | void pop() { 85 | if (s1.top() == min()) 86 | s2.pop(); 87 | s1.pop(); 88 | } 89 | int top() { 90 | return s1.top(); 91 | } 92 | bool empty() { 93 | return s1.empty(); 94 | } 95 | int min() { 96 | if (s2.empty()) return MAX_INT; 97 | else return s2.top(); 98 | } 99 | private: 100 | stack s1, s2; 101 | }; 102 | int main() { 103 | StackWithMin1 mystack; 104 | for (int i = 0; i < 20; ++i) 105 | mystack.push(i); 106 | cout << mystack.min() << " " << mystack.top() << endl; 107 | mystack.push(-100); 108 | mystack.push(-100); 109 | cout << mystack.min() << " " << mystack.top() << endl; 110 | mystack.pop(); 111 | cout << mystack.min() << " " << mystack.top() << endl; 112 | return 0; 113 | } 114 | -------------------------------------------------------------------------------- /Solutions/Chapter 19 Moderate/19.5.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Q 19.5 The Game of Master is played as below: 3 | * The computer has dour slots containing balls that are red(R),yellow(Y),green(G)or blue(B). 4 | * For example:the computer might have RGGB(e.g.,Slot#1 is red,Slot#2 and Slot#3 are green,Slot#4 is blue). 5 | * You,the user,are trying to guess the solution.You might,for example,guess YRGB. 6 | * When you guess the correct color for the correct slot,you get a "hit". 7 | * If you guess a color that exists but is in the wrong slot,you get a "pseudo-hit". 8 | * For example:the guess YGRB has 2 hits and ine pseudo hit. 9 | * 10 | * For each guess,you are told the number of hits and pseudo-hits.Write a method that,given a guess and a solution, 11 | * returns the number of hits and pseudo hits. 12 | */ 13 | 14 | #include 15 | #include 16 | using namespace std; 17 | 18 | struct Result 19 | { 20 | int hits; 21 | int pseudo_hits; 22 | }; 23 | 24 | Result Estimate(const char* solution, const char* guess) 25 | { 26 | Result res; 27 | res.hits = 0; 28 | res.pseudo_hits = 0; 29 | int solution_mask = 0; 30 | for (int i = 0; i < 4; ++i) 31 | { 32 | solution_mask |= 1 << (solution[i]-'A'); 33 | 34 | } 35 | for (int i = 0; i < 4; ++i) 36 | { 37 | if (guess[i] == solution[i]) 38 | ++res.hits; 39 | else if (solution_mask &(1 << (guess[i] - 'A'))) 40 | ++res.pseudo_hits; 41 | } 42 | return res; 43 | } 44 | 45 | int Min(int a, int b) 46 | { 47 | return a < b ? a : b; 48 | } 49 | 50 | Result Estimate1(const char* solution, const char* guess) 51 | { 52 | Result res; 53 | res.hits = 0; 54 | res.pseudo_hits = 0; 55 | const int num = 26 + 5; 56 | int guess_count[num], solution_count[num]; 57 | memset(guess_count, 0, sizeof(guess_count)); 58 | memset(solution_count, 0, sizeof(solution_count)); 59 | for (int i = 0; i < 4; ++i) 60 | { 61 | if (guess[i] == solution[i]) 62 | ++res.hits; 63 | ++guess_count[(int)(guess[i] - 'A')]; 64 | ++solution_count[(int)(solution_count[i] - 'A')]; 65 | } 66 | char color[] = "RGBY"; 67 | for (int i = 0; i < 4; ++i) 68 | { 69 | int idx = (int)(color[i] - 'A'); 70 | res.pseudo_hits += Min(guess_count[idx], solution_count[idx]); 71 | } 72 | res.pseudo_hits -= res.hits; 73 | return res; 74 | } 75 | 76 | int main() 77 | { 78 | char solution[] = "RYGB"; 79 | char guess[] = "YRRR"; 80 | Result res = Estimate(solution, guess); 81 | cout << res.hits << " " << res.pseudo_hits << endl; 82 | Result res1 = Estimate1(solution, guess); 83 | cout << res1.hits << " " << res1.pseudo_hits << endl; 84 | return 0; 85 | } 86 | 87 | 88 | -------------------------------------------------------------------------------- /Solutions/Chapter 4 Trees and Graphs/4.6.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | *Q4.6 Design an algorithm and write code to find the first common ancestor of two nodes in a binary tree. 3 | *Avoid storing addtional nodes ina data strcucture. 4 | *NOTE:This is not necessarily a binary search tree. 5 | */ 6 | 7 | #include 8 | #include 9 | #include 10 | using namespace std; 11 | 12 | const int maxn = 100; 13 | struct Node 14 | { 15 | int key; 16 | Node *lchild, *rchild, *parent; 17 | }; 18 | Node *p, node[maxn]; 19 | int cnt; 20 | 21 | void init() 22 | { 23 | p = NULL; 24 | memset(node,'\0',sizeof(node)); 25 | cnt = 0; 26 | } 27 | void create_minial_tree(Node* &head, Node *parent, int a[], int start, int end) 28 | { 29 | if (start <= end) 30 | { 31 | int mid=(start + end)>>1; 32 | node[cnt].key = a[mid]; 33 | node[cnt].parent = parent; 34 | head = &node[cnt++]; 35 | create_minial_tree(head->lchild, head, a, start, mid - 1); 36 | create_minial_tree(head->rchild,head,a,mid+1,end); 37 | } 38 | } 39 | Node* first_ancestor(Node* n1, Node* n2) 40 | { 41 | if (n1 == NULL || n2 == NULL) return NULL; 42 | mapm; 43 | while (n1) 44 | { 45 | m[n1] = true; 46 | n1 = n1->parent; 47 | } 48 | while (n2 && !m[n2]) 49 | { 50 | n2 = n2->parent; 51 | } 52 | return n2; 53 | } 54 | bool father(Node* n1, Node* n2) 55 | { 56 | if (n1 == NULL) return false; 57 | else if (n1 == n2) return true; 58 | else return father(n1->lchild, n2) || father(n1->rchild, n2); 59 | } 60 | Node* first_ancestor1(Node* n1, Node* n2) 61 | { 62 | if (n1 == NULL || n2 == NULL) return NULL; 63 | while (n1) 64 | { 65 | if (father(n1, n2)) return n1; 66 | n1 = n1->parent; 67 | } 68 | return NULL; 69 | } 70 | void first_ancestor2(Node* head, Node* n1, Node* n2, Node* &ans) 71 | { 72 | if (head == NULL || n1 == NULL || n2 == NULL) return; 73 | if (head && father(head, n1) && father(head, n2)) 74 | { 75 | ans = head; 76 | first_ancestor2(head->lchild,n1,n2,ans); 77 | first_ancestor2(head->rchild,n1,n2,ans); 78 | } 79 | } 80 | Node* search(Node* head, int x) 81 | { 82 | if (head == NULL) return NULL; 83 | else if (x == head->key) return NULL; 84 | else if (x <= head->key) search(head->lchild, x); 85 | else search(head->rchild,x); 86 | } 87 | int main() 88 | { 89 | init(); 90 | int a[] = { 0,1,2,3,4,5,6 }; 91 | Node *head = NULL; 92 | create_minial_tree(head,NULL,a,0,6); 93 | Node *n1 = search(head, 0); 94 | Node *n2 = search(head, 4); 95 | cout << n1->key << " " << n2->key << endl; 96 | Node *ans = first_ancestor(n1, n2); 97 | cout << ans->key << endl; 98 | Node *ans1 = NULL; 99 | first_ancestor2(head,n1,n2,ans1); 100 | cout << ans1->key << endl; 101 | return 0; 102 | } 103 | -------------------------------------------------------------------------------- /Solutions/Chapter 12 System Design and Memory Limits/12.4.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * TASK: You are given an array storing numbers in [0,32000). Using only 4kB of 3 | * memory, print all numbers which appear at least twice in the array. 4 | * 5 | * NOTE: I have slightly modified the original question since requiring that 6 | * the array has all numbers in [0,N] for some N in [0,32000) does not add 7 | * any complexity to the problem. 8 | */ 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | /** 17 | * @brief Returns a bitset indicating which numbers in an array of size n are 18 | * duplicates, where the array numbers are in the range [0,32000). 19 | * @note Complexity: O(n) in time, O(1) in space. 20 | * @note This function uses, in total, 4002 bytes of memory to detect 21 | * duplicates, but since we are returning a bitset with 32000 bits, it 22 | * uses 8002 bytes in total (this would not be the case if we merely 23 | * printed the duplicate values). 24 | */ 25 | std::bitset<32000> get_duplicates(const std::vector& values) 26 | { 27 | std::bitset<32000> seen(false); 28 | std::bitset<32000> duplicate(false); 29 | 30 | for (const uint16_t x : values) 31 | { 32 | if (seen[x] == true) 33 | { 34 | duplicate[x] = true; 35 | } 36 | else 37 | { 38 | seen[x] = true; 39 | } 40 | } 41 | 42 | return duplicate; 43 | } 44 | 45 | /** 46 | * @brief Returns a random vector containing n integer values in [0,32000). 47 | * @note Complexity: O(n) in both time and space. 48 | */ 49 | std::vector random_vector(const size_t n) 50 | { 51 | static std::random_device device; 52 | static std::mt19937 generator(device()); 53 | 54 | std::uniform_int_distribution distribution(0, 31999); 55 | 56 | std::vector values; 57 | 58 | while (values.size() < n) 59 | { 60 | values.push_back(distribution(generator)); 61 | } 62 | 63 | return values; 64 | } 65 | 66 | int main() 67 | { 68 | for (size_t n = 0; n <= 100000; n += 1000) 69 | { 70 | std::vector values = random_vector(n); 71 | 72 | std::bitset<32000> duplicates = get_duplicates(values); 73 | 74 | std::sort(values.begin(), values.end()); 75 | 76 | for (size_t i = 1; i + 1 < values.size(); ++i) 77 | { 78 | bool is_duplicate = 79 | (values[i] == values[i - 1]) || (values[i] == values[i + 1]); 80 | 81 | assert(duplicates[values[i]] == is_duplicate); 82 | } 83 | 84 | std::cout << "passed random test for array of size " << n << std::endl; 85 | } 86 | 87 | return EXIT_SUCCESS; 88 | } 89 | -------------------------------------------------------------------------------- /Solutions/Chapter 1 Arrays and Strings/1.3.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | *Q1.3 Design an algorithm and write code to remove the duplicate charaters in a string without using any additional buffer. 3 | *NOTE:One or twp addtional variables are fine.An extra copy of the array is not. 4 | *FOLLOW UP 5 | *Write the test cases for this method. 6 | */ 7 | 8 | #include 9 | #include 10 | #include 11 | using namespace std; 12 | 13 | string removeDuplicate1(string s) 14 | { 15 | int check = 0; 16 | int len = s.length(); 17 | if (len < 2) return s; 18 | string str = ""; 19 | for (int i = 0; i < len; ++i) 20 | { 21 | int v = (int)(s[i] - 'a'); 22 | if ((check & (1 << v)) == 0) 23 | { 24 | str += s[i]; 25 | check |= (1< 8 | #include 9 | #include 10 | #include 11 | 12 | /** 13 | * @brief Computes -a using only additions (-a = a + (-2)*a). 14 | * @note Complexity: O(|a|) in time, O(1) in space. 15 | */ 16 | int negative(int a) 17 | { 18 | int b = a; 19 | 20 | if (a > 0) 21 | { 22 | while (a > 0) 23 | { 24 | b += (-2); 25 | --a; 26 | } 27 | } 28 | else 29 | { 30 | while (a < 0) 31 | { 32 | b += 2; 33 | ++a; 34 | } 35 | } 36 | 37 | return b; 38 | } 39 | 40 | /** 41 | * @brief Computes |a| using only additions. 42 | * @note Complexity: O(|a|) in time, O(1) in space. 43 | */ 44 | int magnitude(const int a) 45 | { 46 | return (a > 0) ? a : negative(a); 47 | } 48 | 49 | /** 50 | * @brief Computes a*b using only additions. 51 | * @note Complexity: O(|a|) in time, O(1) in space. 52 | */ 53 | int multiply(const int a, const int b) 54 | { 55 | int c = 0; 56 | 57 | /* c <-- |a|*b */ 58 | for (int i = magnitude(a); i > 0; --i) 59 | { 60 | c += b; 61 | } 62 | 63 | return (a < 0) ? negative(c) : c; 64 | } 65 | 66 | /** 67 | * @brief Computes (a-b) using only additions. 68 | * @note Complexity: O(|b|) in time, O(1) in space. 69 | */ 70 | int subtract(const int a, const int b) 71 | { 72 | return a + negative(b); 73 | } 74 | 75 | /** 76 | * @brief Computes a/b using only additions. 77 | * @note Complexity: O(max(|a|,|b|)) in time, O(1) in space. 78 | */ 79 | int divide(const int a, const int b) 80 | { 81 | if (b == 0) 82 | { 83 | throw std::overflow_error("cannot divide by zero"); 84 | } 85 | 86 | /* determine the sign of a/b */ 87 | int sign = ((a > 0 && b > 0) || (a < 0 && b < 0)) ? 1 : -1; 88 | 89 | const int a_mag = magnitude(a); 90 | const int b_mag = magnitude(b); 91 | 92 | int c = 0; 93 | int d = 0; 94 | 95 | /* d <-- |a|/|b| */ 96 | while (c + b_mag <= a_mag) 97 | { 98 | c += b_mag; 99 | ++d; 100 | } 101 | 102 | return (sign == 1) ? d : negative(d); 103 | } 104 | 105 | int main() 106 | { 107 | std::random_device device; 108 | std::mt19937 generator(device()); 109 | 110 | std::uniform_int_distribution distribution(-1000, 1000); 111 | 112 | for (int i = 0; i < 1000; ++i) 113 | { 114 | int a = distribution(generator); 115 | int b = distribution(generator); 116 | 117 | assert(negative(a) == -a); 118 | assert(magnitude(a) == std::abs(a)); 119 | 120 | assert(subtract(a, b) == a - b); 121 | assert(multiply(a, b) == a * b); 122 | 123 | if (b != 0) 124 | { 125 | assert(divide(a, b) == a / b); 126 | } 127 | } 128 | 129 | std::cout << "passed random tests" << std::endl; 130 | 131 | return EXIT_SUCCESS; 132 | } 133 | -------------------------------------------------------------------------------- /Solutions/Chapter 12 System Design and Memory Limits/12.3.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * TASK: You are given a big file which has 4 billions integers. Assuming that 3 | * you have only 1GB of memory available, find an integer value which is 4 | * not in the file. Try also solving this problem assuming that you have 5 | * very little memory available, e.g. 10MB. 6 | * 7 | * NOTE: The solution below assumes that the integer values can be represented 8 | * in 32 bits, but will not work if we need 64 bits to represent them. 9 | */ 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | /** 17 | * @brief Finds a missing integer among the n given integers using a histogram. 18 | * @note Complexity: O(n) in time, O(1) in space. 19 | * @note This function uses, in total, less than 300kB of memory. 20 | */ 21 | int get_absent_int(const std::vector& values) 22 | { 23 | /* each bucket represents a range [x, x+65536) for some integer x */ 24 | static const uint32_t bucket_size = 65536; 25 | 26 | /* histogram with 65536 buckets: uses slightly more than ~260kB */ 27 | std::vector histogram(65536, 0); 28 | 29 | for (const uint32_t x : values) 30 | { 31 | ++histogram[x / bucket_size]; 32 | } 33 | 34 | /* find which bucket did not get filled up */ 35 | uint32_t xmin = 0; 36 | 37 | for (const uint32_t count : histogram) 38 | { 39 | if (count < bucket_size) 40 | { 41 | break; 42 | } 43 | 44 | xmin += bucket_size; 45 | } 46 | 47 | /* integer range represented by the incomplete bucket: [xmin, xmax) */ 48 | uint32_t xmax = xmin + bucket_size; 49 | 50 | /* 51 | * go over all input integers and mark all integers seen in [xmin, xmax) 52 | * as "seen"; this bucket uses ~8kB of memory 53 | */ 54 | std::vector seen(bucket_size, false); 55 | 56 | for (const uint32_t x : values) 57 | { 58 | if (xmin <= x && x < xmax) 59 | { 60 | seen[x - xmin] = true; 61 | } 62 | } 63 | 64 | /* determine an integer x in [xmin, xmax) which is missing */ 65 | uint32_t x = xmin; 66 | 67 | while (x < xmax) 68 | { 69 | if (seen[x - xmin] == false) 70 | { 71 | break; 72 | } 73 | 74 | ++x; 75 | } 76 | 77 | return x; 78 | } 79 | 80 | int main() 81 | { 82 | std::random_device device; 83 | std::mt19937 generator(device()); 84 | 85 | std::uniform_int_distribution distribution; 86 | 87 | for (int i = 0; i < 10; ++i) 88 | { 89 | std::vector values; 90 | 91 | /* 92 | * here we generate sets of integer values to emulate the input 93 | * file, but since 4 billion integers would not fit on most 94 | * modern computers in 2016, we generate sets which are small 95 | * enough just for testing purposes (with a million values) 96 | */ 97 | while (values.size() < 1000000) 98 | { 99 | values.push_back(distribution(generator)); 100 | } 101 | 102 | uint32_t x = get_absent_int(values); 103 | 104 | assert(std::find(values.begin(), values.end(), x) == values.end()); 105 | } 106 | 107 | std::cout << "passed all random tests" << std::endl; 108 | 109 | return EXIT_SUCCESS; 110 | } 111 | -------------------------------------------------------------------------------- /Solutions/Chapter 3 Stacks and Queues/3.3.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | *Q3.3 Imagine a(literial)stack of plates.If the stack gets too high,it might topple.Therefore,in real life,we would likely start a new stack when the 3 | *previous stack exceeds some threshold.Implement a data structure SetOfStacks that mimics this.SetOfStacks should be composed of serveral stacks,and 4 | *should create a new stack once the previous one exceeds capacity.SetOfStacks.push() and SetOfStacks.pop() should behave identically to a single stack 5 | *(that is,pop() should return the same values as if there were just a single stack). 6 | *FOLLOW UP 7 | *Implement a function popAt(int index) which performs a pop opration on a specific sub-stack. 8 | */ 9 | 10 | #include 11 | using namespace std; 12 | 13 | const int STACK_SIZE = 100; 14 | const int STACK_NUM = 10; 15 | class stack { 16 | private: 17 | int *buf; 18 | int cur; 19 | int capacity; 20 | public: 21 | stack(int capa = STACK_SIZE) { 22 | buf = new int[capa]; 23 | cur = -1; 24 | capacity = capa; 25 | } 26 | ~stack() { 27 | delete[] buf; 28 | } 29 | void push(int val) { 30 | buf[++cur] = val; 31 | } 32 | void pop() { 33 | --cur; 34 | } 35 | int top() { 36 | return buf[cur]; 37 | } 38 | bool empty() { 39 | return cur == -1; 40 | } 41 | bool full() { 42 | return cur == capacity - 1; 43 | } 44 | }; 45 | 46 | class SetOfStacks { 47 | private: 48 | stack *st; 49 | int cur; 50 | int capacity; 51 | 52 | public: 53 | SetOfStacks(int capa = STACK_NUM) { 54 | st = new stack[capa]; 55 | cur = 0; 56 | capacity = capa; 57 | } 58 | ~SetOfStacks() { 59 | delete[] st; 60 | } 61 | void push(int val) { 62 | if (st[cur].full()) ++cur; 63 | st[cur].push(val); 64 | } 65 | void pop() { 66 | if (st[cur].empty()) --cur; 67 | return st[cur].pop(); 68 | } 69 | bool empty() { 70 | if (cur == 0) return st[0].empty(); 71 | else return false; 72 | } 73 | bool full() { 74 | if (cur == capacity - 1) return st[cur].full(); 75 | else return false; 76 | } 77 | }; 78 | 79 | class SetOfStacks1 { 80 | private: 81 | stack *st; 82 | int cur; 83 | int capacity; 84 | 85 | public: 86 | SetOfStacks1(int capa = STACK_NUM) { 87 | st = new stack[capa]; 88 | cur = 0; 89 | capacity = capa; 90 | } 91 | ~SetOfStacks1() { 92 | delete[] st; 93 | } 94 | void push(int val) { 95 | if (st[cur].full()) ++cur; 96 | st[cur].push(val); 97 | } 98 | void pop() { 99 | while (st[cur].empty()) --cur; 100 | st[cur].pop(); 101 | } 102 | void popAt(int idx) { //popAt method 103 | while (st[idx].empty()) --idx; 104 | st[idx].pop(); 105 | } 106 | int top() { 107 | while (st[cur].empty()) --cur; 108 | return st[cur].top(); 109 | } 110 | bool empty() { 111 | while (cur != -1 && st[cur].empty()) --cur; 112 | if (cur == -1) return true; 113 | else return false; 114 | } 115 | bool full() { 116 | if (cur == capacity - 1) return st[cur].full(); 117 | else return false; 118 | } 119 | }; 120 | 121 | int main() { 122 | /*SetOfStacks ss; 123 | for (int i = 0; i < 3*STACK_SIZE + 1; ++i) 124 | { 125 | ss.push(i); 126 | } 127 | while (!ss.empty()) { 128 | cout << ss.top() << endl; 129 | ss.top(); 130 | }*/ 131 | 132 | SetOfStacks1 ss1; 133 | for (int i = 0; i < 3 * STACK_SIZE + 1; ++i) 134 | { 135 | ss1.push(i); 136 | } 137 | for (int i = 0; i < STACK_SIZE; ++i) 138 | { 139 | ss1.popAt(0); 140 | ss1.popAt(2); 141 | } 142 | ss1.popAt(3); 143 | while (!ss1.empty()) 144 | { 145 | cout << ss1.top() << endl; 146 | ss1.pop(); 147 | } 148 | 149 | return 0; 150 | } 151 | -------------------------------------------------------------------------------- /Solutions/Chapter 4 Trees and Graphs/BST.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | const int maxn = 100; 7 | 8 | typedef struct BST{ 9 | int key; 10 | BST *lchild, *rchild, *parent; 11 | }BST; 12 | BST *head, *p, node[maxn]; 13 | int cnt; 14 | 15 | void init(){ 16 | head = p = NULL; 17 | cnt = 0; 18 | memset(node, '\0', sizeof(node)); 19 | } 20 | 21 | void insert(BST* &head, int x){ 22 | if(head == NULL){ 23 | node[cnt].key = x; 24 | node[cnt].parent = p; 25 | head = &node[cnt++]; 26 | return; 27 | } 28 | p = head; 29 | if(head->key > x) 30 | insert(head->lchild, x); 31 | else 32 | insert(head->rchild, x); 33 | } 34 | 35 | void inorderTraver(BST *head){ 36 | if(head == NULL) return; 37 | inorderTraver(head->lchild); 38 | cout<key<<" "; 39 | inorderTraver(head->rchild); 40 | } 41 | 42 | BST* search(BST *head, int x){ 43 | if(head == NULL) return NULL; 44 | if(head->key == x) return head; 45 | else if(head->key > x) 46 | search(head->lchild, x); 47 | else 48 | search(head->rchild, x); 49 | } 50 | 51 | BST* minimum(BST *head){ 52 | if(head == NULL) return NULL; 53 | while(head->lchild != NULL) 54 | head = head->lchild; 55 | return head; 56 | } 57 | 58 | BST* maximum(BST *head){ 59 | if(head == NULL) return NULL; 60 | while(head->rchild != NULL) 61 | head = head->rchild; 62 | return head; 63 | } 64 | 65 | BST* successor(BST *head){ 66 | if(head->rchild != NULL) 67 | return minimum(head->rchild); 68 | BST *y = head->parent; 69 | while(y!=NULL && y->rchild==head){ 70 | head = y; 71 | y = y->parent; 72 | } 73 | return y; 74 | } 75 | 76 | BST* predecessor(BST *head){ 77 | if(head->lchild != NULL) 78 | return maximum(head->lchild); 79 | BST *y = head->parent; 80 | while(y!=NULL && y->lchild==head){ 81 | head = y; 82 | y = y->parent; 83 | } 84 | return y; 85 | } 86 | 87 | void delet(BST *z){ 88 | if(z->lchild==NULL && z->rchild==NULL){ 89 | if(z==head) head = NULL; 90 | else if(z->parent->lchild == z) 91 | z->parent->lchild = NULL; 92 | else 93 | z->parent->rchild = NULL; 94 | } 95 | 96 | else if(z->lchild==NULL || z->rchild==NULL){ 97 | if(z==head){ 98 | if(z->lchild) head = z->lchild; 99 | else head = z->rchild; 100 | head->parent = NULL; 101 | } 102 | else{ 103 | if(z->parent->lchild==z && z->lchild){ 104 | z->parent->lchild = z->lchild; 105 | z->lchild->parent = z->parent; 106 | } 107 | else if(z->parent->lchild==z && z->rchild){ 108 | z->parent->lchild = z->rchild; 109 | z->rchild->parent = z->parent; 110 | } 111 | else if(z->parent->rchild==z && z->lchild){ 112 | z->parent->rchild = z->lchild; 113 | z->lchild->parent = z->parent; 114 | } 115 | else{ 116 | z->parent->rchild = z->rchild; 117 | z->rchild->parent = z->parent; 118 | } 119 | } 120 | } 121 | 122 | else{ 123 | BST *s = predecessor(z); 124 | z->key = s->key; 125 | if(s->parent == z) 126 | s->parent->lchild = s->lchild; 127 | else 128 | s->parent->rchild = s->lchild; 129 | if(s->lchild) 130 | s->lchild->parent = s->parent; 131 | } 132 | } 133 | int main(){ 134 | freopen("BST.in", "r", stdin); 135 | init(); 136 | int x; 137 | while(cin>>x) 138 | insert(head, x); 139 | inorderTraver(head); 140 | cout<key<key< 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | /** 13 | * @brief Finds the k-th number of type (3^a)*(5^b)*(7^c) using brute force. 14 | * @note Complexity: O(k²) in time, O(k) in space. 15 | */ 16 | uint64_t find_number_1(const size_t k) 17 | { 18 | std::vector numbers = {3, 5, 7}; 19 | 20 | while (numbers.size() < k + 1) 21 | { 22 | uint64_t smallest = std::numeric_limits::max(); 23 | 24 | /* 25 | * multiply each number computed so far by 3, 5 and 7; each 26 | * resulting value which is larger than numbers.back() is a 27 | * candidate for the next number in the sequence, and the 28 | * actual next is the smallest one among all candidates 29 | */ 30 | for (const uint64_t num : numbers) 31 | { 32 | for (const uint64_t x : {3, 5, 7}) 33 | { 34 | if (numbers.back() < num * x) 35 | { 36 | smallest = std::min(smallest, num * x); 37 | } 38 | } 39 | } 40 | 41 | numbers.push_back(smallest); 42 | } 43 | 44 | return numbers[k]; 45 | } 46 | 47 | /** 48 | * @brief Finds the k-th number of type (3^a)*(5^b)*(7^c) using three queues, 49 | * each one containing numbers which must still be multiplied by 3, 5 50 | * and 7 respectively at each iteration. 51 | * @note Complexity: O(k) in both time and space. 52 | */ 53 | uint64_t find_number_2(size_t k) 54 | { 55 | std::deque q3 = {uint64_t(1)}; 56 | std::deque q5 = {uint64_t(1)}; 57 | std::deque q7 = {uint64_t(1)}; 58 | 59 | uint64_t next = uint64_t(1); 60 | 61 | ++k; 62 | 63 | while (k > 0) 64 | { 65 | /* 66 | * compute the next candidates of each queue; if none of the 67 | * candidates produce a number large than next, just iterate 68 | * again (but pop the queue whose candidate was the best one), 69 | * otherwise add the winning candidate to all queues 70 | */ 71 | uint64_t next3 = uint64_t(3) * q3.front(); 72 | uint64_t next5 = uint64_t(5) * q5.front(); 73 | uint64_t next7 = uint64_t(7) * q7.front(); 74 | 75 | /* if next3 is the smallest candidate */ 76 | if (next3 <= next5 && next3 <= next7) 77 | { 78 | q3.pop_front(); 79 | if (next3 <= next) 80 | { 81 | continue; 82 | } 83 | next = next3; 84 | } 85 | /* if next5 is the smallest candidate */ 86 | else if (next5 <= next3 && next5 <= next7) 87 | { 88 | q5.pop_front(); 89 | if (next5 <= next) 90 | { 91 | continue; 92 | } 93 | next = next5; 94 | } 95 | /* if next7 is the smallest candidate */ 96 | else 97 | { 98 | q7.pop_front(); 99 | if (next7 <= next) 100 | { 101 | continue; 102 | } 103 | next = next7; 104 | } 105 | 106 | q3.push_back(next); 107 | q5.push_back(next); 108 | q7.push_back(next); 109 | 110 | --k; 111 | } 112 | 113 | return next; 114 | } 115 | 116 | /** 117 | * @brief Returns true if n is an integer whose prime factors are only 3, 5 118 | * and 7, false otherwise. 119 | * @note Complexity: O(log(n)) in time, O(1) in space. 120 | */ 121 | bool is_valid(uint64_t n) 122 | { 123 | if (n < 3) 124 | { 125 | return false; 126 | } 127 | 128 | while (n != 1) 129 | { 130 | uint64_t old_n = n; 131 | 132 | n = (n % 3 == 0) ? n / 3 : n; 133 | n = (n % 5 == 0) ? n / 5 : n; 134 | n = (n % 7 == 0) ? n / 7 : n; 135 | 136 | if (n == old_n) 137 | { 138 | return false; 139 | } 140 | } 141 | 142 | return true; 143 | } 144 | 145 | int main() 146 | { 147 | for (size_t k = 0; k <= 100; ++k) 148 | { 149 | uint64_t n1 = find_number_1(k); 150 | uint64_t n2 = find_number_2(k); 151 | 152 | assert(n1 == n2); 153 | assert(is_valid(n1)); 154 | } 155 | 156 | std::cout << "passed all tests" << std::endl; 157 | } 158 | -------------------------------------------------------------------------------- /Solutions/Chapter 20 Hard/20.6.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * TASK: Given a very large array containing n integers, determine its m largest 3 | * values. Typical values of n and m are 1 billion and 1 million 4 | * respectively. 5 | */ 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | /** 13 | * @brief Returns the m largest elements of an array using quick-select. 14 | * @note Complexity: O(m) in time (on average), O(n) in space, where n is the 15 | * number of elements in the array. 16 | */ 17 | std::vector get_m_largest_1(std::vector values, const size_t m) 18 | { 19 | assert(m <= values.size()); 20 | 21 | static std::random_device device; 22 | static std::mt19937 generator(device()); 23 | 24 | auto first = values.begin(); 25 | auto last = values.end(); 26 | 27 | /* number of largest elements we still need to find */ 28 | size_t missing = m; 29 | 30 | while (true) 31 | { 32 | size_t k = std::distance(first, last); 33 | 34 | std::uniform_int_distribution distribution(0, k - 1); 35 | 36 | /* randomly select a pivot */ 37 | auto pivot = first + distribution(generator); 38 | 39 | std::swap(*first, *pivot); 40 | 41 | auto compare = [first](const int x) { return x < *first; }; 42 | 43 | /* 44 | * partition [first+1,last): the left half will contain values 45 | * which are < pivot, the right half will contain values which 46 | * are >= pivot 47 | */ 48 | auto middle = std::partition(first + 1, last, compare) - 1; 49 | 50 | /* 51 | * make [first,middle) contain values which are < pivot and 52 | * [middle,last) contain values which are >= pivot 53 | */ 54 | if (middle != first) 55 | { 56 | std::swap(*first, *middle); 57 | } 58 | 59 | /* 60 | * since all values in [middle,last) are larger than the 61 | * values in [first,middle), the d values in [middle,last) 62 | * are the d largest values in [first,last) 63 | */ 64 | size_t d = std::distance(middle, last); 65 | 66 | if (d == missing) 67 | { 68 | break; 69 | } 70 | else if (d < missing) 71 | { 72 | last = middle; 73 | missing -= d; 74 | } 75 | else /* d > missing */ 76 | { 77 | first = middle + 1; 78 | } 79 | } 80 | 81 | return {values.end() - m, values.end()}; 82 | } 83 | 84 | /** 85 | * @brief Returns the m largest elements of an array using a min-heap. 86 | * @note Complexity: O(n*log(m)) in time, O(m) in space, where n is the number 87 | * of elements in the array. 88 | */ 89 | std::vector get_m_largest_2(const std::vector& values, const size_t m) 90 | { 91 | assert(m <= values.size()); 92 | 93 | auto heap_compare = [](const int a, const int b) { return a > b; }; 94 | 95 | std::vector m_largest(values.begin(), values.begin() + m); 96 | 97 | /* turn the first m values into a min-heap in O(m) time */ 98 | std::make_heap(m_largest.begin(), m_largest.end(), heap_compare); 99 | 100 | for (size_t i = m; i < values.size(); ++i) 101 | { 102 | /* push values[i] into the heap; heap size becomes m+1 */ 103 | m_largest.push_back(values[i]); 104 | std::push_heap(m_largest.begin(), m_largest.end(), heap_compare); 105 | 106 | /* pop the smallest value from the heap; heap size becomes m */ 107 | std::pop_heap(m_largest.begin(), m_largest.end(), heap_compare); 108 | m_largest.pop_back(); 109 | } 110 | 111 | return m_largest; 112 | } 113 | 114 | /** 115 | * @brief Returns the m largest elements of an array by sorting it first. 116 | * @note Complexity: O(n*log(n)) in time (on average), O(n) in space, where n 117 | * is the number of elements in the array. 118 | */ 119 | std::vector get_m_largest_3(std::vector values, const size_t m) 120 | { 121 | assert(m <= values.size()); 122 | 123 | std::sort(values.begin(), values.end()); 124 | 125 | return {values.end() - m, values.end()}; 126 | } 127 | 128 | int main() 129 | { 130 | std::random_device device; 131 | std::mt19937 generator(device()); 132 | 133 | std::uniform_int_distribution distribution(-1000, 1000); 134 | 135 | for (size_t n = 0; n <= 50; ++n) 136 | { 137 | for (int i = 0; i < 100; ++i) 138 | { 139 | std::vector values; 140 | 141 | while (values.size() < n) 142 | { 143 | values.push_back(distribution(generator)); 144 | } 145 | 146 | for (size_t m = 1; m <= n; ++m) 147 | { 148 | std::vector largest1 = get_m_largest_1(values, m); 149 | std::vector largest2 = get_m_largest_2(values, m); 150 | std::vector largest3 = get_m_largest_3(values, m); 151 | 152 | std::sort(largest1.begin(), largest1.end()); 153 | std::sort(largest2.begin(), largest2.end()); 154 | 155 | assert(largest1 == largest2); 156 | assert(largest2 == largest3); 157 | } 158 | } 159 | 160 | std::cout << "passed random tests for arrays of size " << n 161 | << std::endl; 162 | } 163 | 164 | return EXIT_SUCCESS; 165 | } 166 | -------------------------------------------------------------------------------- /Solutions/Chapter 10 Mathematical/10.6.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * TASK: Given a set of n distinct points on a plane, determine the line which 3 | * is tangent to the largest number of points. 4 | * 5 | * NOTE: The solution to this problem is not, in general, unique. 6 | */ 7 | 8 | #include 9 | #include 10 | #include 11 | #include "line.h" 12 | 13 | /** 14 | * @brief Returns a vector with all lines which connect each pair of points 15 | * on an array with n distinct points. 16 | * @note Complexity: O(n²) in both time and space since there are n*(n-1)/2 17 | * possible distinct pairs of points. 18 | */ 19 | std::vector build_all_lines(const std::vector& points) 20 | { 21 | std::vector lines; 22 | 23 | for (size_t i = 0; i < points.size(); ++i) 24 | { 25 | for (size_t j = i + 1; j < points.size(); ++j) 26 | { 27 | lines.push_back(line(points[i], points[j])); 28 | } 29 | } 30 | 31 | return lines; 32 | } 33 | 34 | /** 35 | * @brief Determines the line which crosses the largest number of points using 36 | * brute-force (build all possible lines and then determine which one 37 | * of them crosses the largest number of points by mere counting). 38 | * @note Complexity: O(n³) in time, O(n²) in space, where n is the number of 39 | * points. 40 | */ 41 | line line_crosses_most_points_1(const std::vector& points) 42 | { 43 | assert(points.size() >= 2); 44 | 45 | /* compute all lines passing over each distinct pair of points */ 46 | std::vector lines = build_all_lines(points); 47 | 48 | /* determine which line crosses the largest number of points */ 49 | size_t best_line = 0; 50 | size_t max_crossed = 0; 51 | 52 | for (size_t i = 0; i < lines.size(); ++i) 53 | { 54 | /* number of points crossed by line i */ 55 | size_t num_crossed_i = 0; 56 | 57 | for (const point& p : points) 58 | { 59 | if (lines[i].crosses(p) == true) 60 | { 61 | ++num_crossed_i; 62 | } 63 | } 64 | 65 | if (num_crossed_i > max_crossed) 66 | { 67 | max_crossed = num_crossed_i; 68 | best_line = i; 69 | } 70 | } 71 | 72 | return lines[best_line]; 73 | } 74 | 75 | /** 76 | * @brief Comparison function which orders lines by x-intercept values, then by 77 | * y-intercept values and finally by the sines of the angles they make 78 | * with the positive x axis. 79 | * @note Complexity: O(1) in both time and space. 80 | */ 81 | bool line_compare(const line& r, const line& s) 82 | { 83 | double rx = r.x_intercept(); 84 | double sx = s.x_intercept(); 85 | 86 | /* if r and s have the same x intercept values */ 87 | if (std::abs(rx - sx) < epsilon) 88 | { 89 | double ry = r.y_intercept(); 90 | double sy = s.y_intercept(); 91 | 92 | /* if r and s have the same y intercept values */ 93 | if (std::abs(ry - sy) < epsilon) 94 | { 95 | return r.sine() < s.sine(); 96 | } 97 | 98 | return ry < sy; 99 | } 100 | 101 | return rx < sx; 102 | } 103 | 104 | /** 105 | * @brief Determines the line which crosses the largest number of points using 106 | * sorting (build all possible lines, sort them and then determine which 107 | * one of them occurs the most in the sorted array of lines). 108 | * @note Complexity: O(n²*log(n)) in time, O(n²) in space. 109 | */ 110 | line line_crosses_most_points_2(const std::vector& points) 111 | { 112 | assert(points.size() >= 2); 113 | 114 | /* compute all lines passing over each distinct pair of points */ 115 | std::vector lines = build_all_lines(points); 116 | 117 | /* 118 | * sort the lines array using line_compare(); this will group identical 119 | * lines together and runs in O(n²*log(n²)) = O(n²*log(n)) time 120 | */ 121 | std::sort(lines.begin(), lines.end(), line_compare); 122 | 123 | /* 124 | * determine which line appears most in the sorted array; by doing this, 125 | * we end up getting the line which crosses the largest number of points 126 | * because if a line crosses m points, there will be m*(m-1)/2 identical 127 | * lines in the lines array, so the line which crosses the largest number 128 | * of points will be the one which appears most in the array 129 | */ 130 | size_t best_line = 0; 131 | size_t max_count = 1; 132 | 133 | size_t i = 0; 134 | 135 | while (i < lines.size()) 136 | { 137 | size_t j = i + 1; 138 | size_t count_equal_i = 1; 139 | 140 | /* loop as long as we keep on finding identical lines */ 141 | while (j < lines.size() && lines[i] == lines[j]) 142 | { 143 | ++count_equal_i; 144 | ++j; 145 | } 146 | 147 | if (count_equal_i > max_count) 148 | { 149 | max_count = count_equal_i; 150 | best_line = i; 151 | } 152 | 153 | i = j; 154 | } 155 | 156 | return lines[best_line]; 157 | } 158 | 159 | /** 160 | * @brief Returns an array with n distinct random points with coordinates (i,j), 161 | * where i and j are integer values in [0,9]. 162 | * @note This method works only for n <= 100, otherwise it will never finish. 163 | */ 164 | std::vector random_points(const size_t n) 165 | { 166 | assert(n <= 100); 167 | 168 | static std::random_device device; 169 | static std::mt19937 generator(device()); 170 | 171 | std::uniform_int_distribution distribution(0, 9); 172 | 173 | std::vector points; 174 | 175 | while (points.size() < n) 176 | { 177 | double x = static_cast(distribution(generator)); 178 | double y = static_cast(distribution(generator)); 179 | 180 | point p{x, y}; 181 | 182 | /* all points in the array must be distinct */ 183 | if (std::find(points.begin(), points.end(), p) == points.end()) 184 | { 185 | points.push_back({x, y}); 186 | } 187 | } 188 | 189 | return points; 190 | } 191 | 192 | int main() 193 | { 194 | for (size_t n = 2; n <= 20; ++n) 195 | { 196 | for (int i = 0; i < 1000; ++i) 197 | { 198 | std::vector points = random_points(n); 199 | 200 | line r1 = line_crosses_most_points_1(points); 201 | line r2 = line_crosses_most_points_2(points); 202 | 203 | size_t crossed_1 = 0; 204 | size_t crossed_2 = 0; 205 | 206 | for (const point& p : points) 207 | { 208 | crossed_1 += r1.crosses(p); 209 | crossed_2 += r2.crosses(p); 210 | } 211 | 212 | assert(crossed_1 == crossed_2); 213 | } 214 | 215 | std::cout << "passed random tests for point sets of size " << n 216 | << std::endl; 217 | } 218 | 219 | return EXIT_SUCCESS; 220 | } 221 | -------------------------------------------------------------------------------- /Solutions/Chapter 20 Hard/20.10.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * TASK: You are given a dictionary and a pair of words with equal lengths. 3 | * Determine a "path of words" taking the first word into the second one 4 | * such that at each step, only one character is changed and the resulting 5 | * word is still part of the dictionary. As an example, for input words 6 | * "cat" and "bit", a possible path is: cat -> bat -> bit (assuming that 7 | * all these words are in the dictionary). 8 | */ 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | using dictionary = std::unordered_set; 21 | using word_array = std::vector; 22 | 23 | /** 24 | * @brief Returns true if two words word1 and word2 have the same length and 25 | * differ by exactly one character, false otherwise. 26 | * @note Complexity: O(d) in time, O(1) in space, where d is the length of the 27 | * words (if not equal, the method runs in O(1) time). 28 | */ 29 | bool is_distance_one(const std::string& word1, const std::string& word2) 30 | { 31 | if (word1.size() != word2.size()) 32 | { 33 | return false; 34 | } 35 | 36 | size_t count = 0; 37 | 38 | for (size_t i = 0; i < word1.size(); ++i) 39 | { 40 | count += (word1[i] != word2[i]); 41 | } 42 | 43 | return (count == 1); 44 | } 45 | 46 | /** 47 | * @brief Returns an array containing all words in a given dictionary with 48 | * distance one from a given word. 49 | * @note Complexity: O(d) in both time and space, where d is the word length. 50 | */ 51 | word_array get_distance_one_words(std::string word, const dictionary& dict) 52 | { 53 | word_array dist_one; 54 | 55 | /* 56 | * replace each character in word with every character in [a-zA-Z], 57 | * then check if the resulting string is a word in the dictionary 58 | * (this implementation is not portable, but works correctly for ASCII 59 | * strings) 60 | */ 61 | for (char& current : word) 62 | { 63 | char original = current; 64 | 65 | for (char c = 'a'; c <= 'z'; ++c) 66 | { 67 | current = c; 68 | 69 | if (dict.find(word) != dict.end()) 70 | { 71 | dist_one.push_back(word); 72 | } 73 | } 74 | 75 | for (char c = 'A'; c <= 'Z'; ++c) 76 | { 77 | current = c; 78 | 79 | if (dict.find(word) != dict.end()) 80 | { 81 | dist_one.push_back(word); 82 | } 83 | } 84 | 85 | current = original; 86 | } 87 | 88 | return dist_one; 89 | } 90 | 91 | /** 92 | * @brief Determines a path between word1 and word2 which defines a series of 93 | * steps to transform word1 into word2 such that each step involves only 94 | * one character change and generates a word which is also in the 95 | * dictionary (this is merely an implementation of breadth-first search). 96 | * @note Complexity: O(n*d) in both time and space, where n is the number of 97 | * words in the dictionary and d is the length of its longest word. 98 | */ 99 | word_array get_path_between_words(const std::string& word1, 100 | const std::string& word2, 101 | const dictionary& dict) 102 | { 103 | /* 104 | * return an empty path if one of these conditions are satisfied: 105 | * 106 | * 1) word1 and word2 are equal 107 | * 2) word1 and word2 have different lengths 108 | * 3) word1 is not in the dictionary 109 | * 4) word2 is not in the dictionary 110 | */ 111 | if (word1 == word2 || word1.size() != word2.size() || 112 | dict.find(word1) == dict.end() || dict.find(word2) == dict.end()) 113 | { 114 | return {}; 115 | } 116 | 117 | std::queue Q; 118 | std::unordered_set explored; 119 | std::unordered_map previous; 120 | 121 | Q.push(word1); 122 | explored.insert(word1); 123 | 124 | while (Q.empty() == false) 125 | { 126 | std::string current = Q.front(); 127 | Q.pop(); 128 | 129 | word_array neighbors = get_distance_one_words(current, dict); 130 | 131 | for (const std::string& neighbor : neighbors) 132 | { 133 | /* 134 | * if we reached the target (word2), build the path in 135 | * reverse order from word2 to word1 and then return it 136 | * in correct order 137 | */ 138 | if (neighbor == word2) 139 | { 140 | word_array path; 141 | 142 | path.push_back(neighbor); 143 | 144 | while (current != word1) 145 | { 146 | path.push_back(current); 147 | current = previous[current]; 148 | } 149 | 150 | path.push_back(word1); 151 | 152 | /* correct the path direction: word1 -> word2 */ 153 | std::reverse(path.begin(), path.end()); 154 | 155 | return path; 156 | } 157 | 158 | /* if neighbor has not been explored yet */ 159 | if (explored.find(neighbor) == explored.end()) 160 | { 161 | Q.push(neighbor); 162 | explored.insert(neighbor); 163 | 164 | previous[neighbor] = current; 165 | } 166 | } 167 | } 168 | 169 | /* if we reach this point, we cannot transform word1 into word2 */ 170 | return {}; 171 | } 172 | 173 | int main(int argc, char** argv) 174 | { 175 | /* 176 | * usage: ./solve 177 | * example: ./solve dictionary.txt cat bit 178 | */ 179 | 180 | assert(argc > 3); 181 | 182 | /* make sure the dictionary file is valid */ 183 | std::ifstream dict_file(argv[1]); 184 | assert(dict_file.is_open() == true); 185 | 186 | std::string word1(argv[2]); 187 | std::string word2(argv[3]); 188 | 189 | dictionary dict; 190 | 191 | /* read all words from the dictionary file */ 192 | std::string dict_word; 193 | while (dict_file >> dict_word) 194 | { 195 | dict.insert(dict_word); 196 | } 197 | 198 | word_array path = get_path_between_words(word1, word2, dict); 199 | 200 | if (path.empty() == false) 201 | { 202 | std::cout << path.front(); 203 | 204 | for (size_t i = 1; i < path.size(); ++i) 205 | { 206 | std::cout << " -> " << path[i]; 207 | 208 | assert(is_distance_one(path[i - 1], path[i]) == true); 209 | } 210 | 211 | std::cout << std::endl; 212 | } 213 | else if (word1 == word2) 214 | { 215 | std::cout << "initial and target words are equal" << std::endl; 216 | } 217 | else 218 | { 219 | std::cout << "no path found between '" << word1 << "' and '" << word2 220 | << "'" << std::endl; 221 | } 222 | 223 | return EXIT_SUCCESS; 224 | } 225 | -------------------------------------------------------------------------------- /Solutions/Chapter 20 Hard/20.13.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * TASK: Your are given a set of words (a dictionary). Determine the largest 3 | * rectangle of characters such that every row and every column forms a 4 | * word in the given dictionary (read from left to right and top to 5 | * bottom respectively). 6 | * 7 | * NOTE: The solution below works for any dictionary whose words are encoded in 8 | * either ASCII or ISO-8859-15; this should cover languages from the 9 | * Americas, Western Europe, Oceania and much of Africa (see 10 | * https://en.wikipedia.org/wiki/ISO/IEC_8859-1 for more on this topic). 11 | */ 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | /* a bitmask which indicates valid/invalid characters */ 23 | using char_bitset = std::bitset<256>; 24 | 25 | /* a set of (distinct) words */ 26 | using word_set = std::unordered_set; 27 | 28 | /** @brief A dictionary class for storing words and extra useful information. */ 29 | class dictionary 30 | { 31 | public: 32 | /** 33 | * @brief Inserts a word into the dictionary. 34 | * @note Complexity: O(n²) in both time and space, where n is the length 35 | * of the word. 36 | */ 37 | void insert(const std::string& word) 38 | { 39 | size_t n = word.size(); 40 | 41 | words_.insert(word); 42 | largest_word_length_ = std::max(largest_word_length_, n); 43 | 44 | if (next_chars_.size() <= n) 45 | { 46 | next_chars_.resize(n + 1); 47 | } 48 | 49 | /* 50 | * for each prefix word[0..i), with i in [0,n), add word[i] as a 51 | * "valid next character" for word[0..i) whenever we are trying 52 | * to form a word of length n 53 | */ 54 | for (size_t i = 0; i < n; ++i) 55 | { 56 | uint8_t char_bit = static_cast(word[i]); 57 | next_chars_[n][word.substr(0, i)][char_bit] = true; 58 | } 59 | } 60 | 61 | /** 62 | * @brief Given a word prefix, returns a bitmask indicating what are the 63 | * possible next characters if the prefix is assumed to be part 64 | * of a word of length n present in the dictionary. 65 | * @note Complexity: O(n) in time, O(1) in space. 66 | */ 67 | char_bitset valid_next_chars(const std::string& prefix, 68 | const size_t n) const 69 | { 70 | auto it = next_chars_[n].find(prefix); 71 | 72 | if (it == next_chars_[n].end()) 73 | { 74 | return {}; 75 | } 76 | 77 | return it->second; 78 | } 79 | 80 | /** 81 | * @brief Returns true if a given word is in the dictionary, false 82 | * otherwise. 83 | * @note Complexity: O(n) in time, O(1) in space, where n is the length 84 | * of the input word. 85 | */ 86 | bool find(const std::string& word) const 87 | { 88 | return (words_.find(word) != words_.end()); 89 | } 90 | 91 | /** 92 | * @brief Returns the length of the longest word in the dictionary. 93 | * @note Complexity: O(1) in both time and space. 94 | */ 95 | size_t largest_word_length() const 96 | { 97 | return largest_word_length_; 98 | } 99 | 100 | private: 101 | /* words in the dictionary */ 102 | word_set words_; 103 | 104 | /* length of the longest word in the dictionary */ 105 | size_t largest_word_length_ = 0; 106 | 107 | /* valid next characters given the target word length and a prefix */ 108 | std::vector > next_chars_; 109 | }; 110 | 111 | /** 112 | * @brief A "rectangle of characters" such that each undefined cell stores a 113 | * '\0' character; each cell is identified by a pair of indices (i,j), 114 | * with (0,0) being the index of the top-left rectangle cell. 115 | */ 116 | class rectangle 117 | { 118 | public: 119 | rectangle(const size_t width = 0, const size_t height = 0) 120 | : width_(width), height_(height), chars_(width * height, '\0') 121 | { 122 | /* nothing needs to be done here */ 123 | } 124 | 125 | /** 126 | * @brief Returns a reference to the character at the i-th row and j-th 127 | * column (both are zero indexed). 128 | * @note Complexity: O(1) in both time and space. 129 | */ 130 | char& operator()(const size_t i, const size_t j) 131 | { 132 | assert(i < height() && j < width()); 133 | 134 | return chars_[i * width() + j]; 135 | } 136 | 137 | /** 138 | * @brief Returns a copy of the character at the i-th row and j-th 139 | * column (both are zero indexed). 140 | * @note Complexity: O(1) in both time and space. 141 | */ 142 | char operator()(const size_t i, const size_t j) const 143 | { 144 | assert(i < height() && j < width()); 145 | 146 | return chars_[i * width() + j]; 147 | } 148 | 149 | /** 150 | * @brief Marks the cell at the i-th row and j-th column as "undefined" 151 | * (i.e., sets it to '\0'). 152 | * @note Complexity: O(1) in both time and space. 153 | */ 154 | void reset(const size_t i, const size_t j) 155 | { 156 | (*this)(i, j) = '\0'; 157 | } 158 | 159 | /** 160 | * @brief Returns the leftmost contiguous sequence of defined characters 161 | * at the i-th row. 162 | * @note Complexity: O(width) in both time and space. 163 | */ 164 | std::string subrow(const size_t i) const 165 | { 166 | assert(i < height()); 167 | 168 | std::string result; 169 | 170 | for (size_t j = 0; j < width() && (*this)(i, j) != '\0'; ++j) 171 | { 172 | result.push_back((*this)(i, j)); 173 | } 174 | 175 | return result; 176 | } 177 | 178 | /** 179 | * @brief Returns the topmost contiguous sequence of defined characters 180 | * at the j-th column. 181 | * @note Complexity: O(height) in both time and space. 182 | */ 183 | std::string subcolumn(const size_t j) const 184 | { 185 | assert(j < width()); 186 | 187 | std::string result; 188 | 189 | for (size_t i = 0; i < height() && (*this)(i, j) != '\0'; ++i) 190 | { 191 | result.push_back((*this)(i, j)); 192 | } 193 | 194 | return result; 195 | } 196 | 197 | /** 198 | * @brief Returns the width of the rectangle. 199 | * @note Complexity: O(1) in both time and space. 200 | */ 201 | size_t width() const 202 | { 203 | return width_; 204 | } 205 | 206 | /** 207 | * @brief Returns the height of the rectangle. 208 | * @note Complexity: O(1) in both time and space. 209 | */ 210 | size_t height() const 211 | { 212 | return height_; 213 | } 214 | 215 | /** 216 | * @brief Returns true if the rectangle has area zero, false otherwise. 217 | * @note Complexity: O(1) in both time and space. 218 | */ 219 | bool empty() const 220 | { 221 | return (width() == 0 || height() == 0); 222 | } 223 | 224 | /** 225 | * @brief Prints the rectangle on a given output stream. 226 | * @note Complexity: O(width*height) in time, O(1) in space. 227 | */ 228 | std::ostream& print(std::ostream& os = std::cout) const 229 | { 230 | for (size_t i = 0; i < height(); ++i) 231 | { 232 | for (size_t j = 0; j < width(); ++j) 233 | { 234 | os << (*this)(i, j); 235 | } 236 | 237 | os << "\n"; 238 | } 239 | 240 | return os; 241 | } 242 | 243 | private: 244 | const size_t width_; 245 | const size_t height_; 246 | std::vector chars_; 247 | }; 248 | 249 | /** 250 | * @brief Recursive step on the backtracking implementation; at each call, all 251 | * cells rect(0:i, 0:j) except for rect(i,j) are assumed to be already 252 | * defined; the rectangle is constructed first from left to right 253 | * starting at the top-left cell, then top to bottom, so the topmost row 254 | * is built first, then the second topmost row and so on until we reach 255 | * the bottom-right cell. 256 | * @return true if a valid rectangle could be built, false otherwise. 257 | */ 258 | bool build_rectangle(rectangle& rect, 259 | const dictionary& dict, 260 | const size_t i = 0, 261 | const size_t j = 0) 262 | { 263 | std::string subrow = rect.subrow(i); 264 | std::string subcol = rect.subcolumn(j); 265 | 266 | /* subrow must be equal to rect(i, 0:j-1) */ 267 | assert(subrow.size() == j); 268 | 269 | /* subcol must be equal to rect(0:i-1, j) */ 270 | assert(subcol.size() == i); 271 | 272 | /* 273 | * considering that the i-th row and the j-th column must form words in 274 | * the dictionary, determine which characters can be placed at rect(i,j) 275 | * such that it will still be possible for the i-th row and the j-th 276 | * column to form words of lengths rect.width() and rect.height() 277 | * respectively when they are both fully built (i.e., all cells defined) 278 | */ 279 | char_bitset valid_next_char = dict.valid_next_chars(subrow, rect.width()) & 280 | dict.valid_next_chars(subcol, rect.height()); 281 | 282 | /* the character '\0' may not be part of a word */ 283 | for (int c = 1; c < 256; ++c) 284 | { 285 | if (valid_next_char[c] == true) 286 | { 287 | rect(i, j) = static_cast(c); 288 | 289 | if (j + 1 < rect.width()) 290 | { 291 | if (build_rectangle(rect, dict, i, j + 1) == true) 292 | { 293 | return true; 294 | } 295 | } 296 | else if (i + 1 < rect.height()) /* j+1 == rect.width() */ 297 | { 298 | if (build_rectangle(rect, dict, i + 1, 0) == true) 299 | { 300 | return true; 301 | } 302 | } 303 | else /* we are at the right-bottom rectangle cell */ 304 | { 305 | return true; 306 | } 307 | 308 | rect.reset(i, j); 309 | } 310 | } 311 | 312 | return false; 313 | } 314 | 315 | /** 316 | * @brief Builds the largest rectangle of characters such that each of its rows 317 | * and columns forms a word in a given dictionary. 318 | * @note Complexity: O(N²*d^N²) in time, O(N²) in space, where N is the length 319 | * of the longest word in the dictionary and d is the number of distinct 320 | * characters from which the dictionary words are constructed (notice that 321 | * d cannot exceed 255 in this implementation; also, this runtime 322 | * asymptotic bound is very conservative and a solution will in general be 323 | * obtained in much less time). 324 | */ 325 | rectangle build_largest_word_rectangle(const dictionary& dict) 326 | { 327 | size_t N = dict.largest_word_length(); 328 | 329 | /* 330 | * consider first the rectangles with the maximum possible area N*N, 331 | * then (N*N - 1), then (N*N - 2) and so on; the first valid rectangle 332 | * which is found is the one we are looking for 333 | */ 334 | for (size_t area = N * N; area > 0; --area) 335 | { 336 | for (size_t width = N; width > 0; --width) 337 | { 338 | size_t height = area / width; 339 | 340 | /* 341 | * if width < height, we already considered this 342 | * rectangle (with swapped values of width and height), 343 | * and there is no need to consider even smaller width 344 | * values 345 | */ 346 | if (width < height) 347 | { 348 | break; 349 | } 350 | 351 | /* if no rectangle with the given area/width can exist */ 352 | if (width * height != area) 353 | { 354 | continue; 355 | } 356 | 357 | rectangle rect(width, height); 358 | 359 | if (build_rectangle(rect, dict) == true) 360 | { 361 | return rect; 362 | } 363 | } 364 | } 365 | 366 | /* 367 | * if we reach this point, there is no rectangle which can be formed 368 | * with the words from the input dictionary 369 | */ 370 | return {}; 371 | } 372 | 373 | /** 374 | * @brief Returns true if the rectangle rows and columns form words in the given 375 | * dictionary, false otherwise. 376 | * @note Complexity: O(width*height) in time, O(max(width,height)) in space. 377 | */ 378 | bool is_valid_rectangle(const rectangle& rect, const dictionary& dict) 379 | { 380 | /* check if each row is a valid word in the dictionary */ 381 | for (size_t i = 0; i < rect.height(); ++i) 382 | { 383 | std::string row = rect.subrow(i); 384 | 385 | if (row.size() != rect.width()) 386 | { 387 | return false; 388 | } 389 | 390 | if (dict.find(row) == false) 391 | { 392 | return false; 393 | } 394 | } 395 | 396 | /* check if each column is a valid word in the dictionary */ 397 | for (size_t j = 0; j < rect.width(); ++j) 398 | { 399 | std::string column = rect.subcolumn(j); 400 | 401 | if (column.size() != rect.height()) 402 | { 403 | return false; 404 | } 405 | 406 | if (dict.find(column) == false) 407 | { 408 | return false; 409 | } 410 | } 411 | 412 | return true; 413 | } 414 | 415 | int main(int argc, char** argv) 416 | { 417 | /* 418 | * usage: ./solve 419 | * example: ./solve dictionaries/dictionary-100.txt 420 | */ 421 | 422 | assert(argc > 1); 423 | 424 | /* make sure the dictionary file is valid */ 425 | std::ifstream dict_file(argv[1]); 426 | assert(dict_file.is_open() == true); 427 | 428 | dictionary dict; 429 | 430 | /* read all words from the dictionary file */ 431 | std::string dict_word; 432 | while (dict_file >> dict_word) 433 | { 434 | dict.insert(dict_word); 435 | } 436 | 437 | rectangle rect = build_largest_word_rectangle(dict); 438 | 439 | if (rect.empty() == false) 440 | { 441 | assert(is_valid_rectangle(rect, dict) == true); 442 | 443 | rect.print(); 444 | } 445 | else 446 | { 447 | std::cout << "no rectangle could be built\n"; 448 | } 449 | 450 | return EXIT_SUCCESS; 451 | } 452 | --------------------------------------------------------------------------------