• “万里挑一”算法


    看了上面几个解决的,总是有些牵强,放上我写的,供大家参考。
    题目:1-1000放在含有1001个元素的数组中,只有唯一的一个元素值重复,其它均只出现
    一次。每个数组元素只能访问一次,设计一个算法,将它找出来;不用辅助存储空
    间,能否设计一个算法实现?
    时间还是o(N),无额外存储空间(说白了就是除了数组之外,不能额外开辟内存空间存储数组元素)。



    //初始化
                int N = 10;
                
    int[] a = new int[N];
                Random rand 
    = new Random();
                
    //赋值
                for (int i = 1; i < a.Length; i++)
                {
                    a[i] 
    = i;
                }

                
    int idx1 = 0;
                
    int idx2 = 0;
                
    //打乱顺序
                for (int i = 0; i < a.Length * 10; i++)
                {
                    idx1 
    = rand.Next(N);
                    idx2 
    = rand.Next(N);
                    
    if (idx1 == idx2)
                    {
                        i
    --;
                        
    continue;
                    }
                    a[idx1] 
    = a[idx1] ^ a[idx2];
                    a[idx2] 
    = a[idx1] ^ a[idx2];
                    a[idx1] 
    = a[idx1] ^ a[idx2];
                }
                
    //创建重复元素一个
                idx1 = rand.Next(N);
                
    while (a[idx1] == 0)
                    idx1 
    = rand.Next(N);

                
    for (int i = 0; i < a.Length; i++)
                {
                    
    if (a[i] == 0)
                    {
                        a[i] 
    = a[idx1];
                        
    break;
                    }
                }
                
    //查找
                unsafe
                {
                    
    fixed (int* p = a)
                    {
                        
    int* p1 = p;
                        
    //if a[0]==a[1]
                        if (*p1 == *(p1 + 1))
                        {
                            
    //Find!
                            return;
                        }
                        
    //loop array
                        while (p1 < p + N)
                        {
                            
    short* pBigEndian = (short*)(p + *(short*)p1) + 1;
                            
    short* pLittleEndian = (short*)p1;
                            
    *pBigEndian = *pLittleEndian;
                            p1
    ++;
                            pBigEndian 
    = (short*)(p + *(short*)p1) + 1;
                            pLittleEndian 
    = (short*)p1;
                            
    if (*pBigEndian == *pLittleEndian)
                            {
                                
    //Find!
                                break;
                            }
                        }
                    }
                }
    这个帖子挂了一天,能看懂我的方法人很少阿,为了节省大家的时间,我解释如下,
    假设数组有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了,所以命中,跳出。
  • 相关阅读:
    【Python五篇慢慢弹(3)】函数修行知python
    【Python五篇慢慢弹】数据结构看python
    【项目管理】GitHub使用操作指南
    【Python五篇慢慢弹】快速上手学python
    【NLP】十分钟快览自然语言处理学习总结
    【NLP】条件随机场知识扩展延伸(五)
    【NLP】基于统计学习方法角度谈谈CRF(四)
    【NLP】基于机器学习角度谈谈CRF(三)
    【NLP】基于自然语言处理角度谈谈CRF(二)
    【NLP】前戏:一起走进条件随机场(一)
  • 原文地址:https://www.cnblogs.com/diggingdeeply/p/1528656.html
Copyright © 2020-2023  润新知