[讨论]时间换空间算法,散分讨论
有过这样一个问题,如何用最小的空间代价得到N个正整数中重复出现过大于N/2次的唯一的一个整数
(N为百万级,乱序,内存限制1M内,时间并没有充裕到允许使用外存...请在算法范畴内解决)
一个经典的做法是时间换空间,做整数分割存储。
建立一个int data[10][10]数组,如果某个数的第i位为j,那么data[i][j]加1.
例如整数123对应data[2][1], data[1][2], data[0][3]
因此,输入N个整数并更新data数组,代码如下:
int data[10][10] = {0}; int i, j, number, byte, byteValue; for (i = 0; i < N; ++i) { cin >> number; byte = 0; do{ byteValue = number % 10; data[byte++][byteValue]++; number /= 10; }while (number); }
public static void outSingle(int[] N) { int i = int.MinValue, c; do { c = -1; foreach (int n in N) { if (n == i && ++c != 0) break; } if (c == 0) Console.WriteLine(i); } while (++i != int.MinValue); }
[解决办法]
估计m最多为2。
所有的数异或一下,结果为落单的两个数的异或结果。
针对该结果的二进制表示中,为1的位的位置,
将原来所有的数分为两部分,
一部分该位为0,另一部分该位为1,
两部分分别视为m为1的情况处理。。。
[解决办法]
如果确定存在>N/2
public static int moreHalf(int[] N) { uint un; int i, l = (N.Length + 1) >> 1; int[] c = new int[32]; foreach (int n in N) { for (un = (uint)n, i = 0; un != 0; i++, un >>= 1) if ((un & 1) != 0) c[i]++; } for (un = 0, i = 31; i >= 0; i--) if (c[i] >= l) un |= 1U << i; return (int)un; }
[解决办法]
如果确定存在>N/2,应该是这样
public static int moreHalf(int[] N) { int v = 0, c = -1; foreach (int n in N) { if (c < 0) { v = n; c = 0; } else if (v == n) c++; else c--; } return v; }
[解决办法]
差不多这样子吧:
for (n=i=0;i<N;i++) if (n==0) x=a[i], n=1; else if (a[i]==x) n++; else n--;for (n=i=0;i<N;i++) if (a[i]==x) n++;if (n>N/2) printf("The answer is %d.\n",x);else printf("No answer.\n");
[解决办法]
所有数据输入完毕后,那么data中每行值最大的并且大于N/2的数合并起来,就是出现最多的那个数。
问题得到完美解决。
这个看不明白,不一定是这个数吧。
[解决办法]
路过,顶!