9月15日腾讯 C++游戏客户端 笔试分享

前排先说一下,根据个人经验,笔试基本上只要能过线就行,对后续流程影响真的不大。

我已经不知道有多少家公司,笔试题全A,然后简历被刷,或是一面后被刷了。

我腾讯的流程其实已经结束了。

所以诸位不用对笔试成绩过分看重。

奇怪了,我发布时代码选的是C++,发出来变成plain text了

腾子这次笔试题难度还是不太大的,比美团难一些,不过肯定比米哈游网易雷火这种笔试简单的多。

1、对k个链表进行排序。

思路:初看以为是k个升序链表(样例是升序),仔细一看题目描述链表是乱序的,所以直接摧毁原始链表,提取所有数值并排序,最后用排序好的数值重新建一个链表即可,没必要在链表上进行操作。

class Solution {
public:
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     * 返回一个指向链表头部的指针。
     * @param a ListNode类vector 指向这些数链的开头
     * @return ListNode类
     */
    ListNode* solve(vector<ListNode*>& a) {
        vector<int> nums;

        for (auto& head : a)
        {
            while (head != nullptr)
            {
                nums.emplace_back(head->val);
                auto node_next = head->next;
                delete(head);
                head = node_next;
            }
        }

        sort(nums.begin(), nums.end(), [](int a, int b) {return a < b; });
        ListNode* head = new ListNode(nums[0]);
        ListNode* tmp_node = head;
        for (int i = 1; i < nums.size(); i++)
        {
            tmp_node->next = new ListNode(nums[i]);
            tmp_node = tmp_node->next;
        }

        return head;
    }
};

2、对一个正整数数组中的数字执行k次操作,求k次操作后数组和的最小值。对数字的操作如下:

如果x是偶数,则操作后x = 2*x + 1

如果x是奇数,则操作后x = 2*x

思路:简单贪心即可,每次操作最小的那个数字即可。用优先队列更好,但是忘了如何规定优先队列升序还是降序,所以用了map

#include<iostream>
#include<map>
using namespace std;

int main()
{
	int n, k;
	cin >> n >> k;

	long long sum = 0;
	map<long long, int> nums;
	for (int i = 0; i < n; i++)
	{
		long long num;
		cin >> num;
		nums[num]++;
		sum += num;
	}

	for (int i = 0; i < k; i++)
	{
		auto it = nums.begin();
		long long num = it->first;
		sum -= num;

		if (num % 2 == 0)
			num = num * 2 + 1;
		else
			num = num * 2;

		it->second--;
		if (it->second == 0)nums.erase(it);
		nums[num]++;
		sum += num;
	}

	cout << sum << endl;
	return 0;
}

3、有n辆赛车,以及所有赛车的当前位置p,速度v,假设赛车均做匀速直线运动。问你t时刻后,有多少赛车的名次发生了改变?

思路:初始输入是有序的,只用对t时刻后的位置重新排序重新计算名次即可。

#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;

struct car
{
	int pos = 0;
	int rank_now = 0;
	int rank_new = 0;
};

int main()
{
	int n, t;
	cin >> n >> t;

	vector<car> cars(n);
	for (int i = 0; i < n; i++)
	{
		cin >> cars[n - 1 - i].pos;
	}

	cars[0].rank_now = 1;
	for (int i = 1; i < n; i++)
	{
		if (cars[i].pos == cars[i - 1].pos)
			cars[i].rank_now = cars[i - 1].rank_now;
		else
			cars[i].rank_now = i + 1;
	}

	for (int i = 0; i < n; i++)
	{
		int v;
		cin >> v;
		cars[n - 1 - i].pos += v * t;
	}

	sort(cars.begin(), cars.end(), [](car a, car b) {return a.pos > b.pos; });

	int count = 0;
	cars[0].rank_new = 1;
	if (cars[0].rank_now > cars[0].rank_new)count++;
	for (int i = 1; i < n; i++)
	{
		if (cars[i].pos == cars[i - 1].pos)
			cars[i].rank_new = cars[i - 1].rank_new;
		else
			cars[i].rank_new = i + 1;

		if (cars[i].rank_now > cars[i].rank_new)
			count++;
	}

	cout << count << endl;
	return 0;
}

4、对于一个字符串,将其首字符放在末尾,这个操作称为旋转字符串("abcdef" -> "bcdefa") 。对于两个字符串,如果其中一个字符串可以通过一次或多次旋转变成另一个字符串,则这两个字符串“互旋”

给你T组数据,问你每组数据中是否存在两个字符串“互旋”?

思路:观察数据量,字符串数量很多,字符串长度不长,如果两两比较肯定超时,应当用哈希表匹配。

#include<iostream>
#include<string>
#include<unordered_set>
using namespace std;

int main()
{
	int T;
	cin >> T;

	for (int i = 0; i < T; i++)
	{
		int n;
		cin >> n;

		bool isFind = false;
		unordered_set<string> strs;
		for (int j = 0; j < n; j++)
		{
			string str;
			cin >> str;

			if (isFind)continue;

			for (int k = 0; k < str.length(); k++)
			{
				std::rotate(str.begin(), str.begin() + str.length() - 1, str.end());
				if (strs.find(str) != strs.end())
				{
					isFind = true;
					break;
				}
			}

			if (!isFind)
				strs.insert(str);
		}

		if (isFind)
			cout << "YES" << endl;
		else
			cout << "NO" << endl;
	}

	return 0;
}

5、有n个数字,数字可能为0可能为1,告诉你每个数字的坐标值。你可以将k个1变为0。

你每次操作可以让一个0的位置+1或是-1,。

问你最少需要几次操作使得所有0之间没有1。(如果0和1重合,视为中间有1)

思路:对于所有1

计算将1左侧所有0移动到1右侧的操作数(表示将所有0移动到这个1右侧需要的代价lcost)

计算将1右侧所有0移动到1左侧的操作数(表示将所有0移动到这个1左侧需要的代价rcost)

在所有数字左侧添加一个1,其左代价lcost = 0;在所有数字右侧添加一个1,其右代价rcost = 0;

那么,对于两个1,左侧的1的lcost和右侧的1的rcost加起来,即是将所有0移动到这两个1之间所需要的操作数。

遍历所有1,求lcost[i] 与rcost[i + k + 1](因为可以将中间k个1变为0,所以右侧选i + k + 1)的最小值即可

#include<iostream>
#include<vector>
using namespace std;

int main()
{
	int n, k;
	cin >> n >> k;

	vector<long long> pos(n);
	vector<int> color(n);
	vector<int> blue_idx;
	for (int i = 0; i < n; i++)
	{
		cin >> pos[i];
	}
	for (int i = 0; i < n; i++)
	{
		cin >> color[i];
		if (color[i] == 1)
		{
			blue_idx.emplace_back(i);
		}
	}

	int num_blue = blue_idx.size();
	vector<long long> lcost(num_blue + 2, 0);
	vector<long long> rcost(num_blue + 2, 0);
	
	int lnum = 0;
	long long lpos = 0;
	long long lidx = -1;
	for (int i = 0; i < num_blue; i++)
	{
		long long pos_now = pos[blue_idx[i]];
		lcost[i + 1] = lcost[i] + (pos_now - lpos) * lnum;
		for (int p = lidx + 1; p < blue_idx[i]; p++)
		{
			lcost[i + 1] += pos_now - pos[p] + 1;
			lnum++;
		}

		lpos = pos_now;
		lidx = blue_idx[i];
	}

	int rnum = 0;
	long long rpos = pos[n - 1];
	long long ridx = n;
	for (int i = num_blue; i > 0; i--)
	{
		long long pos_now = pos[blue_idx[i - 1]];
		rcost[i] = rcost[i + 1] + (rpos - pos_now) * rnum;
		for (int p = ridx - 1; p > blue_idx[i - 1]; p--)
		{
			rcost[i] += pos[p] - pos_now + 1;
			rnum++;
		}

		rpos = pos_now;
		ridx = blue_idx[i - 1];
	}

	long long cost_min = lcost[num_blue];
	for (int i = 0, j = k + 1; j <= num_blue + 1; i++, j++)
	{
		long long cost_now = lcost[i] + rcost[j];
		if (cost_now < cost_min)
			cost_min = cost_now;
		//if (cost_now == 0)
		//{
		//	int p = j - 1;
		//	while (p > i && lcost[i] + rcost[p] == 0)p--;
		//	if (cost_min > p - i)
		//		cost_min = p - i;
		//}
		//else
		//{
		//	int p = j - 1;
		//	while (p > i && lcost[i] + rcost[p] == cost_now)p--;
		//	if (cost_min > cost_now + p - i)
		//		cost_min = cost_now + p - i;
		//}
	}
	cout << cost_min << endl;
	return 0;
}

全部评论
前排捕捉文佬,太强了😭
1 回复
分享
发布于 2023-09-15 23:01 浙江
想问大佬第五题一般属于啥算法类型,刷少了这部分想不到
1 回复
分享
发布于 2023-09-16 18:11 上海
联想
校招火热招聘中
官网直投
这题解看的津津有味😆
点赞 回复
分享
发布于 2023-09-15 23:24 上海
第五题做了四十分钟,放弃了
点赞 回复
分享
发布于 2023-09-15 23:29 河南
我ak了,但之前已经一面挂了
点赞 回复
分享
发布于 2023-09-15 23:45 云南
大佬题解好牛……请问大佬笔试一般多少分能过线呀?
点赞 回复
分享
发布于 2023-09-16 18:50 广东
看起来解题不错呀,阿里盒马客户端P5岗位可以考虑下,二维码直达:
点赞 回复
分享
发布于 2023-09-22 10:40 浙江
关注了 大佬有没有兴趣有偿一对一辅导一下代码能力呀
点赞 回复
分享
发布于 2023-12-19 11:20 浙江
除了代码之外有考图形学,操作系统之类的题吗大佬
点赞 回复
分享
发布于 04-23 10:36 英国

相关推荐

timeLine:4.11&nbsp;一面———————————————4.18&nbsp;二面———————————————4.22&nbsp;明天即将面临第三面,小牛客助我!———————————————4.23&nbsp;三面———————————————4.24&nbsp;HR面,小牛客助我!———————————————4.25&nbsp;云证+录用评估,许愿oc,小牛客助我!———————————————4.28&nbsp;offer———————————————还愿:一面:1.&nbsp;自我介绍2.&nbsp;项目中的难点是什么3.&nbsp;HashMap的底层实现是什么?HashMap什么时候扩容?HashMap负载因子为什么设定为0.75?设置成1会怎么样?HashMap的时间复杂度为多少?4.&nbsp;介绍一下TCP/IP四层体系结构,每层的作用是什么?5.&nbsp;三次握手和四次挥手?6.&nbsp;介绍一下Java里面的happens-before原则7.&nbsp;介绍一下Java可见性、原子性、有序性?8.&nbsp;Java中如何保证程序按照顺序执行?9.&nbsp;Java中写的程序是否会按照写的顺序执行?10.&nbsp;运行时数据区有哪些部分组成?哪些是线程共享的?哪些不是?11.&nbsp;公平锁和非公平锁的区别是什么?12.&nbsp;volitale的作用是什么?写过单例模式,单例模式中的双重检查锁定中,为什么要用volitale修饰instance?13.&nbsp;webSocket是怎么实现的?14.&nbsp;自己写过锁嘛?什么情况下会造成死锁?举个例子?15.&nbsp;Java的锁框架AQS是什么?手撕数组中重复的数据二面:1.&nbsp;狠狠拷打项目2.&nbsp;Java常见的权限修饰符有哪些?介绍一下3.&nbsp;内部类、静态内部类、匿名内部类的区别?4.&nbsp;线程池的作用是什么?5.&nbsp;客户端的线程池是怎么配置的?或者一般的线程池线程数是怎么选的?6.&nbsp;volatile的作用是什么?7.&nbsp;Java提供了原子操作的类,那这些原子操作的类和volatile有什么区别?8.&nbsp;如何实现一个线程安全的ArrayList?9.&nbsp;泛型擦除有了解吗?泛型中的T和?有什么区别10.&nbsp;C++泛型擦除和Java泛型擦除有什么区别?11.&nbsp;安卓的四大组件都有什么?12.&nbsp;安卓的生命周期?13.&nbsp;设计模式知道多少?介绍一下14.&nbsp;静态和单例怎么选?手撕层序遍历字数不够,见下
点赞 评论 收藏
转发
16 43 评论
分享
牛客网
牛客企业服务