C++ STL和几道经典的面试题

本文深入解析C++标准模板库(STL)各组件的底层实现原理,包括vector、list等容器,以及stack、queue等适配器,并提供实用的位运算技巧和数组操作方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

1、C++ STL 的底层实现:

2、不用算术运算符进行求和

3、两数组不同数据

4、元素去重

5、组合求解

6、打靶算法


1、C++ STL 的底层实现:

vector底层数据结构为数组 ,支持快速随机访问
list底层数据结构为双向链表,支持快速增删
deque底层数据结构为一个中央控制器和多个缓冲区,详细见STL源码剖析P146,支持首尾(中间不能)快速增删,也支持随机访问
stack底层一般用23实现,封闭头部即可,不用vector的原因应该是容量大小有限制,扩容耗时
queue底层一般用23实现,封闭头部即可,不用vector的原因应该是容量大小有限制,扩容耗时(stack和queue其实是适配器,而不叫容器,因为是对容器的再封装)
priority_queue底层数据结构一般为vector为底层容器,堆heap为处理规则来管理底层容器实现
set底层数据结构为红黑树,有序,不重复
multiset底层数据结构为红黑树,有序,可重复
map底层数据结构为红黑树,有序,不重复
multimap底层数据结构为红黑树,有序,可重复
hash_set底层数据结构为hash表,无序,不重复
hash_multiset底层数据结构为hash表,无序,可重复
hash_map 底层数据结构为hash表,无序,不重复
hash_multimap底层数据结构为hash表,无序,可重复

2、不用算术运算符进行求和

不使用算术运算求和那么只能考虑直接在二进制位上进行位运算,事实上利用异或运算(^)和与运算(&)就能完成加法运算要做的事情,其中异或运算完成相加但是不进位,而与运算计算出哪些地方需要进位,在通过左移运算(<<)就可以完成进位操作了。

#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;  
}

3、两数组不同数据

利用位运算中异或运算的特点,两个相同的数异或的结果一定是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;
}

4、元素去重

题目:有一个已经排好序的数组,其中存在重复元素,请将重复元素删除掉,例如,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); 
}  

5、组合求解

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);
}

6、打靶算法

靶环有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

如果不用递归的思想,使用循环的方式的话,要打几枪需要写几层循环,虽然思路简单,如果是打是几十或上百那要写死了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值