| 发表于:2007-03-02 19:57:0867楼 得分:0 |
经证明 sun3411(sun) 的思路确实可行正确. sun3411(sun) 的思想如下 : 原数据中少了两个数据, 则创建两个局部变量, 用来补充. 因为每个数据是唯一的, 所有原数组必定存在x个循环(即数组中, 根据索引取值, 再用值做索引, 循环), 而取走两个数据之后, 则至少有一个循环会断环, 如果找出断环的值, 即是原始数据. 按照 sun3411(sun) 的思路写出了一段程序. 但是结果令人遗憾, 当max值为10000以下没有问题, 当max为100000时, 计算一次需175578ms, 即175s, 那当1000000时, 估计得5个小时左右才能出结果. 仔细思考之后, 发现求平方和的算法, 时间复杂度为 o(n), 而sun3411(sun)的算法时间复杂度为 o(n^2) , 而本题的n却非常大, 导致此算法无法令人满意. 可能我的计算过程不是最优化的, 希望 sun3411(sun) 能补充更好的改进算法. ps. 计算了才肯放心 完整原程序如下. 类 find.searchtwonum2 package find; import java.util.random; /** * 从1到1000000中任意拿掉两个数,把剩下的999998个数顺序打乱,并且放入数组中。 * 要求只扫描一遍数组,把这两个数找出来。可以使用最到不超过5个局部变量, 不能用数组变量,并且不能改变原数组的值。 * * ps.1. 将所有平方和加起来, 依然低于64位整数的最大值. ps.2. 整型*整型, 注意强转成long型. 否则1e6 * 1e6 != 1e12 * * @author lhj * @time 2007-3-1 - 下午10:51:33 * */ public final class searchtwonum2 { public final int[] createdata(int max, int num1, int num2) { // 检查参数 if (num1 <= 0 ¦ ¦ num1 > max ¦ ¦ num2 <= 0 ¦ ¦ num2 > max ¦ ¦ num1 == num2) { throw new illegalargumentexception(); } if (num1 > num2) { int temp = num1; num1 = num2; num2 = temp; } // 赋值. int[] data = new int[max - 2]; for (int i = 1; i < num1; i++) { data[i - 1] = i; } for (int i = num1 + 1; i < num2; i++) { data[i - 2] = i; } for (int i = num2 + 1; i <= max; i++) { data[i - 3] = i; } // 打乱顺序 random rand = new random(); for (int i = 0; i < 100000; i++) { int x = rand.nextint(max - 2); int y = rand.nextint(max - 2); // system.out.println(x + " " + y); int temp = data[x]; data[x] = data[y]; data[y] = temp; } return data; } public final void find(int[] data) { final int length = data.length; int num1 = -1; int num2 = -1; for (int i = 0; i < length; i++) { int point = i; while (true) { // 3584169 1 -1 2,7 int current = data[point] - 1; if (current == length) { if (num1 == -1) { num1 = i; } break; } if (current == length + 1) { if (num2 == -1) { num2 = i; } break; } if (current == num1) { num1 = i; break; } if (current == num2) { num2 = i; break; } if (current == i) { break; } point = current; } } if (num1 > num2) { int temp = num1; num1 = num2; num2 = temp; } system.out.println( "result = " + (num1 + 1) + " " + (num2 + 1)); } public final void calc(int max, int num1, int num2) { system.out.println( "data = " + max + " " + num1 + " " + num2); long begin = system.currenttimemillis(); find(createdata(max, num1, num2)); long end = system.currenttimemillis(); system.out.println( "time = " + (end-begin)); system.out.println(); } public static void main(string[] args) { searchtwonum2 search = new searchtwonum2(); search.calc(10, 1, 2); search.calc(100, 51, 72); search.calc(1000, 500, 758); search.calc(1000, 500, 758); search.calc(10000, 514, 7574); search.calc(100000, 54321, 76543); search.calc(1000000, 11, 879517); search.calc(1000000, 12345, 67890); search.calc(1000000, 999998, 999999); search.calc(1000000, 999999, 1000000); search.calc(1000000, 1, 2); search.calc(1000000, 5, 7); search.calc(1000000, 12345, 67890); search.calc(1000000, 12545, 67290); search.calc(1000000, 11345, 67850); search.calc(1000000, 999998, 999999); search.calc(1000000, 999999, 1000000); } } /* begin : max=10 num1=1 num2=2 1 2 time = 0 begin : max=100 num1=51 num2=72 51 72 time = 0 begin : max=1000 num1=500 num2=758 500 758 time = 16 begin : max=1000 num1=500 num2=758 500 758 time = 0 begin : max=10000 num1=514 num2=7574 514 7574 time = 235 begin : max=100000 num1=54321 num2=76543 54321 76543 time = 175578 begin : max=1000000 num1=11 num2=879517 */ | | |
|