• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            那誰(shuí)的技術(shù)博客

            感興趣領(lǐng)域:高性能服務(wù)器編程,存儲(chǔ),算法,Linux內(nèi)核
            隨筆 - 210, 文章 - 0, 評(píng)論 - 1183, 引用 - 0
            數(shù)據(jù)加載中……

            在一個(gè)有序序列中查找重復(fù)/不存在的數(shù)

            首先說(shuō)明一下這個(gè)問題中提到的"有序序列"的概念.它指的是其中的元素在序列長(zhǎng)度范圍之內(nèi),而且是有序(比如升序)排列的序列.比如一個(gè)只包含10個(gè)元素的數(shù)組, 其中的元素大小在[0, 9]之間,而且是升序排列的.

            這兩個(gè)問題是二分查找算法的典型應(yīng)用.

            首先來(lái)看看查找不存在元素的算法.假設(shè)一個(gè)元素x不存在, 那么在序列中, 在x位置的元素是x + 1, 以此類推.

            初始化 left = 0, right = len - 1 (其中l(wèi)en是這個(gè)有序序列的長(zhǎng)度, 假設(shè)序列從0開始)

            當(dāng)left 
            <= right時(shí)繼續(xù)循環(huán):
                  pos 
            = (left + right) / 2
                 
                  如果 序列的第pos個(gè)元素不等于pos
                          那么不存在的元素一定出現(xiàn)在pos之前, 將right 
            = pos - 1
                  否則
                          pos之前的元素都是存在的, 因此 left 
            = pos + 1

            根據(jù)上面的查找原則, 在left之前的元素都是存在的, 返回left

            再來(lái)看看查找重復(fù)元素的算法.假設(shè)一個(gè)元素x重復(fù)出現(xiàn), 那么在序列中, 在x + 1位置的元素是x, 而x+1出現(xiàn)在序列的x+2位置上, 以此類推.
            從上面的算法可以看出, 最后返回的位置, 在它之前的元素位置都是正確的, 就是說(shuō),出現(xiàn)在了它們應(yīng)該出現(xiàn)的位置, 因此, 上面算法也依然可以用于這個(gè)問題上面, 只要把上面算法的返回值 - 1即可以得到本算法要求的返回值.

            關(guān)于這個(gè)問題,我之前有過(guò)類似問題的討論:
            1) 二分查找算法(迭代和遞歸版本)
            2) 求出不在里面的數(shù)來(lái)
            這個(gè)問題的討論也是對(duì)<<編程珠璣>>第二章第一個(gè)算法問題的補(bǔ)充.

            C代碼如下:
            /*
             * 查找有序序列中 重復(fù)/不存在 的數(shù)算法演示
             * 版權(quán)所有:
            http://www.shnenglu.com/converse/
             
            */

            #include 
            <stdio.h>
            #include 
            <stdlib.h>
            #include 
            <time.h>

            #define FUNC_IN()   printf("\nin  %s\n\n", __FUNCTION__)
            #define FUNC_OUT()  printf("\nout %s\n\n", __FUNCTION__)

            /* 生成一個(gè)長(zhǎng)度為len的數(shù)組, 其中array[i] = i(0<=i<len) */
            void generate_array(int array[], int len);
                
            /* 向長(zhǎng)度為len的有序數(shù)組中新增一個(gè)元素x(0<=x<len - 1), 同時(shí)保持原有數(shù)組有序 */
            void add_to_array(int array[], int len, int x);

            /* 刪除長(zhǎng)度為len的有序數(shù)組中的一個(gè)元素x(0<=x<len), 同時(shí)保存原有數(shù)組有序 */
            void del_from_array(int array[], int len, int x);

            /* 打印一個(gè)數(shù)組 */
            void display_array(int array[], int len);

            /* 查找一個(gè)長(zhǎng)度為len的有序數(shù)組中哪個(gè)元素不存在 */
            int find_not_exist(int array[], int len);

            /* 查找一個(gè)長(zhǎng)度為len的有序數(shù)組中哪個(gè)元素重復(fù)了 */
            int find_duplicate(int array[], int len);

            int main(int argc, char *argv[])
            {
                
            int count = 10;
                
            int *array = NULL;

                srand(time(NULL));

                
            if (argc == 2)
                {
                    count 
            = atoi(argv[1]);
                }

                
            /* 申請(qǐng)內(nèi)存的時(shí)候多申請(qǐng)一個(gè)元素 */
                
            if ((array = (int *)malloc((count + 1* sizeof(int))) == NULL)
                {
                    printf(
            "malloc error!\n");
                    exit(
            -1);
                }

                
            /* 首先生成一個(gè)元素都是有序的整型數(shù)組 */
                generate_array(array, count);

                display_array(array, count);

                
            /* 刪除其中的一個(gè)元素 */
                del_from_array(array, count, rand() 
            % count);

                display_array(array, count);

                
            /* 查找不存在的元素 */
                
            int x = find_not_exist(array, count);
                printf(
            "the element not exist is %d\n", x);

                
            /* 把刪除的元素補(bǔ)上 */
                add_to_array(array, count 
            + 1, x);

                
            /* 新增一個(gè)重復(fù)的元素 */
                add_to_array(array, count 
            + 1, rand() % count);

                display_array(array, count 
            + 1);

                
            /* 查找重復(fù)的元素 */
                printf(
            "the element duplicate is %d\n", find_duplicate(array, count + 1));

                free(array);

                
            return 0;
            }

            void generate_array(int array[], int len)
            {
                
            int i;

                
            for (i = 0; i < len; ++i)
                {
                    array[i] 
            = i;
                }
            }

            void add_to_array(int array[], int len, int x)
            {
                
            int i;

                
            /* 把[x + 1, len - 1]之間的元素右移一個(gè)位置 */
                
            for (i = x + 1; i < len - 1++i)
                {
                    array[i 
            + 1= i;
                }

                
            /* x + 1的位置保存重復(fù)的x, 這樣數(shù)組仍然是有序的 */
                array[x 
            + 1= x;
            }

            void del_from_array(int array[], int len, int x)
            {
                
            int i;

                
            /* 將[x, len)的元素向左移動(dòng)一個(gè)位置 */
                
            for (i = x; i < len; ++i)
                {
                    array[i] 
            = i + 1;
                }

                printf(
            "del_from_array element is %d\n", x);
            }

            void display_array(int array[], int len)
            {
                
            int i;

                printf(
            "\n{ ");
                
            for (i = 0; i < len; ++i)
                {
                    printf(
            "%d ", array[i]);
                }

                printf(
            "}\n");
            }

            int find_not_exist(int array[], int len)
            {
                FUNC_IN();

                
            int left, right, pos, count;

                
            for (left = 0, right = len - 1, count = 1; left <= right; count++)
                {
                    pos 
            = (left + right) / 2;

                    printf(
            "[%d] left = %d, pos = %d, right = %d\n", count, left, pos, right);

                    
            /*
                     * 如果array[pos] != pos, 那么不存在的元素一定在[left, pos - 1]之間
                     
            */
                    
            if (array[pos] != pos)
                    {
                        right 
            = pos - 1;
                    }
                    
            else
                    {
                        left 
            = pos + 1;
                    }
                }

                FUNC_OUT();

                
            /* left之前的元素都是存在的 */
                
            return left;
            }

            int find_duplicate(int array[], int len)
            {
                
            /*
                 * find_not_exist()函數(shù)的返回值表示在它之前的元素都是正確的, 
                 * 因此這個(gè)返回位置就是有重復(fù)的元素位置 + 1, 于是要減去1
                 * 
            */
                
            return find_not_exist(array, len) - 1;
            }





            posted on 2009-08-23 20:24 那誰(shuí) 閱讀(4840) 評(píng)論(3)  編輯 收藏 引用 所屬分類: 算法與數(shù)據(jù)結(jié)構(gòu)

            評(píng)論

            # re: 在一個(gè)有序序列中查找重復(fù)/不存在的數(shù)  回復(fù)  更多評(píng)論   

            為什么不用BitArray?
            遍歷一次就搞定!
            2009-08-24 12:20 | 阿福

            # re: 在一個(gè)有序序列中查找重復(fù)/不存在的數(shù)  回復(fù)  更多評(píng)論   

            @阿福
            別人是搞算法的...
            用容器只是應(yīng)用
            2009-08-24 16:09 | Norz

            # re: 在一個(gè)有序序列中查找重復(fù)/不存在的數(shù)  回復(fù)  更多評(píng)論   

            @阿福
            你可能沒有仔細(xì)看我對(duì)問題的描述,事實(shí)上,如果使用這里所用的二分查找算法,都不用遍歷一次,O(log(n))的時(shí)間復(fù)雜度就搞定問題了.
            2009-08-24 16:23 | 那誰(shuí)
            四虎国产精品成人免费久久| 国产亚洲美女精品久久久久狼| 久久99精品国产自在现线小黄鸭 | 青青草国产97免久久费观看| 国产综合免费精品久久久| 亚洲中文字幕无码久久2020| 91精品国产91热久久久久福利 | 国内精品久久久久久中文字幕| 久久精品国产国产精品四凭| 久久精品国产亚洲av影院| 2019久久久高清456| 久久久久久国产精品无码下载 | 色综合久久精品中文字幕首页| 久久精品国产亚洲AV无码偷窥| 国产一区二区精品久久岳| 久久99热这里只有精品国产| 亚洲日本va午夜中文字幕久久| 久久99久久成人免费播放| 亚洲AV无码久久精品狠狠爱浪潮 | 久久99热只有频精品8| 亚洲人AV永久一区二区三区久久 | 久久久久久国产精品无码下载| 伊人久久综在合线亚洲2019| 久久精品国产亚洲AV嫖农村妇女| 无码人妻久久一区二区三区蜜桃| 久久国产乱子伦精品免费强| 97精品依人久久久大香线蕉97| 久久久久女教师免费一区| 国产成人精品久久| 伊人情人综合成人久久网小说| 精品国产日韩久久亚洲| 国产日韩久久免费影院| 99久久免费只有精品国产| 国产精品美女久久久| 久久精品国产精品亚洲人人| 久久99精品久久久久久齐齐| 久久99精品久久久久久野外| 久久夜色精品国产亚洲av| 国产aⅴ激情无码久久| A级毛片无码久久精品免费| 久久久亚洲欧洲日产国码是AV|