2017年清华软院保研机试第2题:被遗漏的数字

被遗漏的数字(30 分)

Problem Description

小明写了一个函数,将1-n 的数随机排列组成一个字符串,每个数字使用且仅使用一次。但是小明在写的时候粗心了,导致生成的字符串丢失了其中一个数字。帮助小明找出这个数字

Input

测试输入包含若干测试用例,每个测试用例占两行,第一行是n(2<=n<=200),第二行是一个字符串。

Output

对每个测试用例输出1 行,输出缺漏的数字

Sample Input

5
1234
20
12345678910111314151617181920

Sample Output

5
12

--------------------------------------------------------------------------------

思路

统计1~n所有数码('0'~'9')中应该出现的次数,与实际字符串中出现的数码次数相减,得到被遗漏的数字的组成数码。如果组成数码中有0,需要特判。否则将数码组合成各种<=n的排列,统计各个排列在字符串中出现的次数。若一个排列在字符串中出现的次数小于其应该出现的次数,则被遗漏的数字就是这个排列。

一个未解决的问题是例如下面的输入:

21

1234567891011131415161718192021

既可以认为答案是12,也可以认为答案是21

--------------------------------------------------------------------------------

代码

主程序

#include
#include
#include
#include

void itos(int n, char *c_n)
{
	int i = 0, j =0;
	while (n > 0)
	{
		c_n[i++] = n%10 + '0';
		n /= 10;
	}
	for (j=0; j select, int n)
{
	if (select.front() >= 100)			// 三位数只要没有出现就是“被遗漏的数字”
	{
		for (std::vector::iterator it = select.begin(); it != select.end(); it++)
		{
			if (!cnt_times(str, *it))
			{
				return *it;
			}
		}
	}
	else								// 两位数要计算在字符串中应该出现的次数,出现次数小于它才是“被遗漏的数字”
	{
		for (std::vector::iterator it = select.begin(); it != select.end(); it++)
		{
			if (cnt_times(str, *it) < expect(*it, n))
			{
				return *it;
			}
		}
	}
	return select.front();				// 对于未决情况,任意输出,不妨输出第一个组合
}


int main()
{
#ifndef ONLINE_JUDGE
	freopen("thuSE16_02.txt", "r", stdin);
#endif
	int n, i, j, a, str_len, len, ans1, ans2, ans3, ans4, ans5, ans6, myans;
	char str[600] = {};
	int cnt[10] = {};
	std::vector ans;
	std::vector select;				// 备选数字集合
	std::vector::iterator it;
	while (scanf("%d", &n) != EOF)
	{
		memset(cnt, 0, sizeof(cnt));
		ans.clear();
		for (i=1; i<=n; i++)
		{
			a = i;
			while (a > 0)
			{
				cnt[a%10] ++;
				a /= 10;
			}
		}
		scanf("%s", str);
		str_len = strlen(str);
		for (i=0; i n)
			{
				printf("%d\n", ans2);
			}
			else if (ans2 > n)
			{
				printf("%d\n", ans1);
			}
			else
			{
				select.clear();
				select.push_back(ans1);
				select.push_back(ans2);
				printf("%d\n", pick(str, select, n));
			}
		}
		else if (len == 3)
		{
			ans1 = 100*ans.at(0) + 10*ans.at(1) + ans.at(2);
			ans2 = 100*ans.at(0) + 10*ans.at(2) + ans.at(1);
			ans3 = 100*ans.at(1) + 10*ans.at(0) + ans.at(2);
			ans4 = 100*ans.at(1) + 10*ans.at(2) + ans.at(0);
			ans5 = 100*ans.at(2) + 10*ans.at(0) + ans.at(1);
			ans6 = 100*ans.at(2) + 10*ans.at(1) + ans.at(0);
			if (ans.at(0) == 0 && ans.at(1) == 0)
			{
				printf("%d\n", ans6);
			}
			else if (ans.at(0) == ans.at(1) == ans.at(2))
			{
				printf("%d\n", ans1);
			}
			else if (ans.at(0) == 0)
			{
				select.clear();
				select.push_back(ans3);
				select.push_back(ans4);
				select.push_back(ans5);
				select.push_back(ans6);
				myans = select.back();
				while (myans > n)
				{
					select.pop_back();
					myans = select.back();
				}
				printf("%d\n", pick(str, select, n));
			}
			else
			{
				select.clear();
				select.push_back(ans1);
				select.push_back(ans2);
				select.push_back(ans3);
				select.push_back(ans4);
				select.push_back(ans5);
				select.push_back(ans6);
				myans = select.back();
				while (myans > n)
				{
					select.pop_back();
					myans = select.back();
				}
				printf("%d\n", pick(str, select, n));
			}
		}
	}
	return 0;
}

测试用例生成程序

#include
#include
#include

int a[205] = {};

int main()
{
	int n = 150, i, r1, r2, t = 100;		// n: total number
	for (i=0; i

 

你可能感兴趣的:(保研机试,清华大学软件学院保研机试经验)