腾讯软件后台开发0426笔试-超详细题目+C++实现

总体感受

成绩还算满意,100+60+0+100+100,两道数据结构的题都比较基础,欢迎指正和参考🤣

题目1:模拟队列

我老老实实用的链表实现,花了我三十分钟,我当场裂开……
输入样例:
第一行输入样例数T,之后每个样例,先输入操作数Q,然后进行"PUSH", "TOP", "POP", "SIZE","CLEAR"五种操作。
输出样例:
"TOP"输出队头元素,队伍空返回-1;"POP"失效时输出-1。
#include<iostream>
#include<stdio.h>
#include<algorithm>
using namespace std;

struct node{
	int val;
	node* next;
	node(int x):val(x),next(nullptr) {}
};

class myQueue{
public:
	myQueue(){
		dummyNode=new node(0);
		length=0;
	}
	~myQueue(){
		delete dummyNode;
		dummyNode=nullptr;
		length=0;
	}

	void push(int x){
		node* lastNode=dummyNode;
		while(lastNode->next){
			lastNode=lastNode->next;
		}
		node* newNode=new node(x);
		lastNode->next=newNode;
		length++;
	}

	void top(){
		if(length==0){
			printf("%d\n",-1);
		}
		else{
			printf("%d\n",dummyNode->next->val);
		}
	}

	void pop(){
		if(length==0){
			printf("%d\n",-1);
		}
		else{
			node* head=dummyNode->next;
			dummyNode->next=head->next;
			delete head;
			length--;
		}
	}

	void size(){
		printf("%d\n",length);
	}

	void clear(){
		delete dummyNode->next;
		dummyNode->next=nullptr;
		length=0;
	}
private:
	node* dummyNode;
	int length;
};

int main(){
	int T;
	scanf("%d",&T);
	for(int i=0;i<T;i++){
		myQueue q;
		int Q;
		scanf("%d", &Q);
		for(int j=0;j<Q;j++){
			string s;
			//s.resize(4);
			//scanf("%s",&s[0]);
			cin>>s;
			//cout<<s<<endl;
			if(s=="PUSH"){
				int i;
				scanf("%d",&i);
				q.push(i);
			}
			else if(s=="TOP"){
				q.top();
			}
			else if(s=="POP"){
				q.pop();
			}
			else if(s=="SIZE"){
				q.size();
			}
			else if(s=="CLEAR"){
				q.clear();
			}
		}
	}
	return 0;
}

题目2:求两个点集合的最短距离

给定两个相同规模的点集合(大小为n),计算集合间的最低距离。这里的距离是欧式距离,然后暴力枚举的,通过60%。希望AC的朋友指点下本弱鸡,之后会更新AC答案的,感谢~
输入样例:
第一行输入集合规模n,然后输入集合A和B的点坐标,每行是点的横坐标和纵坐标,先输入A再输入B
例如:
4
0 1
1 1
1 0
1 1
2 2
2 3
3 2
3 3
输出样例:两个集合间的最短距离
例如:上样例中,集合A的[1,1]和集合B的[2,2]距离最短,距离是1.414(保留三位小数)
#include <stdio.h>
#include <vector>
#include <cmath>
using namespace std;
vector<int> ax;
vector<int> ay;
vector<int> bx;
vector<int> by;
inline double calDist(int a, int b){
	return sqrt(pow(ax[a]-bx[b],2)+pow(ay[a]-by[b],2));
}

int main(){
	int N;
	scanf("%d",&N);
	for(int i=0;i<N;i++){
		int n;
		scanf("%d", &n);
		ax.assign(n,-1);
		ay.assign(n,-1);
		bx.assign(n,-1);
		by.assign(n,-1);
		for(int j=0;j<n;j++){
			scanf("%d %d", &ax[j], &ay[j]);
		}
		for(int j=0;j<n;j++){
			scanf("%d %d", &bx[j], &by[j]);
		}

		
		double dist=calDist(0,0);
		for(int i=0;i<n;i++){
			for(int j=0;j<n;j++){
				double tmp=calDist(i,j);
				if(tmp<dist) dist=tmp;
			}
		}
		printf("%.3f\n", dist);
	}
}

4月28日更新:

在ACWING上找到原题,并参考了一位大佬的思路(分治+二分),他的讲解十分清晰,链接是:https://www.acwing.com/solution/acwing/content/826/
自己重写了一遍代码,如下:
#include <bits/stdc++.h>
using namespace std;
const int N=1000005;
#define INF 1e8

struct point{
    double x,y;
    int f; // 集合
} P[N], T[N];

bool comp1(point a, point b){ // 根据x优先排序
    if(a.x==b.x) return a.y<b.y;
    return a.x<b.x;
}

bool comp2(point a, point b){ // 根据y优先排序
    if(a.y==b.y) return a.x<b.x;
    return a.y<b.y;
}

double dist(point a,point b){
    if(a.f==b.f) return INF; // 同种类,距离设为INF
    double x2=(a.x-b.x)*(a.x-b.x);
    double y2=(a.y-b.y)*(a.y-b.y);
    return sqrt(x2+y2);
}

double minDist(int l,int r){
    if(l==r) return INF;
    if(l+1==r) return dist(P[l],P[r]);
    int m=(l+r)>>1;
    double ans=min(minDist(l,m),minDist(m+1,r)); // 分治左右平面的最短距离
    // 寻找中间距离
    int cnt=0;
    for(int i=l;i<=r;i++){
        if(abs(P[m].x-P[i].x)<=ans) T[++cnt]=P[i]; // 排除离平面分界线过远的点
    }
    sort(T+1,T+1+cnt,comp2);
    for(int i=1;i<=cnt;i++){
        for(int j=i+1;j<=cnt;j++){
            if(T[j].y-T[i].y>=ans) break; // 根据y坐标剪枝
            ans=min(ans,dist(T[i],T[j]));
        }
    }
    
    return ans;
}

int main(){
    int t;
    cin>>t;
    while(t--){
        int n;
        cin>>n;
        int i;
        for(i=1;i<=n;i++){
            cin>>P[i].x>>P[i].y;
            P[i].f=0;
        }
        for(i=n+1;i<=n<<1;i++){
            cin>>P[i].x>>P[i].y;
            P[i].f=1;
        }
        sort(P+1,P+1+(n<<1),comp1);
        printf("%0.3lf\n", minDist(1,n<<1));
    }
}

题目3:翻转卡片

n张卡片排成一行,每张卡片的正面和背面均有数字,一开始所有卡片正面朝上。有一种操作是将相邻卡片交换位置,并且两张卡片翻面。求这种操作的最少次数,使得卡片所显示的、排成一行的数字能够实现非严格递增排序。如果不存在这个最少次数,则返回-1。我总感觉像是冒泡排序,但死活没想出来,希望AC的朋友指点下本弱鸡,之后会更新AC答案的,感谢~
输入样例:
第一行是卡片数(n<=18)
第二行是卡片正面数字的数组
第三行是卡片背面数字的数组
例如:
3
1 3 2
3 2 1
输出样例:
1 (操作的最少次数,不能实现则为-1)

题目4:两个栈模拟队列

《剑指offer》里的第九题:https://leetcode-cn.com/problems/yong-liang-ge-zhan-shi-xian-dui-lie-lcof/,大体思路是两个栈分别扮演队列的队头和队尾,入队操作在队尾栈里,出队和检查队头在队头栈中,中途要维护队尾栈向队头栈的元素转移。
输入样例:
第一行是操作数N
之后有N行操作,有“add”,“peek”和“poll”三种操作
输出样例:
“peek”操作需输出队头元素
#include <stdio.h>
#include <iostream>
#include <stack>
using namespace std;
//int add_pos=0;

void add(stack<int>& stack1, stack<int>& stack2, int i){
	stack1.push(i);
}

void peek(stack<int>& stack1, stack<int>& stack2){
	if(stack2.empty()){
		if(stack1.empty()) return;
		while(!stack1.empty()){
			int tmp=stack1.top();
			stack1.pop();
			stack2.push(tmp);
		}
	}

	printf("%d\n", stack2.top());
}

void poll(stack<int>& stack1, stack<int>& stack2){
	if(stack2.empty()){
		if(stack1.empty()) return;
		while(!stack1.empty()){
			int tmp=stack1.top();
			stack1.pop();
			stack2.push(tmp);
		}
	}

	stack2.pop();	
}

int main(){
	stack<int> stack1,stack2;
	int N;
	scanf("%d", &N);
	for(int i=0;i<N;i++){
		string s;
		cin>>s;
		if(s=="add"){
			int i;
			scanf("%d", &i);
			add(stack1,stack2,i);
		}
		else if(s=="peek"){
			peek(stack1,stack2);
		}
		else if(s=="poll"){
			poll(stack1,stack2);
		}
	}

	return 0;
}

题目5:满二叉树的祖先节点

有一个无穷高的满二叉树,层次遍历从小到大编号,根结点从1开始,第二行是“2 3”,第三行是“4 5 6 7”……对于编号为n的结点,求其高度为k的祖先节点,若不存在则返回-1.
思路:满二叉树的层级编号是一个很经典的问题,编号为n的节点的父结点编号是n>>1,祖父节点编号是n>>2……以此类推。另外,树高为k的节点编号范围是[2^(k-1), 2^k),所以编号为n的节点的树高为⌊log2(n)⌋+1,进而当k>=⌊log2(n)⌋+1时,不存在该祖先节点。
输入样例:
第一行是检索数Q
下面Q行的检索中,每一行包含节点编号i和祖先节点高度k
例如:
4
10 1
10 2
10 3
10 4
输出样例:
每行检索对应的祖先节点编号
例如:
1
2
5
-1
#include <stdio.h>
using namespace std;

int calHeight(long long x){
	int height=1;
	long long tmp=1;
	while(1){
		if(x>=tmp && x<(tmp<<1)) break;
		height++;
		tmp=tmp<<1;
	}
	return height;
}

int main(){
	int Q;
	scanf("%d",&Q);
	for(int i=0;i<Q;i++){
		long long x;
		int k;
		scanf("%lld %d", &x, &k);

		int height=calHeight(x);
		if(k>=height) printf("%d\n", -1);
		else{
			long long ret=x>>(height-k);
			printf("%lld\n", ret);
		}
		
	}
}
另外,弱鸡的我求教下各位C++的格式输入/输出到底怎样规范操作?我经常将scanf和cin混用,也经常碰到一些输入/输出样例处理的bug,各位收藏过整理这些输入/输出的网站吗?谢谢

#腾讯笔试##腾讯##笔经##实习#
全部评论
对,c++的输入输出有时候真的头疼...同求
点赞 回复 分享
发布于 2020-04-26 23:45
感觉只用cin就没问题呀第五题计算高度我用的log,复杂度o(1)赞一下楼主的位运算
点赞 回复 分享
发布于 2020-04-27 00:09
队列直接调用queue更快一点哈哈哈
点赞 回复 分享
发布于 2020-04-27 09:26
大佬直接指针实现,着实牛逼
点赞 回复 分享
发布于 2020-04-29 09:02
大佬第三题都没搞定,还好我看了一眼就放弃了😂
点赞 回复 分享
发布于 2020-04-29 12:13
我觉得如果是做题的话为了降低心理压力直接 #include <cstdio> 也挺好用的,可以当成C语言直接用printf和scanf。有文档: https://en.cppreference.com/w/cpp/header/cstdio
点赞 回复 分享
发布于 2020-04-29 22:58
!??
点赞 回复 分享
发布于 2020-08-21 18:02

相关推荐

点赞 评论 收藏
分享
点赞 评论 收藏
分享
8 45 评论
分享
牛客网
牛客企业服务