zoukankan      html  css  js  c++  java
  • 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 << '	' << 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

    所有博文均为原著,如若转载,请注明出处!
  • 相关阅读:
    概率算法实现八皇后问题-cpp
    交互式多媒体图书平台的设计
    Map容器
    序列容器和容器适配器
    ubuntu18.04 基于VSCode的C++环境搭建
    工程化编程实战callback接口学习
    stl_string
    通过filebeat的modules搜集nginx日志
    gitlab-runner安装配置
    EFK搜集MySQL慢日志
  • 原文地址:https://www.cnblogs.com/zpcoding/p/10538140.html
Copyright © 2011-2022 走看看