├── 1-1.设计具有getMin()功能的栈.cpp ├── 1-2.两个栈实现队列.cpp ├── 1-3.仅用递归和栈操作实现栈的逆序.cpp ├── 1-5.用栈实现另一个栈的排序.cpp ├── 1-6.用栈来求解汉诺塔问题.cpp ├── 1-7.生成窗口最大值数组.cpp ├── 1-8.构造数组的MaxTree.cpp ├── 1-9.求最大子矩阵的大小.cpp ├── 2-1.打印两个有序链表的公共部分.cpp ├── 2-19.合并两个有序的单链表.cpp ├── 2-2.在单链表删除倒数第n个结点.cpp ├── 2-3.删除链表中间结点和a除以b位置的结点.cpp ├── 2-4.反转单向和双向链表.cpp ├── 2-5.反转部分单链表.cpp ├── 2-6.环形单链表的约瑟夫环问题.cpp └── README.md /1-1.设计具有getMin()功能的栈.cpp: -------------------------------------------------------------------------------- 1 | /*** 2 | 设计一个具有getMin功能的栈 3 | ***/ 4 | 5 | #include 6 | #include 7 | 8 | using namespace std; 9 | 10 | class StackWithMin { 11 | public: 12 | void push( int x ); 13 | void pop(); 14 | int top(); 15 | bool empty(); 16 | int getMin(); 17 | 18 | private: 19 | stack stackData; 20 | stack stackMin; 21 | }; 22 | 23 | void StackWithMin::push( int x ) { 24 | stackData.push( x ); 25 | if( stackMin.empty() ) { 26 | stackMin.push( x ); 27 | } 28 | else { 29 | if( stackMin.top() >= x ) { 30 | stackMin.push( x ); 31 | } 32 | } 33 | } 34 | 35 | void StackWithMin::pop() { 36 | if( stackData.empty() ) { 37 | printf( "the stack is empty!" ); 38 | } 39 | else { 40 | int cur = stackData.top(); 41 | stackData.pop(); 42 | if( cur == stackMin.top() ) { 43 | stackMin.pop(); 44 | } 45 | } 46 | } 47 | 48 | int StackWithMin::getMin() { 49 | if( stackData.empty() ) { 50 | printf( "the stack is empty!" ); 51 | } 52 | else { 53 | return stackMin.top(); 54 | } 55 | } 56 | 57 | int StackWithMin::top() { 58 | if( stackData.empty() ) { 59 | printf( "the stack is empty!" ); 60 | } 61 | else { 62 | return stackData.top(); 63 | } 64 | } 65 | 66 | bool StackWithMin::empty() { 67 | return stackData.empty(); 68 | } 69 | 70 | int main() { 71 | StackWithMin s; 72 | 73 | s.push( 3 ); 74 | s.push( 4 ); 75 | s.push( 5 ); 76 | s.push( 1 ); 77 | s.push( 2 ); 78 | s.push( 1 ); 79 | s.pop(); 80 | s.pop(); 81 | s.pop(); 82 | 83 | printf( "%d\n", s.getMin() ); 84 | 85 | return 0; 86 | } 87 | -------------------------------------------------------------------------------- /1-2.两个栈实现队列.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #define ERROR -10000 5 | 6 | using namespace std; 7 | 8 | class myQueue { 9 | public: 10 | void add( int x ); 11 | int poll(); 12 | int peek(); 13 | private: 14 | stack s1; 15 | stack s2; 16 | }; 17 | 18 | void myQueue::add( int x ) { 19 | s1.push( x ); 20 | } 21 | 22 | int myQueue::poll() { 23 | int res; 24 | res = peek(); 25 | 26 | if( res != ERROR ) { 27 | s2.pop(); 28 | } 29 | 30 | return res; 31 | } 32 | 33 | int myQueue::peek() { 34 | int res; 35 | if( !s2.empty() ) { 36 | res = s2.top(); 37 | } 38 | else { 39 | if( s1.empty() ) { 40 | printf( "the queue is empty!\n" ); 41 | return ERROR; 42 | } 43 | else { 44 | while( !s1.empty() ) { 45 | int cur = s1.top(); 46 | s1.pop(); 47 | s2.push( cur ); 48 | } 49 | res = s2.top(); 50 | } 51 | } 52 | 53 | return res; 54 | } 55 | 56 | int main() { 57 | myQueue q; 58 | q.add( 1 ); 59 | q.add( 2 ); 60 | q.add( 3 ); 61 | printf( "%d\n", q.peek() ); 62 | q.poll(); 63 | printf( "%d\n", q.peek() ); 64 | q.poll(); 65 | q.add( 5 ); 66 | q.add( 6 ); 67 | printf( "%d\n", q.peek() ); 68 | q.poll(); 69 | printf( "%d\n", q.peek() ); 70 | q.poll(); 71 | printf( "%d\n", q.peek() ); 72 | 73 | return 0; 74 | } 75 | -------------------------------------------------------------------------------- /1-3.仅用递归和栈操作实现栈的逆序.cpp: -------------------------------------------------------------------------------- 1 | /*** 2 | 仅用递归函数和栈操作 3 | 实现栈的逆序 4 | ***/ 5 | 6 | #include 7 | #include 8 | 9 | using namespace std; 10 | 11 | int getAndRemoveLastElement( stack &s ) { 12 | int result = s.top(); 13 | s.pop(); 14 | 15 | if( s.empty() ) { 16 | return result; 17 | } 18 | else { 19 | int last = getAndRemoveLastElement( s ); 20 | s.push( result ); 21 | return last; 22 | } 23 | } 24 | 25 | void reverse( stack &s ) { 26 | if( s.empty() ) { 27 | return; 28 | } 29 | else { 30 | int i = getAndRemoveLastElement( s ); 31 | reverse( s ); 32 | s.push( i ); 33 | } 34 | } 35 | 36 | int main() { 37 | stack s; 38 | s.push( 1 ); 39 | s.push( 2 ); 40 | s.push( 3 ); 41 | 42 | reverse( s ); 43 | 44 | while( !s.empty() ) { 45 | printf( "%d\n", s.top() ); 46 | s.pop(); 47 | } 48 | 49 | return 0; 50 | } 51 | -------------------------------------------------------------------------------- /1-5.用栈实现另一个栈的排序.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace std; 5 | 6 | void stackSort( stack &s ) { 7 | stack help; 8 | while( !s.empty() ) { 9 | int cur = s.top(); 10 | s.pop(); 11 | while( !help.empty() && cur > help.top() ) { 12 | int top = help.top(); 13 | help.pop(); 14 | s.push( top ); 15 | } 16 | help.push( cur ); 17 | } 18 | 19 | while( !help.empty() ) { 20 | s.push( help.top() ); 21 | help.pop(); 22 | } 23 | } 24 | 25 | void printStack( stack &s ) { 26 | while( !s.empty() ) { 27 | printf( "%d\n", s.top() ); 28 | s.pop(); 29 | } 30 | } 31 | 32 | int main() { 33 | stack stackData; 34 | 35 | stackData.push( 3 ); 36 | stackData.push( 2 ); 37 | stackData.push( 1 ); 38 | stackData.push( 5 ); 39 | stackData.push( 4 ); 40 | 41 | stackSort( stackData ); 42 | 43 | printStack( stackData ); 44 | 45 | return 0; 46 | } 47 | -------------------------------------------------------------------------------- /1-6.用栈来求解汉诺塔问题.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace std; 5 | 6 | int process( int num, string left, string mid, string right, string from, string to ) { 7 | if( num == 1 ) { 8 | if( from == "mid" || to == "mid" ) { 9 | cout << "move 1 from " + from + " to " + to << endl; 10 | return 1; 11 | } 12 | else { 13 | cout << "move 1 from " + from + " to mid" << endl; 14 | cout << "move 1 from mid to " + to << endl; 15 | return 2; 16 | } 17 | } 18 | if( from == "mid" || to == "mid" ) { 19 | string another = ( from == "left" || to == "left" ) ? "right" : "left"; 20 | int part1 = process( num - 1, left, mid, right, from, another ); 21 | int part2 = 1; 22 | cout << "move "; 23 | cout << num; 24 | cout << " from " + from + " to " + to << endl; 25 | int part3 = process( num - 1, left, mid, right, another, to ); 26 | return part1 + part2 + part3; 27 | } 28 | else { 29 | int part1 = process( num - 1, left, mid, right, from, to ); 30 | int part2 = 1; 31 | cout << "move "; 32 | cout << num; 33 | cout << " from " + from + " to mid" << endl; 34 | int part3 = process( num - 1, left, mid, right, to, from ); 35 | int part4 = 1; 36 | cout << "move "; 37 | cout << num; 38 | cout << " from mid to " + to << endl; 39 | int part5 = process( num - 1, left, mid, right, from, to ); 40 | return part1 + part2 + part3 + part4 + part5; 41 | } 42 | } 43 | 44 | int hanoiProblem1( int num ) { 45 | if( num < 1 ) return 0; 46 | return process( num, "left", "mid", "right", "left", "right" ); 47 | } 48 | 49 | int main() { 50 | int sum = hanoiProblem1( 2 ); 51 | printf( "%d\n", sum ); 52 | 53 | return 0; 54 | } 55 | -------------------------------------------------------------------------------- /1-7.生成窗口最大值数组.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | vector getMaxWindow( vector &v, int w ) { 8 | vector ans; 9 | 10 | if( v.empty() || w < 1 || v.size() < w ) { 11 | return ans; 12 | } 13 | 14 | deque q; 15 | for( int i = 0; i < v.size(); i++ ) { 16 | while( !q.empty() && v[q.back()] <= v[i] ) { 17 | q.pop_back(); 18 | } 19 | q.push_back( i ); 20 | if( q.front() == i - w ) { 21 | q.pop_front(); 22 | } 23 | if( i >= w - 1 ) { 24 | ans.push_back( v[q.front()] ); 25 | } 26 | } 27 | 28 | return ans; 29 | } 30 | 31 | int main() { 32 | vector vec; 33 | vec.push_back( 4 ); 34 | vec.push_back( 3 ); 35 | vec.push_back( 5 ); 36 | vec.push_back( 4 ); 37 | vec.push_back( 3 ); 38 | vec.push_back( 3 ); 39 | vec.push_back( 6 ); 40 | vec.push_back( 7 ); 41 | 42 | vector ans = getMaxWindow( vec, 3 ); 43 | 44 | for( int i = 0; i < ans.size(); i++ ) { 45 | printf( "%d ", ans[i] ); 46 | } 47 | 48 | return 0; 49 | } 50 | -------------------------------------------------------------------------------- /1-8.构造数组的MaxTree.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flx413/Coding-Interview-Guide/c8758294a20e170b97dfc3010797ad9acc155b2d/1-8.构造数组的MaxTree.cpp -------------------------------------------------------------------------------- /1-9.求最大子矩阵的大小.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #define MAX 100 6 | 7 | using namespace std; 8 | 9 | int maxRecFromBottom( int height[], int n ) { 10 | int maxArea = 0; 11 | stack s; 12 | 13 | for( int i = 0; i < n; i++ ) { 14 | while( !s.empty() && height[i] <= height[s.top()] ) { 15 | int j = s.top(); 16 | s.pop(); 17 | int k = s.empty() ? -1 : s.top(); 18 | int curArea = ( i - k - 1 ) * height[j]; 19 | maxArea = max( maxArea, curArea ); 20 | } 21 | s.push( i ); 22 | } 23 | 24 | while( !s.empty() ) { 25 | int j = s.top(); 26 | s.pop(); 27 | int k = s.empty() ? -1 : s.top(); 28 | int curArea = ( n - k - 1 ) * height[j]; 29 | maxArea = max( maxArea, curArea ); 30 | } 31 | 32 | return maxArea; 33 | } 34 | 35 | int maxRecSize( int map[MAX][MAX], int n, int m ) { 36 | int height[MAX]; 37 | int maxArea = 0; 38 | 39 | fill( height, height + m, 0 ); 40 | 41 | for( int i = 0; i < n; i++ ) { 42 | for( int j = 0; j < m; j++ ) { 43 | height[j] = map[i][j] == 0 ? 0 : height[j] + 1; 44 | } 45 | maxArea = max( maxRecFromBottom( height, m ), maxArea ); 46 | } 47 | 48 | return maxArea; 49 | } 50 | 51 | int main() { 52 | int map[MAX][MAX] = { { 1, 0, 1, 1 }, { 1, 1, 1, 1 }, { 1, 1, 1, 0 } }; 53 | 54 | int maxArea = maxRecSize( map, 3, 4 ); 55 | 56 | printf( "%d\n", maxArea); 57 | 58 | return 0; 59 | } 60 | -------------------------------------------------------------------------------- /2-1.打印两个有序链表的公共部分.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flx413/Coding-Interview-Guide/c8758294a20e170b97dfc3010797ad9acc155b2d/2-1.打印两个有序链表的公共部分.cpp -------------------------------------------------------------------------------- /2-19.合并两个有序的单链表.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | struct Node 5 | { 6 | int val; 7 | Node *next; 8 | Node(int v) : val(v) { next = NULL; } 9 | }; 10 | 11 | Node* Merge(Node *head1, Node *head2) 12 | { 13 | if (head1 == NULL) return head2; 14 | if (head2 == NULL) return head1; 15 | 16 | Node *head = NULL; 17 | Node *pre = NULL; 18 | Node *p1 = head1; 19 | Node *p2 = head2; 20 | if (p1->val > p2->val) 21 | { 22 | head = p2; 23 | pre = p2; 24 | p2 = p2->next; 25 | } 26 | else 27 | { 28 | head = p1; 29 | pre = p1; 30 | p1 = p1->next; 31 | } 32 | 33 | while (NULL != p1 && NULL != p2) 34 | { 35 | if (p1->val > p2->val) 36 | { 37 | pre->next = p2; 38 | pre = p2; 39 | p2 = p2->next; 40 | } 41 | else 42 | { 43 | pre->next = p1; 44 | pre = p1; 45 | p1 = p1->next; 46 | } 47 | } 48 | 49 | if (NULL != p1) pre->next = p1; 50 | if (NULL != p2) pre->next = p2; 51 | 52 | return head; 53 | } 54 | 55 | void PrintList(Node *head) 56 | { 57 | Node *p = head; 58 | while (NULL != p) 59 | { 60 | printf("%d ", p->val); 61 | p = p->next; 62 | } 63 | } 64 | int main() { 65 | Node *node1_1 = new Node(1); 66 | Node *node1_2 = new Node(2); 67 | Node *node1_3 = new Node(3); 68 | Node *node1_4 = new Node(4); 69 | Node *node1_5 = new Node(5); 70 | 71 | Node *node2_1 = new Node(0); 72 | Node *node2_2 = new Node(3); 73 | Node *node2_3 = new Node(4); 74 | Node *node2_4 = new Node(7); 75 | Node *node2_5 = new Node(10); 76 | 77 | node1_1->next = node1_2; 78 | node1_2->next = node1_3; 79 | node1_3->next = node1_4; 80 | node1_4->next = node1_5; 81 | 82 | node2_1->next = node2_2; 83 | node2_2->next = node2_3; 84 | node2_3->next = node2_4; 85 | node2_4->next = node2_5; 86 | 87 | Node *head1 = node1_1; 88 | Node *head2 = node2_1; 89 | Node *head = Merge(head1, head2); 90 | PrintList(head); 91 | 92 | return 0; 93 | } -------------------------------------------------------------------------------- /2-2.在单链表删除倒数第n个结点.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flx413/Coding-Interview-Guide/c8758294a20e170b97dfc3010797ad9acc155b2d/2-2.在单链表删除倒数第n个结点.cpp -------------------------------------------------------------------------------- /2-3.删除链表中间结点和a除以b位置的结点.cpp: -------------------------------------------------------------------------------- 1 | typedef struct Node { 2 | int value; 3 | Node* next; 4 | 5 | Node( int data ) { 6 | this.value = data; 7 | } 8 | } Node; 9 | 10 | Node* removeMidNode( Node* head ) { 11 | if( head == NULL || head->next == NULL ) { 12 | return head; 13 | } 14 | if( head->next->next == NULL ) { 15 | return head->next; 16 | } 17 | 18 | Node* pre = head; 19 | Node* cur = head->next->next; 20 | while( cur->next != NULL && cur->next->next != NULL ) { 21 | pre = pre->next; 22 | cur = cur->next->next; 23 | } 24 | Node* mid = pre->next; 25 | pre->next = pre->next->next; 26 | delete mid; 27 | mid = NULL; 28 | 29 | return head; 30 | } 31 | 32 | Node* removeByRatio( Node* head, int a, int b ) { 33 | if( a < 1 || a > b ) return head; 34 | 35 | int len = 0; 36 | Node* cur = head; 37 | while( cur != NULL ) { 38 | len++; 39 | cur = cur->next; 40 | } 41 | 42 | int pos = (int)ceil( ((double)( a * n ) ) / (double)b ); 43 | if( pos == 1 ) { 44 | head = head->next; 45 | } 46 | else if( pos > 1 ) { 47 | cur = head; 48 | while( --pos != 1 ) { 49 | cur = cur->next; 50 | } 51 | cur->next = cur->next->next; 52 | } 53 | 54 | return head; 55 | } 56 | -------------------------------------------------------------------------------- /2-4.反转单向和双向链表.cpp: -------------------------------------------------------------------------------- 1 | typedef struct Node { 2 | int value; 3 | Node* next; 4 | 5 | Node( int data ) { 6 | this.value = data; 7 | } 8 | } Node; 9 | 10 | Node* reverseList( Node* head ) { 11 | Node* pre = NULL; 12 | Node* next = NULL; 13 | while( head != NULL ) { 14 | next = head->next; 15 | head->next = pre; 16 | pre = head; 17 | head = next; 18 | } 19 | 20 | return pre; 21 | } 22 | 23 | 24 | 25 | typedef struct DoubleNode { 26 | int value; 27 | DoubleNode* next; 28 | DoubleNode* last; 29 | DoubleNode( int data ) { 30 | this.value = data; 31 | } 32 | } DoubleNode; 33 | 34 | DoubleNode* reverseList( DoubleNode* head ) { 35 | DoubleNode* pre = NULL; 36 | DoubleNode* next = NULL; 37 | while( head != NULL ) { 38 | next = head->next; 39 | head->next = pre; 40 | head->last = next; 41 | pre = head; 42 | head = next; 43 | } 44 | 45 | return pre; 46 | } 47 | -------------------------------------------------------------------------------- /2-5.反转部分单链表.cpp: -------------------------------------------------------------------------------- 1 | typedef struct Node { 2 | int value; 3 | Node* next; 4 | 5 | Node( int data ) { 6 | this.value = data; 7 | } 8 | } Node; 9 | 10 | Node* reversePart( Node* head, int from, int to ) { 11 | int len = 0; 12 | Node* node1 = NULL; 13 | Node* fPre = NULL; 14 | Node* tPos = NULL; 15 | while( node1 != NULL ) { 16 | len++; 17 | fPre = len == from - 1 ? node1 : fPre; 18 | tPos = len == to + 1 ? node1 : tPos; 19 | node1 = node1->next; 20 | } 21 | if( from > to || from < 1 || to > len ) return head; 22 | 23 | node1 = fPre == NULL ? head : fPre.next; 24 | Node* node2 = node1->next; 25 | node1>next = tPos; 26 | Node* next = NULL; 27 | while( node2 != tPos ) { 28 | next = node2->next; 29 | node2->next = node1; 30 | node1 = node2; 31 | node2 = next; 32 | } 33 | if( fPre != NULL ) { 34 | fPre->next = node1; 35 | return head; 36 | } 37 | return node1; 38 | } 39 | -------------------------------------------------------------------------------- /2-6.环形单链表的约瑟夫环问题.cpp: -------------------------------------------------------------------------------- 1 | typedef struct Node { 2 | int value; 3 | Node* next; 4 | 5 | Node( int data ) { 6 | this.value = data; 7 | } 8 | } Node; 9 | 10 | Node* josephusKill( Node* head, int m ) { 11 | if( head == NULL || head->next == head || m < 1 ) return head; 12 | 13 | Node* last = head; 14 | while( last->next != head ) { 15 | last = last->next; 16 | } 17 | int count = 0; 18 | while( head != last ) { 19 | if( ++count == m ) { 20 | last->next = head->next; 21 | count = 0; 22 | } 23 | else { 24 | last = last->next; 25 | } 26 | head = last->next; 27 | } 28 | 29 | return head; 30 | } 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Coding-Interview-Guide 2 | 《程序员面试代码指南——IT名企算法与数据结构题目最优解》、个人面试算法练习 3 | 4 | ## 第一章 栈和队列 5 | 6 | * 1-1.设计具有getMin()功能的栈 7 | 8 | * 1-2.两个栈实现队列 9 | 10 | * 1-3.仅用递归和栈操作实现栈的逆序 11 | 12 | * 1-5.用栈实现另一个栈的排序 13 | 14 | * 1-6.用栈来求解汉诺塔问题 15 | 16 | * 1-7.生成窗口最大值数组 17 | 18 | * 1-8.构造数组的MaxTree 19 | 20 | * 1-9.求最大子矩阵的大小 21 | 22 | ## 第二章 链表问题 23 | 24 | * 2-1.打印两个有序链表的公共部分 25 | 26 | * 2-2.在单链表删除倒数第n个结点 27 | 28 | ## 第三章 二叉树问题 29 | 30 | 31 | ## 第四章 递归和动态规划 32 | 33 | 34 | ## 第五章 字符串问题 35 | 36 | 37 | ## 第六章 大数据和空间限制 38 | 39 | 40 | ## 第七章 位运算 41 | 42 | 43 | ## 第八章 数组和矩阵问题 44 | 45 | 46 | ## 第九章 其他题目 47 | 48 | 49 | 50 | --------------------------------------------------------------------------------