腾讯2017暑期实习生编程题(三题)

总的来说,作为暑期实习生的题目,三题都不难,仔细思考都能顺利做出来

PS:我喜欢漂亮点的代码风格O(∩_∩)O

对于A题,求个逆序,再求最长公共子序列就可以了,这里回头还可以复习一下最长公共子串怎么求,记得上次省赛线段树+最长公共子串那题挂了不少人。

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

const int MAXLEN = 1010;
int temp[MAXLEN][MAXLEN];

int getRemoveNumber(const string& res, int len)
{
	string str(res);
	reverse(str.begin(), str.end());
	for (int i = 0; i < len; ++i)
	{
		for (int j = 0; j < len; ++j)
		{
			if (res[i] == str[j])
				temp[i + 1][j + 1] = temp[i][j] + 1;
			else temp[i + 1][j + 1] = max(temp[i + 1][j], temp[i][j + 1]);
		}
	}
	return len - temp[len][len];
}
int main()
{
	string str;
	int ans;
	while (cin >> str)
	{
		ans = getRemoveNumber(str, str.length());
		cout << ans << endl;
	}
	return 0;
}

对于B题:设置两个下标,从后往前找就可以了,不难但容易出错,而且加上边界情况容易混乱

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

void solve(string& str, int len)
{
	int i = len - 1, j = len - 1;
	char temp;
	while (true)
	{
		if (i < 0)
		{
			return;
		}
		if (str[i] < 'a')
		{
			temp = str[i];
			for (int k = i + 1; k <= j; ++k)
			{
				str[k - 1] = str[k];
			}
			str[j] = temp;
			j--;
		}
		i--;
	}
}
int main()
{
	string str;
	while (cin >> str)
	{
		solve(str, str.length());
		cout << str << endl;
	}
	return 0;
}

对于C题:咋一看简单,细想却发现不少问题。首先对于A、B两个数,求它们的对数,有两种情况,一种是A==B,则公式为NUM(A)*(NUM(A)-1) / 2,另一种,A != B时,公式为NUM(A)*NUM(B)。然后对于最小差的对数,也分两种情况,一方面是含有相同的数字的情况,那么最小差肯定是0,假设A有nA个相同的,B有nB个相同的,则最小差是它们的总和。另一方面,不含有相同的数字,即N个数各不相同,这也好办,代码中我注释了,就不罗嗦了,当然这两个方面可以合在一起,但要注意比较,不要在遍历时重复计算两个相同的。。。最后在降复杂度上,可以发现可以着手的地方是计算每个数字出现的个数上,可以用map降为O(1),当然,这一步一开始就因该想到了( •̀ ω •́ )y。

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

const int MAX = 2147483647;
map<int, int>mmap;
int arr[100100];

int countNumber(int a, int b)
{
	if (a == b) return mmap[a] * ( mmap[a] - 1 ) / 2;
	else return mmap[a] * mmap[b];
}
int main()
{
	int N;
	while (cin >> N)
	{
		if (N == 1)
		{
			cin >> N; //随便读一个进来
			cout << "0 0" << endl;
			continue;
		}
		for (int i = 0; i < N; ++i)
		{
			cin >> arr[i];
			mmap[arr[i]]++;
		}
		sort(arr, arr + N);

		//若含有差值为0的,则看有多少个这样的数字,把它们的总对数加起来就是差值最小的对数
		int minNum1 = 0;
		for (auto it = mmap.begin(); it != mmap.end(); ++it)
		{
			if (it->second > 1)
			{
				minNum1 += ( it->second )*( it->second - 1 ) / 2;
			}
		}
		if (minNum1 != 0)
		{
			cout << minNum1 << " " << countNumber(arr[0], arr[N - 1]) << endl;
			mmap.clear();
			continue;
		}

		//下面是不含有重复数字的,取差最小的两个数和差最大的两个数
		int min1, min2, mmin = MAX;
		//int max1, max2, mmax = INT_MIN;  //23333,突然发现用不着。。。
		int minNum2 = 0, maxNum2 = 0;
		for (int i = 0; i < N - 1; i++)
		{
			//找最小
			if (arr[i + 1] - arr[i] < mmin)
			{
				//min1 = arr[i];     //同上,用不着。。。
				//min2 = arr[i + 1];
				mmin = arr[i + 1] - arr[i];
				minNum2 = countNumber(arr[i], arr[i + 1]);
			}
			else if (arr[i + 1] - arr[i] == mmin)
			{
				minNum2 += countNumber(arr[i], arr[i + 1]);
			}
		}
		cout << minNum2 << " " << countNumber(arr[N - 1], arr[0]) << endl;
		mmap.clear();
	}
	return 0;
}

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值