编程之美4.10的两道题。
第一题:找出符合条件的九位数,每位数互不相同(1~9的某个排列),满足高n位能被n整除。例如abcdefghi,高两位ab能被2整除,高三位abc能被3整除,以此类推。
一提到排列,很容易就想到递归+回溯,这个方法在面试中使用频率相当高。1~9这九个数字做一次全排列,符合条件的打印,不符合条件的返回。这里可以使用一些剪枝,例如第二高位只能是偶数,第四高位只能是偶数,第五高位只能被5整除,第六高位只能是偶数,第八高位只能是偶数,这样的剪枝大大提高了程序的性能。
<span style="font-size:14px;">void FinANumber(char a[], int len, int index)
{
// 第二个数必须是偶数
if (index == 1 && (a[index] - '0') % 2 != 0)
return;
// 第四个数必须是偶数
if (index == 3 && (a[index] - '0') % 2 != 0)
return;
// 第五个数必须是5的倍数
if (index == 4 && (a[index] - '0') % 5 != 0)
return;
// 第六个数必须是偶数
if (index == 5 && (a[index] - '0') % 2 != 0)
return;
// 第八个数必须是偶数
if (index == 7 && (a[index] - '0') % 2 != 0)
return;
if (index == len)
{
for (int i = 0; i < len; i++)
{
// 前n个数必须被n整除
int n = 0;
for (int j = 0; j <= i; j++)
n = n * 10 + a[j] - '0';
if (n % (i + 1) != 0)
return;
}
for (int i = 0; i < len; i++)
cout << a[i];
cout << endl;
return;
}
// 递归+回溯
for (int i = index; i < len; i++)
{
char tmp = a[index];
a[index] = a[i];
a[i] = tmp;
FinANumber(a, len, index + 1);
tmp = a[index];
a[index] = a[i];
a[i] = tmp;
}
}
int main()
{
char a[] = "123456789";
FinANumber(a, 9, 0);
system("pause");
return 0;
}</span>
第二题:abcde * f = edcba,找出这样的abcdef五个数。
穷举法。使用一个1~9的哈希表可以记录哪些数已经被使用,哪些数未被使用,从而判断是否符合题意。
<span style="font-size:14px;">// 回文游戏
void Palindrome()
{
bool isUsed[10];
for (int n = 10000; n < 100000; n++)
{
bool flag = true;
int copy = n;
memset(isUsed, 0, sizeof(isUsed));
int reverseNum = 0;
// 循环求n的反转数
for (int i = 0; i < 5; i++)
{
int tmp = copy % 10;
reverseNum = reverseNum * 10 + tmp;
copy /= 10;
if (isUsed[tmp])
{
flag = false;
break;
}
else
isUsed[tmp] = true;
}
if (flag && (reverseNum % n == 0))
{
int x = reverseNum / n;
if (x < 10 && !isUsed[x])
cout << n << "*" << x << "=" << reverseNum << endl;
}
}
}
int main()
{
Palindrome();
system("pause");
return 0;
}</span>
参考:
《编程之美》4.10