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 }
getMidimum

 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 }
stackMatch
 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 }
main

 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 }
dupNums

  类似题:给定一个整数数组 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 }
quickSort

快排(非递归,用栈来实现)

 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
quickSort(非递归)

快排时间复杂度分析: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 }
heapSort

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 }
binSearch

 9,给定一个数组a,O(n)时间求 a[j] - a[i] 的最大值?

  https://blog.csdn.net/xiaofengcanyuelong/article/details/78965552

 

posted on 2019-03-15 16:54  爱笑的张飞  阅读(443)  评论(0编辑  收藏  举报

导航