c++ 面试题(算法类)
1,从无序的数据流中找到其中位数:(用大根堆和小根堆来实现)
1 float getMidimum(vector<int>& nums) { 2 priority_queue<int> bigHeap; // 大数优先 3 priority_queue<int, vector<int>, greater<int>> smallHeap; // 小数优先 4 for (int i = 0; i < nums.size(); ++i) { // 对每一个输入的元素 5 if (bigHeap.empty() || nums[i] < bigHeap.top()) 6 bigHeap.push(nums[i]); 7 else 8 smallHeap.push(nums[i]); 9 10 while (bigHeap.size() > smallHeap.size() + 1) { 11 smallHeap.push(bigHeap.top()); 12 bigHeap.pop(); 13 } 14 while (smallHeap.size() > bigHeap.size() + 1) { 15 bigHeap.push(smallHeap.top()); 16 smallHeap.pop(); 17 } 18 } 19 float temp;// 如果两个堆大小相等 20 if (bigHeap.size() == smallHeap.size()) { 21 temp = float(bigHeap.top() + smallHeap.top()) / 2; 22 } 23 else if (bigHeap.size() < smallHeap.size()) // 如果小堆多一个元素 24 temp = smallHeap.top(); 25 else // 如果大堆多一个元素 26 temp = bigHeap.top(); 27 return temp; 28 }
2,25匹马五条赛道怎么最快选出前三个:(类似于:剑指offer p38::二维数组中的查找)
参考:https://blog.csdn.net/cmsbupt/article/details/17404183
3,给定出栈顺序,求入栈顺序:
给定入栈顺序,求出栈顺序:
1 string Out; // 都声明未全局变量 2 string In; 3 bool match(string& In) { 4 int lens = Out.length(); 5 stack<char> stk; // 模拟入栈操作 6 stk.push(In[0]); 7 int j = 1, i = 0; // j 为入栈序列索引, i 为出栈序列索引 8 while (i < lens) { // 如果还没有匹配完所有出栈元素序列,则不断进行匹配,直到入栈序列结束 9 if (j<lens && (stk.empty() || stk.top() != Out[i])) { // 如果入栈序列还有未进入栈的 && (栈空 || 不匹配)--》入栈操作 10 stk.push(In[j]); 11 ++j; // 指向下一个入栈元素 12 } 13 else if (stk.top() == Out[i]) { 14 stk.pop(); 15 ++i; 16 } 17 else if (j == lens && !stk.empty()) { // 如果最后一个元素也遍历了,并且此时栈不空---》不是出栈顺序 18 return false; 19 } 20 } 21 return true; 22 }
1 int _tmain(int argc, _TCHAR* argv[]) 2 { 3 // 给定一个栈的输出序列,找出所有可能的输入序列 4 cout << "input outStack string[Enter]:"; 5 cin >> Out; 6 In = Out; 7 8 sort(In.begin(), In.end()); //求出所有的输入序列,排序的目的是从头开始进行全排列 9 do { 10 if (match(In)) // 该函数的功能是对 In 和 Out 进行匹配,传入的总是 In 11 cout << In << endl; 12 } while (next_permutation(In.begin(), In.end())); // 该函数的实现见前面leetcode 数组类型题的相关博客 13 14 system("pause"); 15 return 0; 16 } 17 18 int _tmain(int argc, _TCHAR* argv[]) 19 { 20 // 给定一个栈的输入序列,找出所有可能的输出序列 21 cout << "input inStack string[Enter]:"; 22 cin >> In; 23 Out = In; 24 25 sort(Out.begin(), Out.end()); // 求出所有的输出序列 26 do { 27 if (match(In)) 28 cout << Out<< endl; // Out 是不断变化的 29 } while (next_permutation(Out.begin(), Out.end())); //修改的是 Out 的本身 30 31 system("pause"); 32 return 0; 33 }
4,给定以排好序的数组(包括负数,0,和正数),平方后找到其重复的元素(时间复杂度为 n,空间复杂度为 1)注:范围未知道
1 void show(vector<int>& result) { 2 for (int i = 0; i<result.size(); ++i) 3 cout << '\t' << result[i]; 4 cout << endl; 5 } 6 7 vector<int> dupNums(vector<int>& nums) { 8 vector<int> result; 9 for (int i = 0; i<nums.size(); ++i) 10 nums[i] *= nums[i]; 11 show(nums); 12 vector<int>::iterator start = nums.begin(); 13 vector<int>::iterator end = nums.end() - 1; 14 while (start != end) { 15 bool dup = false; 16 if (*start < *end) { 17 while ((end - 1) != start) { 18 if (*(end - 1) == *end) { 19 end--; 20 dup = true; 21 } 22 else { 23 break; 24 } 25 } // while2 26 27 if (start != (end - 1) && dup) { 28 result.push_back(*end); 29 end--; 30 } 31 else if (start != (end - 1) && !dup){ 32 end--; 33 } 34 // show(result); 35 if (end - 1 == start) { 36 if (*end == *start) { 37 result.push_back(*start); 38 } 39 return result; 40 } 41 }//if 42 else if (*start > *end) { 43 while (start + 1 != end) { 44 if (*(start + 1) == *start) { 45 start++; 46 dup = true; 47 } 48 else { 49 start++; 50 break; 51 } 52 }//while2 53 if (start + 1 != end && dup) { 54 result.push_back(*start); 55 start++; 56 } 57 if (start + 1 != end && !dup) { 58 start++; 59 } 60 if (start + 1 == end) { 61 if (*start == *end) { 62 result.push_back(*start); 63 } 64 return result; 65 } 66 }//else if 67 else { 68 while (start + 1 != end) { 69 if (*(start + 1) == *start) { 70 start++; 71 } 72 else { 73 result.push_back(*start); 74 start++; 75 break; 76 } 77 } 78 if (start + 1 == end) { 79 return result; 80 } 81 while ((end - 1) != start) { 82 if (*(end - 1) == *end) { 83 end--; 84 } 85 else { 86 end--; 87 break; 88 } 89 }//while2 90 if (end - 1 == start) { 91 if (*start == *end) { 92 result.push_back(*start); 93 } 94 return result; 95 } 96 }//else 97 }//while1 98 return result; 99 }
类似题:给定一个整数数组 a,其中1 ≤ a[i] ≤ n (n为数组长度), 其中有些元素出现两次而其他元素出现一次。找到所有出现两次的元素。空间复杂度为 1。注:范围已知
思路:把 nums[i] 放到 nums[nums[i] - 1] 的位置去(swap 操作)eg:把 4 放到下标为 3 的位置,把 5 放到下标为 4 的位置。
https://blog.csdn.net/zhangbaoanhadoop/article/details/82193866
5,skip_list(跳跃表):
https://blog.csdn.net/ict2014/article/details/17394259
6,快排(递归):
1 //quickSort 2 int Partition(int* arr, int left, int right) { 3 int pivot = arr[left]; 4 while (left < right) { 5 while (left < right && arr[right] >= pivot) 6 --right; 7 if (left < right) arr[left] = arr[right]; 8 9 while (left < right && arr[left] <= pivot) 10 ++left; 11 if (left < right) arr[right] = arr[left]; 12 } 13 arr[left] = pivot; 14 return left; // 返回枢纽值所在下标 15 } 16 17 void quickSort(int* arr, int left, int right) { 18 19 if (left < right) { 20 int pivot = Partition(arr, left, right); 21 quickSort(arr, left, pivot - 1); 22 quickSort(arr, pivot + 1, right); 23 } 24 }
快排(非递归,用栈来实现)
1 void QuickSort(int *a, int left,int right) 2 { 3 if (a == NULL || left < 0 || right <= 0 || left>right) 4 return; 5 stack<int>temp; 6 int i, j; 7 //(注意保存顺序)先将初始状态的左右指针压栈 8 temp.push(right);//先存右指针 9 temp.push(left);//再存左指针 10 while (!temp.empty()) 11 { 12 i = temp.top();//先弹出左指针 13 temp.pop(); 14 j = temp.top();//再弹出右指针 15 temp.pop(); 16 if (i < j) 17 { 18 int k = Pritation(a, i, j); 19 if (k > i) 20 { 21 temp.push(k - 1);//保存中间变量 22 temp.push(i); //保存中间变量 23 } 24 if (j > k) 25 { 26 temp.push(j); 27 temp.push(k + 1); 28 } 29 } 30 // 参考:http://www.cnblogs.com/ljy2013/p/4003412.html
快排时间复杂度分析:https://www.cnblogs.com/surgewong/p/3381438.html
快排的几种优化方式:https://blog.csdn.net/sofia_m/article/details/81534390
快排是不稳定的排序算法,那么稳定的意义是什么呢?
答:当有多个字段需要排序时(比如书籍的销量和书籍的价格),我们可以先用稳定排序对价格(从低到高)进行排序,然后在用稳定排序对书籍的销量进行排序,这样排序的结果就是相同销量的数据价格低的排在前面,达到了在第一列排序的基础上排序了第二列。
7,堆排序:
1 //heapSort 2 void Swap(int& a, int& b) { 3 int temp = a; 4 a = b; 5 b = temp; 6 } 7 //向上调整 8 void siftUp(int* arr, int u) { 9 int c, p; // c == child , p == parent 10 c = u; 11 for (;;) { 12 if (c == 1) break; 13 p = c / 2; 14 if (arr[p] > arr[c]) break; 15 Swap(arr[c], arr[p]); 16 c = p; 17 } 18 } 19 // 向下调整 20 void siftDown(int* arr, int l, int u) { 21 int c, p; 22 p = l; 23 for (;;) { 24 c = 2 * p; 25 if (c > u) break; 26 if (c + 1 <= u && arr[c + 1] > arr[c]) c++; 27 if (arr[p] > arr[c]) break; 28 Swap(arr[p],arr[c]); 29 p = c; 30 } 31 } 32 // 向上调整建大根堆 33 void BuildBigHeap(int* arr,int n) { 34 for (int i = 2; i <= n; ++i) 35 siftUp(arr, i); 36 } 37 //向下调整建大根堆 38 void BuildHeap(int* arr, int n) { 39 for (int i = n / 2; i >= 1; --i) 40 siftDown(arr, i, n); 41 } 42 void heapSort(int* arr, int n) { 43 int i = 0; 44 arr--; 45 BuildBigHeap(arr, n); 46 for (i = n; i >= 2; --i) { 47 Swap(arr[1], arr[n]); 48 siftDown(arr, 1, i - 1); 49 } 50 arr++; 51 }
8,二分搜索
1 // 二分搜索 2 3 // @没有重复值 4 int binSearch(vector<int>& nums, int target) { 5 auto left = nums.begin(); 6 auto right = nums.end()-1; 7 while (left <= right) { // 找mid 的对应值,此时 = 号不能忽略,否则 mid 取不到所有值 8 auto mid = left + (right - left) / 2;// 把搜索范围缩小到 right = left or right = left+1,此时 mid = left 9 if (*mid == target) 10 return distance(nums.begin(), mid); 11 if (*mid < target) 12 left = mid + 1; 13 if (*mid > target) 14 right = mid - 1; 15 } 16 return -1; 17 } 18 19 //@ 有重复值,且返回匹配数 key 的最小下标,等同于 std::lower_bound (返回第一个大于等于 key 的迭代器) 20 int binSearchDupMinIndex(vector<int>& nums, int target) { 21 int left = 0; 22 int right = nums.size() - 1; 23 while (left <= right) { // 找mid 的对应值,此时 = 号不能忽略,否则 mid 取不到所有值 24 int mid = left + (right - left) / 2;// 把搜索范围缩小到 right = left or right = left+1,此时 mid = left 25 if (nums[mid] < target) 26 left = mid + 1; 27 else if (nums[mid] == target){ // 加以特殊处理 28 if (mid - 1 >= 0 && nums[mid - 1] == target) 29 right = mid - 1; 30 else 31 return mid; 32 } 33 else { 34 right = mid - 1; 35 } 36 } 37 return -1; 38 } 39 40 //@ 有重复值,且返回匹配数 key 的最大下标,等同于std::upper_bound(返回第一个大于 key 的元素的迭代器) 41 int binSearchDupMaxIndex(vector<int>& nums, int target) { 42 int left = 0; 43 int right = nums.size() - 1; 44 while (left <= right) { // 找mid 的对应值,此时 = 号不能忽略,否则 mid 取不到所有值 45 int mid = left + (right - left) / 2;// 把搜索范围缩小到 right = left or right = left+1,此时 mid = left 46 if (nums[mid] < target) 47 left = mid + 1; 48 else if (nums[mid] == target){ // 加以特殊处理 49 if (mid + 1 <= right && nums[mid + 1] == target) 50 left = mid + 1; 51 else 52 return mid; 53 } 54 else { 55 right = mid - 1; 56 } 57 } 58 return -1; 59 } 60 61 // [4,5,1,2,3] 旋转数组的二分查找 62 // @ 无重复值 63 int binFind(vector<int>& nums, int target) { 64 int left = 0; 65 int right = nums.size() - 1; 66 while (left <= right) { 67 int mid = left + (right - left) / 2; 68 if (nums[mid] == target) 69 return mid; 70 else if (nums[left] <= nums[mid]) { // mid in left side 递减序列 71 if (nums[left] <= target && target < nums[mid]) // left---target----mid 72 right = mid - 1; 73 else // left---mid---target 74 left = mid + 1; 75 } 76 else { // mid in right side 递增序列 77 if (nums[mid] < target && target <= nums[right]) // mid---target---right 78 left = mid + 1; 79 else // target---mid---right 80 right = mid - 1; 81 } 82 } 83 return -1; 84 } 85 86 // @有重复值 87 // 包含重复元素的数组 A = [1,3,1,1,1],当A[m] >= A[left]时,不能确定target 在left side 88 // 拆分成两个条件: 89 //(1)若:A[mid] > A[left],则区间 [left,mid] 一定递增 90 //(2)若 A[mid] == A[left],确定不了,那就 left++,除去此元素再进行此查找过程 91 int binFindDup(vector<int>& nums, int target) { 92 int left = 0; 93 int right = nums.size() - 1; 94 while (left <= right) { 95 int mid = left + (right - left) / 2; 96 if (nums[mid] == target) 97 return mid; 98 else if (nums[left] < nums[mid]) { // mid in left side 递减序列 99 if (nums[left] <= target && target < nums[mid]) // left---target----mid 100 right = mid - 1; 101 else // left---mid---target 102 left = mid + 1; 103 } 104 else if(nums[left] > target){ // mid in right side 递增序列 105 if (nums[mid] < target && target <= nums[right]) // mid---target---right 106 left = mid + 1; 107 else // target---mid---right 108 right = mid - 1; 109 } 110 else { // 把这个元素除去搜索范围 111 //skip duplicate one 112 left++; 113 } 114 } 115 return -1; 116 }
9,给定一个数组a,O(n)时间求 a[j] - a[i] 的最大值?
https://blog.csdn.net/xiaofengcanyuelong/article/details/78965552