1. 赋值运算符函数(或应说复制拷贝函数问题)
class A { private: int value; public: A(int n) : value(n) {} A(A O) { value = O.value; } // Compile Error : (const A& O) };
因为,A a(0); A b = a; 就会使程序陷入死循环。
2. 实现 Singleton 模式 (C#)
(博客待加设计模式总结)
3.二维数组中的查找
Sample:
二维数组:Matrix[4][4],行列都是递增。
1 2 8 9
2 4 9 12
4 7 10 13
6 8 11 15
判断 value = 7 是否在数组。
思路:从右上角开始,若大于 7 删去一列; 若小于 7 删去一行。
代码:
#include<iostream> const int N = 4; int data[][N] = {{1, 2, 8, 9},{ 2, 4, 9, 12},{4, 7, 10, 13}, {6, 8, 11, 15}}; bool find(int (*matrix)[N], int row, int column, int value) { int r = 0, c = column - 1; while(r < row && c >= 0) { if(matrix[r][c] == value) return true; if(matrix[r][c] > value) --c; else ++r; } return false; } int main() { std::cout << find(data, 4, 4, 10) << std::endl; return 0; }
4.替换空格 时间:O(n) 空间:O(1)
Sample:
输入: S:"We are happy."
输出:S:"We%20are%20happy."
1 #include<stdio.h> 2 #include<string.h> 3 const int N = 18; 4 /* length is the full capacity of the string, max number of elements is length-1*/ 5 void ReplaceBank(char s[], int length){ 6 if(s == NULL && length <= 0) return; // program robustness 7 int nowLength = -1, numberOfBlank = 0; 8 while(s[++nowLength] != '\0'){ 9 if(s[nowLength] == ' ') ++numberOfBlank; 10 } 11 int newLength = nowLength + numberOfBlank * 2; // newLength is the number of elements 12 if(newLength >= length) return; 13 14 int idOfNow = nowLength, idOfNew = newLength; // both point to '/0' 15 while(idOfNow >= 0){ /* key program */ 16 if(s[idOfNow] == ' ') { 17 strncpy(s+idOfNew-2, "%20", 3); 18 idOfNew -= 3; 19 --idOfNow; 20 }else 21 s[idOfNew--] = s[idOfNow--]; 22 } 23 } 24 25 int main(){ 26 char s[N] = "We are happy."; 27 puts(s); 28 ReplaceBank(s,N); 29 puts(s); 30 return 0; 31 }
5.从尾到头打印链表
1. 询问是否可以改变链表结构,若可以,则空间O(1);否则,
2. 使用栈,或者递归。
a. 使用栈:
1 #include <iostream> 2 #include <string> 3 #include <stack> 4 5 struct LinkNode{ 6 char e; 7 LinkNode *next; 8 }; 9 10 void print(LinkNode *Head) 11 { 12 std::stack<char> st; 13 while(Head != NULL) 14 { 15 st.push(Head->e); 16 Head = Head->next; 17 } 18 while(!st.empty()) 19 { 20 printf("%c ", st.top()); 21 st.pop(); 22 } 23 printf("\n"); 24 } 25 26 LinkNode* init(const std::string &s) 27 { 28 size_t i = 0; 29 LinkNode *head, *p; 30 p = head = NULL; 31 while(i < s.length()) 32 { 33 LinkNode *p2 = new LinkNode; 34 p2->e = s[i++]; p2->next = NULL; 35 if(head == NULL) 36 head = p = p2; 37 else 38 { 39 p->next = p2; 40 p = p->next; 41 } 42 } 43 return head; 44 } 45 void release(LinkNode *Head){ 46 if(Head == NULL) return; 47 release(Head->next); 48 delete[] Head; 49 Head = NULL; 50 } 51 int main() 52 { 53 const std::string s = "ABCDEFG"; 54 LinkNode *Head = init(s); 55 print(Head); 56 release(Head); 57 return 0; 58 }
b. 使用递归:
void RecursivePrint(LinkNode *Head) { if(Head == NULL) return; RecursivePrint(Head->next); printf("%c ", Head->e); }
6. 重建二叉树
a. 前序 && 中序
1 #include <cstdio> 2 #include <queue> 3 struct BTNode{ 4 int value; 5 BTNode *pLeft; 6 BTNode *pRight; 7 BTNode(int x) : value(x), pLeft(NULL), pRight(NULL) {} 8 }; 9 10 BTNode* constructCore(int *startPreOrder, int *endPreOrder, int *startInOrder, int *endInOrder) 11 { 12 int rootValue = startPreOrder[0]; 13 BTNode *root = new BTNode(rootValue); 14 int *rootInOrder = startInOrder; 15 while(*rootInOrder != rootValue && rootInOrder <= endInOrder) ++rootInOrder; 16 if(*rootInOrder != rootValue) { printf("Invalid Input!"); return NULL; } 17 18 int leftLength = rootInOrder - startInOrder; 19 if(leftLength > 0) 20 { 21 root->pLeft = constructCore(startPreOrder + 1, startPreOrder + leftLength, 22 startInOrder, startInOrder + leftLength - 1); 23 } 24 if(rootInOrder != endInOrder) 25 { 26 root->pRight = constructCore(startPreOrder + leftLength + 1, endPreOrder, 27 rootInOrder + 1, endInOrder); 28 } 29 return root; 30 } 31 32 BTNode* construct(int *preOrder, int *inOrder, int length) 33 { 34 if(preOrder == NULL || inOrder == NULL || length <= 0) 35 return NULL; 36 return constructCore(preOrder, preOrder + length - 1, inOrder, inOrder + length -1); 37 } 38 void print(BTNode *root) 39 { 40 if(root == NULL) return; 41 42 std::queue<BTNode*> qu; 43 qu.push(root); 44 while(!qu.empty()) 45 { 46 BTNode *p = qu.front(); 47 qu.pop(); 48 if(p->pLeft) qu.push(p->pLeft); 49 if(p->pRight) qu.push(p->pRight); 50 printf("%d ", p->value); 51 } 52 } 53 void release(BTNode *root) 54 { 55 if(root == NULL) return; 56 release(root->pLeft); 57 release(root->pRight); 58 delete[] root; 59 root = NULL; 60 } 61 62 int main() 63 { 64 int preOrder[] = {1, 2, 4, 7, 3, 5, 6, 8}; 65 int inOrder[] = {4, 7, 2, 1, 5, 3, 8, 6}; 66 BTNode *root = construct(preOrder, inOrder, 8); 67 print(root); 68 release(root); 69 return 0; 70 }
二叉树的各种遍历:
1 #include <cstdio> 2 #include <queue> 3 #include <stack> 4 struct BTNode{ 5 int value; 6 BTNode *pLeft; 7 BTNode *pRight; 8 BTNode(int x) : value(x), pLeft(NULL), pRight(NULL) {} 9 }; 10 11 BTNode* constructCore(int *startPreOrder, int *endPreOrder, int *startInOrder, int *endInOrder) 12 { 13 int rootValue = startPreOrder[0]; 14 BTNode *root = new BTNode(rootValue); 15 int *rootInOrder = startInOrder; 16 while(*rootInOrder != rootValue && rootInOrder <= endInOrder) ++rootInOrder; 17 if(*rootInOrder != rootValue) { printf("Invalid Input!\n"); return NULL; } 18 19 int leftLength = rootInOrder - startInOrder; 20 if(leftLength > 0) 21 { 22 root->pLeft = constructCore(startPreOrder + 1, startPreOrder + leftLength, 23 startInOrder, startInOrder + leftLength - 1); 24 } 25 if(rootInOrder != endInOrder) 26 { 27 root->pRight = constructCore(startPreOrder + leftLength + 1, endPreOrder, 28 rootInOrder + 1, endInOrder); 29 } 30 return root; 31 } 32 33 BTNode* construct(int *preOrder, int *inOrder, int length) 34 { 35 if(preOrder == NULL || inOrder == NULL || length <= 0) 36 return NULL; 37 return constructCore(preOrder, preOrder + length - 1, inOrder, inOrder + length -1); 38 } 39 void levelOrderPrint(BTNode *root) 40 { 41 if(root == NULL) return; 42 printf("BFS:"); 43 std::queue<BTNode*> qu; 44 qu.push(root); 45 while(!qu.empty()) 46 { 47 BTNode *p = qu.front(); 48 qu.pop(); 49 if(p->pLeft) qu.push(p->pLeft); 50 if(p->pRight) qu.push(p->pRight); 51 printf("%-3d ", p->value); 52 } 53 printf("\n"); 54 } 55 void preORderPrint2(BTNode *root) // preORder 56 { 57 if(root == NULL) return; 58 printf("DLR: "); 59 std::stack<BTNode*> st; 60 st.push(root); 61 while(!st.empty()) 62 { 63 BTNode *p = st.top(); 64 st.pop(); 65 if(p->pRight) st.push(p->pRight); 66 if(p->pLeft) st.push(p->pLeft); 67 printf("%-3d ", p->value); 68 } 69 printf("\n"); 70 } 71 void inOrderPrint3(BTNode *root) // inOrder 72 { 73 if(root == NULL) return; 74 printf("LDR: "); 75 std::stack<BTNode*> st; 76 st.push(root); 77 BTNode *p = root; 78 while(p->pLeft) 79 { 80 st.push(p->pLeft); 81 p = p->pLeft; 82 } 83 while(!st.empty()) 84 { 85 p = st.top(); 86 st.pop(); 87 if(p->pRight) 88 { 89 BTNode *q = p->pRight; 90 st.push(q); 91 while(q->pLeft) { st.push(q->pLeft); q = q->pLeft; } 92 } 93 printf("%-3d ", p->value); 94 } 95 printf("\n"); 96 } 97 void postOrderPrint4(BTNode *root) // postOrder 98 { 99 if(root == NULL) return; 100 printf("LRD: "); 101 std::stack<BTNode*>st; 102 st.push(root); 103 BTNode *p = root; 104 while(p->pLeft || p->pRight) 105 { 106 while(p->pLeft) { st.push(p->pLeft); p = p->pLeft; } 107 if(p->pRight) { st.push(p->pRight); p = p->pRight; } 108 } 109 //bool tag = true; 110 while(!st.empty()) 111 { 112 BTNode *q = st.top(); 113 st.pop(); 114 if(!st.empty()) 115 { 116 p = st.top(); 117 if(p->pRight && p->pRight != q) 118 { 119 st.push(p->pRight); p = p->pRight; 120 while(p->pLeft || p->pRight) 121 { 122 while(p->pLeft) { st.push(p->pLeft); p = p->pLeft; } 123 if(p->pRight) { st.push(p->pRight); p = p->pRight; } 124 } 125 } 126 } 127 printf("%-3d ", q->value); 128 } 129 printf("\n"); 130 } 131 void DFSPrint(BTNode *root,const int nVertex) 132 { 133 if(root == NULL) return; 134 printf("DFS: "); 135 bool *visit = new bool[nVertex]; 136 memset(visit, false, nVertex); 137 std::stack<BTNode*> st; 138 st.push(root); 139 visit[root->value] = true; 140 while(!st.empty()) 141 { 142 BTNode *p = st.top(); 143 st.pop(); 144 if(p->pRight && !visit[p->pRight->value]) { st.push(p->pRight); visit[p->pRight->value] = true; } 145 if(p->pLeft && !visit[p->pLeft->value]) { st.push(p->pLeft); visit[p->pLeft->value];} 146 printf("%-3d ", p->value); 147 } 148 printf("\n"); 149 } 150 void release(BTNode *root) 151 { 152 if(root == NULL) return; 153 release(root->pLeft); 154 release(root->pRight); 155 delete[] root; 156 root = NULL; 157 } 158 159 int main() 160 { 161 int preOrder[] = {1, 2, 4, 8, 9, 5, 10, 11, 3, 6, 12, 13, 7, 14, 15}; 162 int inOrder[] = {8, 4, 9, 2, 10, 5, 10, 1, 12, 6, 13, 3, 14, 7, 15}; 163 BTNode *root = construct(preOrder, inOrder, 15); 164 levelOrderPrint(root); 165 preORderPrint2(root); 166 inOrderPrint3(root); 167 postOrderPrint4(root); 168 DFSPrint(root, 15+1); 169 release(root); 170 return 0; 171 }
7.用两个栈实现队列
1 #include <cstdio> 2 #include <stack> 3 #include <exception> 4 template<typename T> class CQueue 5 { 6 public: 7 void appendTail(T x); 8 T deleteHead(); 9 private: 10 std::stack<T> st1; 11 std::stack<T> st2; 12 }; 13 template<typename T>void CQueue<T>::appendTail(T x) 14 { 15 st1.push(x); 16 } 17 template<typename T>T CQueue<T>::deleteHead() 18 { 19 if(st2.empty()) 20 { 21 if(st1.empty()) throw new std::exception("queue is empty!"); 22 while(!st1.empty()) 23 { 24 st2.push(st1.top()); 25 st1.pop(); 26 } 27 } 28 T v = st2.top(); 29 st2.pop(); 30 return v; 31 } 32 33 int main() 34 { 35 printf("Test int:\n"); 36 CQueue<int> qu; 37 qu.appendTail(10); 38 qu.appendTail(2); 39 printf("%d\n",qu.deleteHead()); 40 printf("%d\n",qu.deleteHead()); 41 42 printf("Test char*:\n"); 43 CQueue<char*> qu2; 44 qu2.appendTail("Hello"); 45 qu2.appendTail("World!"); 46 printf("%s\n",qu2.deleteHead()); 47 printf("%s\n",qu2.deleteHead()); 48 //printf("%s\n",qu2.deleteHead()); 49 return 0; 50 }
8.旋转数组的最小数字
1 #include <iostream> 2 using namespace std; 3 4 int MinInorder(int *numbers, int low, int high) 5 { 6 int minNum = numbers[low]; 7 while(++low <= high) 8 { 9 if(numbers[low] < minNum) 10 minNum = numbers[low]; 11 } 12 return minNum; 13 } 14 15 int Min(int *numbers, int length) 16 { 17 if(numbers == NULL || length <= 0) throw new exception("Invalid parameters!"); 18 int low = 0, high = length - 1; 19 int mid = low; // note 20 while(numbers[low] >= numbers[high]) // note >= 21 { 22 if(high - low == 1) 23 { 24 mid = high; 25 break; 26 } 27 mid = (low + high) >> 1; 28 if(numbers[mid] == numbers[low] && numbers[mid] == numbers[high]) return MinInorder(numbers, low, high); 29 else if(numbers[mid] >= numbers[low]) low = mid; 30 else if(numbers[mid] <= numbers[high]) high = mid; 31 } 32 return numbers[mid]; 33 } 34 35 int main() 36 { 37 int test1[] = {4, 5, 1, 2, 3}; 38 cout << "Test1: " << Min(test1, sizeof(test1)/4) << endl; 39 40 int test2[] = {1, 1, 1, 0, 1}; 41 cout << "Test2: " << Min(test2, sizeof(test2)/4) << endl; 42 43 return 0; 44 }
9.斐波那契数列第 n 项
a. 动态规划(从低到高保存结果)
int Fibonacci1(unsigned long long N) { long long fibN; long long a[] = {0, 1}; if(N < 2) return a[N]; while(N >= 2) { fibN = (a[0] + a[1]) % M; a[0] = a[1]; a[1] = fibN; --N; } return (int)fibN; }
b1.矩阵二分乘(递归)
const int M = 1e+9 +7 ; struct Matrix{ long long e[2][2]; }; Matrix Mat; Matrix multiplyMatrix(Matrix &A, Matrix &B) { Matrix C; for(int i = 0; i < 2; ++i){ for(int j = 0; j < 2; ++j){ C.e[i][j] = ((A.e[i][0] * B.e[0][j]) % M + (A.e[i][1] * B.e[1][j]) % M) % M; } } return C; } Matrix getMatrix(long long n) { if(n == 1) return Mat; Matrix tem = getMatrix(n>>1); tem = multiplyMatrix(tem,tem); if((n & 0x1) == 0) return tem; else return multiplyMatrix(Mat,tem); } int Fibonacci2(long long N) { if(N == 0) return 0; if(N == 1) return 1; Mat.e[0][0] = 1; Mat.e[0][1] = 1; Mat.e[1][0] = 1; Mat.e[1][1] = 0; Matrix result = getMatrix(N-1); return (int)result.e[0][0]; }
b2. 矩阵二分乘(非递归)
const int M = 1000000007; struct Matrix{ long long e[2][2]; }; Matrix Mat; Matrix multiplyMatrix(Matrix &A, Matrix &B) { Matrix C; for(int i = 0; i < 2; ++i){ for(int j = 0; j < 2; ++j){ C.e[i][j] = ((A.e[i][0] * B.e[0][j]) % M + (A.e[i][1] * B.e[1][j]) % M) % M; } } return C; } Matrix getMatrix(Matrix base, long long N) { Matrix T; // set one unit matrix T.e[0][0] = T.e[1][1] = 1; T.e[0][1] = T.e[1][0] = 0; while(N - 1 != 0) { if(N & 0x1) T = multiplyMatrix(T, base); base = multiplyMatrix(base, base); N >>= 1; } return multiplyMatrix(T, base); } int Fibonacci2(long long N) { if(N == 0) return 0; if(N == 1) return 1; Mat.e[0][0] = 1; Mat.e[0][1] = 1; Mat.e[1][0] = 1; Mat.e[1][1] = 0; Matrix result = getMatrix(Mat, N-1); return (int)result.e[0][0]; }
两种方法效率的比较:
1 #include <iostream> 2 #include <ctime> 3 using namespace std; 4 const int M = 1000000007; 5 struct Matrix{ 6 long long e[2][2]; 7 }; 8 Matrix Mat; 9 10 Matrix multiplyMatrix(Matrix &A, Matrix &B) 11 { 12 Matrix C; 13 for(int i = 0; i < 2; ++i){ 14 for(int j = 0; j < 2; ++j){ 15 C.e[i][j] = ((A.e[i][0] * B.e[0][j]) % M + (A.e[i][1] * B.e[1][j]) % M) % M; 16 } 17 } 18 return C; 19 } 20 Matrix getMatrix(Matrix base, long long N) 21 { 22 Matrix T; // set one unit matrix 23 T.e[0][0] = T.e[1][1] = 1; 24 T.e[0][1] = T.e[1][0] = 0; 25 while(N - 1 != 0) 26 { 27 if(N & 0x1) T = multiplyMatrix(T, base); 28 base = multiplyMatrix(base, base); 29 N >>= 1; 30 } 31 return multiplyMatrix(T, base); 32 } 33 34 int Fibonacci2(long long N) 35 { 36 if(N == 0) return 0; 37 if(N == 1) return 1; 38 Mat.e[0][0] = 1; Mat.e[0][1] = 1; 39 Mat.e[1][0] = 1; Mat.e[1][1] = 0; 40 Matrix result = getMatrix(Mat, N-1); 41 return (int)result.e[0][0]; 42 } 43 44 int Fibonacci1(long long N) 45 { 46 long long fibN; 47 long long a[] = {0, 1}; 48 if(N < 2) return (int)a[N]; 49 while(N >= 2) 50 { 51 fibN = (a[0] + a[1]) % M; 52 a[0] = a[1]; 53 a[1] = fibN; 54 --N; 55 } 56 return (int)fibN; 57 } 58 59 int main() 60 { 61 unsigned long long N; 62 while(cin >> N) 63 { 64 /* method 1: DP */ 65 clock_t start = clock(); 66 int fibN = Fibonacci1(N); 67 clock_t end = clock(); 68 cout << "method1:" << fibN << " time: " << end-start << "ms" << endl; 69 /* method 2 */ 70 start = clock(); 71 fibN = Fibonacci2(N); 72 end = clock(); 73 cout << "method2:" << fibN << " time: " << end-start << "ms" << endl; 74 } 75 return 0; 76 }
10.一个整数的二进制表示中 1 的个数。(包含正负数)
需要注意的是:—1 >> (任意位) == —1; 负数 >> +∞ == —1。 ((—1)10 == (0xffffffff)16 )
a. 利用辅助变量,每次判断 n 的一位。
1 int numberOf1(int n) 2 { 3 int count = 0; 4 int flag = 1; 5 while(flag) 6 { 7 if(n & flag) count ++; 8 flag <<= 1; 9 } 10 return count; 11 }
b. 利用 n 的性质。
1 #include <iostream> 2 int numberOf1(int n){ 3 int count = 0; 4 while(n){ 5 count ++; 6 n &= (n-1); 7 } 8 return count; 9 } 10 int main(){ 11 int N; 12 while(std::cin >> N){ 13 std::cout << "has 1: " << numberOf1(N) << std::endl; 14 } 15 return 0; 16 }