关于一道面试题的分析与解答

给大家分享一下我第一次参加面试时的一个题目:

问题:对于任意一个正整数 N,按以下操作把它转化为一个单一数字(大于 0 小于 10的数):

把 N 的各位上数字相加,若得到的结果不是一个单一数字,就把结果的各位上的数字相加,

若得到的结果还不是一个一位数,就还把结果的各位上的数字相加,

……

直到结果为一个单一数字为止。

如:2345

2+3+4+5=14

1+4=5 结果就为 5。

请写出一个方法,当传入任意一个正整数时,返回它按以上操作所得到的单一数字。

 

分析:如何算出各位上的数字是关键,对于任意一个正整数 N 我们让它对 10 取模,就可以得它的个位数字,由此我们不难想出如下解法:

个位数字:n0=N%10

十位数字:n1=N/10%10

百位数字:n2=N/100%10

……

k 位数字:nk=N/10k%10

把 N1=n0+n1+n2+...+nk 的结果再按上述操作,然后再按上述操作,直到得到一个单一数字为止。由此我们有以下算法:

算法 1:递归算法:

1 public static int getSingleNum1(int N) {
2 int result = 0; // 保存返回结果
3  
4 /*
5 * 每次循环让N模10,即得到相对应位上的数字, 用result来保存这个模10结果,
6 * 然后让N除10 直到N除10的结果等于0,停止循环
7 */
8 while (N > 0) {
9 result += (N % 10);
10 N /= 10;
11 }
12
13 /*
14 * 若result小于10(即已经为单一数字)直接返回
15 * 若大于等于10则对其进行同样的操作(递归),直到返回的结果小于10
16 */
17 if (result < 10) {
18 return result;
19 } else {
20 return getSingleNum1(result);
21 }
22 }

 

算法 2:对于一个递归算法我们可以对其进行消除递归:

1 public static int getSingleNum2(int N) {
2 int result = N; // 保存返回结果
3  
4 /*
5 * 外层循环:每次把内层循环得到的结果赋值给N, 直到N的结果小于10为止
6 * 内层循环:每次循环让N模10,即得到相对应位上的数字,
7 * 用result来保存这个模10结果,然后让N除10 直到N除10的结果等于0,停止循环
8 */
9 while ((N = result) >= 10) {
10 result = 0;
11 while (N > 0) {
12 result += (N % 10);
13 N /= 10;
14 }
15 }
16 return result; // 返回结果
17 }

 

面试时我写的是第二种写法,但第二天早上我一觉醒来,又想了想这个面试的题目,越想越不对,越想越发现这个题目有些蹊跷

数 2345 按题目所给的算法:

2+3+4+5=14

1+4=5

结果为 5

而 2345%9=5

 

再找一个数:67342

6+7+3+4+2=22

2+2=4

结果为 4

而 67342%9=4

 

我又找了一些数试试发现果然很蹊跷:

那就是把这些数直接模 9 就可以得到想要的结果(结果为 0 时为 9)。

要真是这样的话,那该怎么证明呢?经过我的认真分析和思考便有了以下的分析和证明:

设 N0 各位上的数字由低位到高位分别为 n0,1,n0,2,n0,3,……,n0,k0

则 N0=n0,1+n0,2*10+n0,3*102+...+n0,k0*10k0

令 N1=n0,1+n0,2+n0,3+...+n0,k0

设 N1 各位上的数字由低位到高位分别为 n1,1,n1,2,n1,3,……,n1,k1

则 N1=n1,1+n1,2*10+n1,3*102+...+n1,k1*10k1

令 N2=n1,1+n1,2+n1,3+...+n1,k1

……

令 Nm=n(m-1),1+n(m-1), 2+n(m-1),3+...+n(m-1),k(m-1)

设 Nm 各位上的数字由低位到高位分别为 nm,1,nm,2,nm,3,……,nm,km

则 Nm=nm,1+nm,2* 10+nm,3*102+...+nm,km10km

令 Nm+1=nm,1+nm,2+nm,3+...+nm,km

直到 Nm+1 为一个单一数字

 

以下证明 Nm+1=N0%9

 

由以上分析可知:

N0

=n0,1

=n0,1

+n0,2* 10

+n0,2

+n0,3* 102

+n0,3

+...

+...

+n0,k0* 10k0

+n0,k0

 

 

+n0,2* (10-1)

+n0,3* (102-1)

+...

+n0,k0* (10k0-1)

 

=N1

 

 

 

 

 

 

+n0,2* (10-1)

+n0,3* (102-1)

+...

+n0,k0* (10k0-1)

 

=n1,1

+n1,2* 10

+n1,3* 102

+...

+n1,k1* 10k1

 

 

=n1,1

+n0,2* (10-1)

+n1,2

+n0,3* (102-1)

+n1,3

+...

+...

+n0,k0* (10k0-1)

+n1, k1

 

 

+n1,2* (10-1)

+n1,3* (102-1)

+...

+n1,k1* (10k1-1)

 

 

+n0,2* (10-1)

+n0,3* (102-1)

+...

+n0,k0* (10k0-1)

 

……

 

 

 

 

 

=Nm+1

 

+nm,2* (10-1)

 

 +nm,3* (102-1)

 

 +.. .

 

 +nm,k*(10km-1)

 

 

……

 

 

 

 

 

+n1,2* (10-1)

+n1,3* (102-1)

+.. .

+n1,k1* (10k1-1)

 

 

+n0,2* (10-1)

+n0,3* (102-1)

+...

+n0,k0* (10k0-1)

由于 10m-1在 m 为正整数时能整除 9,所以有:

Nm+1=N0%9

由此我们可以得出:

算法 3

1 public static int getSingleNum3(int N) {
2 return N % 9 == 0 ? 9 : N % 9;
3 }

 

如此一条语句就解决了问题!只是我当时在面试时没能想到这样做。如果是你,你会想到这种算法吗?

posted @ 2011-03-08 00:19  STF  阅读(13955)  评论(21编辑  收藏  举报