万里挑一 的算法 时间复杂度 o(n)
2009-07-27 09:29
225 查看
看了上面几个解决的,总是有些牵强,放上我写的,供大家参考。
题目:1-1000放在含有1001个元素的数组中,只有唯一的一个元素值重复,其它均只出现
一次。每个数组元素只能访问一次,设计一个算法,将它找出来;不用辅助存储空
间,能否设计一个算法实现?
时间还是o(N),无额外存储空间(说白了就是除了数组之外,不能额外开辟内存空间存储数组元素)。
//初始化
int N = 10;
int[] a = new int
;
Random rand = new Random();
//赋值
for (int i = 1; i < a.Length; i++)
int idx1 = 0;
int idx2 = 0;
//打乱顺序
for (int i = 0; i < a.Length * 10; i++)
//创建重复元素一个
idx1 = rand.Next(N);
while (a[idx1] == 0)
idx1 = rand.Next(N);
for (int i = 0; i < a.Length; i++)
//查找
unsafe
假设数组有10个元素,初始化时元素如下:
- a {Dimensions:[0x0000000a]} int[]
[0x00000000] 0x00000003 int
[0x00000001] 0x00000008 int
[0x00000002] 0x00000001 int
[0x00000003] 0x00000009 int
[0x00000004] 0x00000007 int
[0x00000005] 0x00000002 int
[0x00000006] 0x00000006 int
[0x00000007] 0x00000005 int
[0x00000008] 0x00000007 int
[0x00000009] 0x00000004 int
可以看出,相重的元素在a[4] 和a[8]处,也就是说数组循环到a[8]时才能发现相同的元素。
循环一次:
- a {Dimensions:[0x0000000a]} int[]
[0x00000000] 0x00000003 int
[0x00000001] 0x00000008 int
[0x00000002] 0x00000001 int
[0x00000003] 0x00030009 int
[0x00000004] 0x00000007 int
[0x00000005] 0x00000002 int
[0x00000006] 0x00000006 int
[0x00000007] 0x00000005 int
[0x00000008] 0x00000007 int
[0x00000009] 0x00000004 int
可以看出a[3]的值变了,变为了0x00030009.因为我将a[0]的低16位写到了a[3]的高16位部分。因为数字是1~10000,所以16位数字就能表示,而对于int来说,32位数字其高位是用不到的,所以就有空间可用了。
思路是:依次将数字写到该数字为索引的位置,当发现欲写的值和数字索引位置的数字相等时(其实也可以简单置为1),则命中。
下面当循环运行到a[8]的时候:
- a {Dimensions:[0x0000000a]} int[]
[0x00000000] 0x00000003 int
[0x00000001] 0x00010008 int
[0x00000002] 0x00020001 int
[0x00000003] 0x00030009 int
[0x00000004] 0x00000007 int
[0x00000005] 0x00050002 int
[0x00000006] 0x00060006 int
[0x00000007] 0x00070005 int
[0x00000008] 0x00080007 int
[0x00000009] 0x00090004 int
此时,a[8]的低位是7,所以应写为a[7]=7; 但是这个时候a[7]的高位已经是7了,所以命中,跳出。
题目:1-1000放在含有1001个元素的数组中,只有唯一的一个元素值重复,其它均只出现
一次。每个数组元素只能访问一次,设计一个算法,将它找出来;不用辅助存储空
间,能否设计一个算法实现?
时间还是o(N),无额外存储空间(说白了就是除了数组之外,不能额外开辟内存空间存储数组元素)。
//初始化
int N = 10;
int[] a = new int
;
Random rand = new Random();
//赋值
for (int i = 1; i < a.Length; i++)
int idx1 = 0;
int idx2 = 0;
//打乱顺序
for (int i = 0; i < a.Length * 10; i++)
//创建重复元素一个
idx1 = rand.Next(N);
while (a[idx1] == 0)
idx1 = rand.Next(N);
for (int i = 0; i < a.Length; i++)
//查找
unsafe
假设数组有10个元素,初始化时元素如下:
- a {Dimensions:[0x0000000a]} int[]
[0x00000000] 0x00000003 int
[0x00000001] 0x00000008 int
[0x00000002] 0x00000001 int
[0x00000003] 0x00000009 int
[0x00000004] 0x00000007 int
[0x00000005] 0x00000002 int
[0x00000006] 0x00000006 int
[0x00000007] 0x00000005 int
[0x00000008] 0x00000007 int
[0x00000009] 0x00000004 int
可以看出,相重的元素在a[4] 和a[8]处,也就是说数组循环到a[8]时才能发现相同的元素。
循环一次:
- a {Dimensions:[0x0000000a]} int[]
[0x00000000] 0x00000003 int
[0x00000001] 0x00000008 int
[0x00000002] 0x00000001 int
[0x00000003] 0x00030009 int
[0x00000004] 0x00000007 int
[0x00000005] 0x00000002 int
[0x00000006] 0x00000006 int
[0x00000007] 0x00000005 int
[0x00000008] 0x00000007 int
[0x00000009] 0x00000004 int
可以看出a[3]的值变了,变为了0x00030009.因为我将a[0]的低16位写到了a[3]的高16位部分。因为数字是1~10000,所以16位数字就能表示,而对于int来说,32位数字其高位是用不到的,所以就有空间可用了。
思路是:依次将数字写到该数字为索引的位置,当发现欲写的值和数字索引位置的数字相等时(其实也可以简单置为1),则命中。
下面当循环运行到a[8]的时候:
- a {Dimensions:[0x0000000a]} int[]
[0x00000000] 0x00000003 int
[0x00000001] 0x00010008 int
[0x00000002] 0x00020001 int
[0x00000003] 0x00030009 int
[0x00000004] 0x00000007 int
[0x00000005] 0x00050002 int
[0x00000006] 0x00060006 int
[0x00000007] 0x00070005 int
[0x00000008] 0x00080007 int
[0x00000009] 0x00090004 int
此时,a[8]的低位是7,所以应写为a[7]=7; 但是这个时候a[7]的高位已经是7了,所以命中,跳出。
相关文章推荐
- 算法复杂度精讲——算法时间复杂度的数学原理:从O(n(log(n))说起
- 算法的时间复杂度
- 算法的时间复杂度(计算实例)
- 寻找 最小的k个数 线性选择算法 平均时间复杂度 O(n)
- 重拾算法(一):算法效率分析(空间复杂度和时间复杂度)
- 算法的时间复杂度和空间复杂度-总结
- 一串首尾相连的珠子(m个),有N种颜色(N《=10),设计一个算法,取出其中一段,要求包含所有N中颜色,并使长度最短。并分析时间复杂度与空间复杂度。
- 算法中的各种排序以及查找时间复杂度
- 算法的时间复杂度(计算实例)
- 软考难点—算法时间的复杂度
- 数据结构之算法时间复杂度
- 从一个实例(整数幂指数)进行算法时间复杂度的分析
- 算法的时间复杂度和空间复杂度
- 算法的时间复杂度和空间复杂度
- 【转】算法的时间复杂度
- 算法的时间复杂度和空间复杂度
- 算法的时间复杂度和空间复杂度-总结
- 算法的时间复杂度 递推
- php 常用算法和时间复杂度
- 算法和数据结构 第一章:算法的时间复杂度