找回密码
 欢迎注册
楼主: fallening

[讨论] 发现一很有趣的题目,讨论一下吧

[复制链接]
发表于 2008-9-9 15:24:44 | 显示全部楼层
第一种是最笨的方法:把每一位从0到9都尝试过,然后再次统计这个数组得到另外一个结果,如果两个数组相等就表明成功,否则就失败。但是这个方法算法太耗时间,不推荐,如果面试的时候能够讲出这种方法,估计面试官还是会给一点分的! 第二种:因为总共出现的总次数为10,所以我们可以很有效的利用这个属性,进行一次排列,为了分析简单,我们从最大开始: 9+1+n*0(n=8),对这个数据进行整理得8100000001,再次对这个数组进行统计分析得7200000010,与刚得到的数组不一样,错误,转到下一个排列 8+2+n*0(n=8),对这个数据进行整理得8010000010,再次对这个数组进行统计分析得7200000010,与刚得到的数组不一样,错误,转到下一个排列 8+1+1+n*0(n=7),对这个数据进行整理得7200000010,再次对这个数组进行统计分析得7110000100,与刚得到的数组不一样,错误,转到下一个排列 .... 总共的排列数: 9 1 0 0 0 0 0 0 0 0 8 2 0 0 0 0 0 0 0 0 8 1 1 0 0 0 0 0 0 0 7 3 0 0 0 0 0 0 0 0 7 2 1 0 0 0 0 0 0 0 7 1 1 1 0 0 0 0 0 0 6 4 0 0 0 0 0 0 0 0 6 3 1 0 0 0 0 0 0 0 6 2 2 0 0 0 0 0 0 0 6 2 1 1 0 0 0 0 0 0 6 1 1 1 1 0 0 0 0 0 5 5 0 0 0 0 0 0 0 0 5 4 1 0 0 0 0 0 0 0 5 3 2 0 0 0 0 0 0 0 5 3 1 1 0 0 0 0 0 0 5 2 2 1 0 0 0 0 0 0 5 2 1 1 1 0 0 0 0 0 5 1 1 1 1 1 0 0 0 0 4 4 2 0 0 0 0 0 0 0 4 4 1 1 0 0 0 0 0 0 4 3 3 0 0 0 0 0 0 0 4 3 2 1 0 0 0 0 0 0 4 3 1 1 1 0 0 0 0 0 4 2 2 2 0 0 0 0 0 0 4 2 2 1 1 0 0 0 0 0 4 2 1 1 1 1 0 0 0 0 4 1 1 1 1 1 1 0 0 0 3 3 3 1 0 0 0 0 0 0 3 3 2 2 0 0 0 0 0 0 3 3 2 1 1 0 0 0 0 0 3 3 1 1 1 1 0 0 0 0 3 2 2 2 1 0 0 0 0 0 3 2 2 1 1 1 0 0 0 0 3 2 1 1 1 1 1 0 0 0 3 1 1 1 1 1 1 1 0 0 2 2 2 2 2 0 0 0 0 0 2 2 2 2 1 1 0 0 0 0 2 2 2 1 1 1 1 0 0 0 2 2 1 1 1 1 1 1 0 0 2 1 1 1 1 1 1 1 1 0 1 1 1 1 1 1 1 1 1 1 也就是说,对这个数据无论进行过多少次统计,它的值都还是等于原值的排列,才是正确的排列 算法如下:(没有注释及缩进的算法,见笑了*^_^*) (且这个程序必须假定A数组为初始值0增量1的等差数列)
  1. C/C++ code
  2. #include <iostream>
  3. using namespace std;
  4. const int N = 10;
  5. int source[N];
  6. int dest[N] = {0};
  7. int dest2[N] = {0};
  8. void init()
  9. {
  10. for(int i=0; i<N; i++)
  11. {
  12. source[i] = i;
  13. }
  14. }
  15. void display(int target[])
  16. {
  17. for(int i=0; i<N; i++)
  18. {
  19. printf("%4d", target[i]);
  20. }
  21. cout << endl;
  22. }
  23. /*
  24. 从src的数据统计出现的次数并存入dest中
  25. Create by Denny, Email: [email]silitex@yeah.net[/email]
  26. */
  27. void count(int *dest, int *src)
  28. {
  29. int i;
  30. for (i = 0; i < N; i++) // dest清0
  31. dest[i] = 0;
  32. for (i = 0; i < N; i++) // 整理当前的数值到正确的位置上
  33. dest[src[i]]++;
  34. }
  35. void main()
  36. {
  37. init();
  38. display(source); // 原始数组
  39. int tmp[N] = {N-1}; // 默认给第一个赋值为N-1
  40. int posi = 0;
  41. while (posi >= 0)
  42. {
  43. int i = 0;
  44. int leave = N;
  45. int min = tmp[0];
  46. for (; i <= posi; i++)
  47. {
  48. leave -= tmp[i];
  49. if (tmp[i] < min)
  50. min = tmp[i];
  51. }
  52. for (; i < N; i++)
  53. tmp[i] = 0;
  54. while (leave > 0)
  55. {
  56. if (min > leave)
  57. min = leave;
  58. tmp[++posi] = min;
  59. leave -= min;
  60. }
  61. count(dest, tmp); // 初步统计,得到一个正确的数值
  62. count(dest2, dest); // 再次进行统计
  63. for (i = 0; i < N; i++) // 核对结果
  64. if (dest2[i] != dest[i])
  65. break;
  66. if (i >= N) // 正确结果,显示答案
  67. display(dest);
  68. while (--tmp[posi] == 0)
  69. posi--;
  70. }
  71. }
复制代码
得到10位数的答案有且仅有一个: 6 2 1 0 0 0 1 0 0 0 9位数答案(只有一个): 5 2 1 0 0 1 0 0 0 8位数答案(只有一个): 4 2 1 0 1 0 0 0 7位数答案(只有一个): 3 2 1 1 0 0 0 6位数无解 5位数答案(只有一个): 2 1 2 0 0 4位数答案: 2 0 2 0 1 2 1 0 3位数无解 2位数无解 1位数无解 11位数答案(只有一个): 7 2 1 0 0 0 0 1 0 0 0 12位数答案(只有一个): 8 2 1 0 0 0 0 0 1 0 0 0 13位数答案(只有一个): 9 2 1 0 0 0 0 0 0 1 0 0 0 14位数答案(只有一个): 10 2 1 0 0 0 0 0 0 0 1 0 0 0 15位数答案(只有一个): 11 2 1 0 0 0 0 0 0 0 0 1 0 0 0 16位数答案(只有一个): 12 2 1 0 0 0 0 0 0 0 0 0 1 0 0 0
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2017-1-21 12:14:34 | 显示全部楼层
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2017-1-21 12:15:49 | 显示全部楼层
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2017-1-21 12:16:41 | 显示全部楼层
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
您需要登录后才可以回帖 登录 | 欢迎注册

本版积分规则

小黑屋|手机版|数学研发网 ( 苏ICP备07505100号 )

GMT+8, 2025-1-22 23:38 , Processed in 0.022055 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表