C++ STL和幾道經典的面試題
https://blog.csdn.net/dingyahui123/article/details/78644235
C++ STL 的實現:
1.vector: 底層資料結構為陣列 ,支援快速隨機訪問。
2.list: 底層資料結構為雙向連結串列,支援快速增刪。
3.deque: 底層資料結構為一箇中央控制器和多個緩衝區,詳細見STL原始碼剖析P146,支援首尾(中間不能)快速增刪,也支援隨機訪問。
4.stack : 底層一般用23實現,封閉頭部即可,不用vector的原因應該是容量大小有限制,擴容耗時
5.queue: 底層一般用23實現,封閉頭部即可,不用vector的原因應該是容量大小有限制,擴容耗時(stack和queue其實是介面卡,而不叫容器,因為是對容器的再封裝)
6.priority_queue: 的底層資料結構一般為vector為底層容器,堆heap為處理規則來管理底層容器實現
7.set: 底層資料結構為紅黑樹,有序,不重複。
8.multiset: 底層資料結構為紅黑樹,有序,可重複。
9.map: 底層資料結構為紅黑樹,有序,不重複。
10.multimap: 底層資料結構為紅黑樹,有序,可重複。
11.hash_set: 底層資料結構為hash表,無序,不重複。
12.hash_multiset: 底層資料結構為hash表,無序,可重複 。
13.hash_map : 底層資料結構為hash表,無序,不重複。
14.hash_multimap: 底層資料結構為hash表,無序,可重複。
1)不用算術運算子進行求和不使用算術運算求和那麼只能考慮直接在二進位制位上進行位運算,事實上利用異或運算(^)和與運算(&)就能完成加法運算要做的事情,其中異或運算完成相加但是不進位,而與運算計算出哪些地方需要進位,在通過左移運算(<<)就可以完成進位操作了。
#include"iostream.h"
int sum(int a,int b){
if(b == 0) return a;
int c = a ^ b;
int d = (a & b) << 1;
return sum(c, d);}
int main(){
cout<<sum(12,13);
return 0;
}
2)利用位運算中異或運算的特點,兩個相同的數異或的結果一定是0,那麼將a和b中的所有元素做一次異或運算,最終的結果就是b比a多出的那個元素的值
#include"iostream.h"
int find(int a[],int b[],int n){
int c = 0;
for(int i = 0; i <n; i++) {
c ^= a[i] ^ b[i];
}
c ^= b[n];
return c;
}
int main(){
int a[6]={1, 3, 2, -4, 10, 18};
int b[]= {3, 55, 1, 2, 10, -4, 18};
cout<<find(a,b,6);
return 0;
}
3)題目:有一個已經排好序的陣列,其中存在重複元素,請將重複元素刪除掉,例如,A = [1, 1, 2, 2, 3],處理之後的陣列應當為A = [1, 2, 3]。
public: int remove(int &A[],int n){
if(n==0)
return 0;
int index=0;
for(int i=1;i<n;i++)
{
if(A[index]!=A[i])
A[++index]=A[i];
}
index++;
return index;
}
在O(n)的時間複雜度內完成陣列移動,如abcde,左移三位變為cdeab,如果陣列長度為l,移動位數為n,如果n大於l的話相當於移動n%l位,如果用一般的迴圈移位時間複雜度為O(n×l),不能在規定的要求內完成,所以只能考慮在陣列本身上下功夫,如abcde,移動3位,可以理解為剩下的前兩位翻轉,後3位翻轉然後整個陣列翻轉,abcde->bacde->baedc->cdeab,這樣就可以在O(n)等級的時間複雜度內完成操作。大致功能函式如下
int reverse(int i,int j,int *array)
{
for(;i>m;i++,m--)
{
temp = array[i];
array[i] = array[j];
array[j] = temp;
}
}
int main()
{
int n;//移動的位數
reserve(0,n-1,A);
reserve(n,L-n-1,A);
reserve(0,n-1,A);
}
4)F(M,N)求解不大於N的和是M的所有組合個數。使用遞迴求解組合個數。
#include "iostream"
using namespace std;
int f(int m,int n)
{
if(m==1)
return 1;
if(n==1)
{
return 1;
}
if(m<n)
{
return f(m,m);
}
if (m==n)
{
return 1+f(m,n-1);
}
return f(m,n-1)+f(m-n,f(m-n,n));
}
int main()
{
cout<<f(3,3);
}
5)打靶演算法:靶環有10個環,那麼當打中時分數可為1-10,如果未打中得分為0,也就是11種可能,比如現在求6槍50分的概率
#include <iostream>
#include <time.h>
using namespace std;
int sum;
int all=0;
int n;
int store[10];
void Output()
{
for(int i = 9; i>=0; --i)
{
cout<<store[i]<<" ";
}
cout<<endl;
++sum;
}
void Cumput(int score, int num)
{
if(score < 0 || score > (num+1)*10 ) //次數為0~9
return;
if(num == 0)
{
store[num] = score;
Output();
for(int i = 9; i>=10-num; --i)
{
all+=store[i];
}
if(all==score){
n++;
all=0;
}
return;
}
for(int i = 0; i <= 10; ++i)
{
store[num] = i;
Cumput(score - i, num - 1);
}
}
int main()
{
const double begin=(double)clock();
Cumput(50, 6);
const double end=(double)clock();
cout<<"總的可能數量:"<<sum<<" ."<<"得分可能數量:"<<n<<endl;
cout<<"用時:"<<end-begin<<endl;
cout<<"概率"<<double(n)/sum;
return 0;
}
......................
......................
0 0 0 10 10 10 10 8 2 0
0 0 0 10 10 10 10 9 0 1
0 0 0 10 10 10 10 9 1 0
0 0 0 10 10 10 10 10 0 0
總的可能數量:195195 .得分可能數量:3003
用時:339931
概率0.0153846
如果不用遞迴的思想,使用迴圈的方式的話,要打幾槍需要寫幾層迴圈,雖然思路簡單,如果是打是幾十或上百那要寫死了。
---------------------
作者:刀客123
來源:CSDN
原文:https://blog.csdn.net/dingyahui123/article/details/78644235
版權宣告:本文為博主原創文章,轉載請附上博文連結!