亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發設計 > 正文

對“求數組中所有和為某固定數的所有數對”的算法的簡單思考

2019-11-17 03:52:00
字體:
來源:轉載
供稿:網友
一、題目描述

    有一個數組a[1000],里面存放了1000個整數,請找出該數組中所有和為M的數對。例如數組為-1,2,4,6,5,3,4,2,9,0,8,3,那么和為8的數對有(-1,9),(2,6),(4,4),(5,3),(5,3),(0,8)。



二、最普通的算法

   在不可率復雜度的情況下,對于這個問題的最簡單的算法如下:

        PRivate static List<int[]> UseNormalWay(int[] arr, int sumTotal)
        {
            List<int[]> result = new List<int[]>();

            for (int i = 0; i < arr.Length; i++)
            {
                int expectNum = sumTotal - arr[i];

                for (int j = i + 1; j < arr.Length; j++)
                {
                    if (arr[j] == expectNum)
                    {
                        result.Add(new int[]{arr[i], expectNum});
                    }
                }
            }

            return result;
        }
   利用兩層循環查找所有和為固定數sumTotal的所有數對,將找到的數對存入List中。但是這個算法復雜度有點高,實際上在遍歷的時候做了一些重復的工作:

    1) 后續循環的時候沒有必要對前面已經配對的數列進行處理。

    2)查找與某個數和為sumTotal的數時,應該可以有一些可以相互利用的過程。

    基于這兩點,可以引用一些01背包或動態規劃的思想(或許引用得不恰當,我對這兩種思想和理解很膚淺)來對這個算法進行改進,利用遞歸來操作。



二、采用遞歸算法

    采用遞歸算法的代碼如下:

       private static List<int[]> UseRecursion(int[] arr, int length, int sumTotal)
        {
            List<int[]> result = new List<int[]>();
            int[] nextArr = new int[length];
            int nextLength = 0;
            int expectNum = sumTotal - arr[0];
            int findStartNumCount = 0;
            int findEndNumCount = 0;

            for (int i = 1; i < length; i++)
            {
                if (arr[i] == expectNum)
                {
                    int circleCount = arr[0] == expectNum ? findEndNumCount : findStartNumCount;
                    circleCount += 1;

                    for (int j = 0; j < circleCount; j++)
                    {
                        result.Add(new int[] { arr[0], expectNum });    
                    }

                    findEndNumCount++;                    
                }
                else if (arr[i] == arr[0])
                {
                    for (int j = 0; j < findEndNumCount; j++)
                    {
                        result.Add(new int[] { expectNum, arr[0] });
                    }
                    findStartNumCount++;
                }
                else
                {
                    nextArr[nextLength++] = arr[i];
                }                
            }

            if (nextLength > 0)
            {
                List<int[]> nextResult = UseRecursion(nextArr, nextLength, sumTotal);
                foreach (int[] item in nextResult)
                {
                    result.Add(item);
                }
            }

            return result;
        }
      每遞歸一次后,將所有沒有檢查過匹配的數字再組成一個新的數組以便在下一次遞歸中來處理,但這么做浪費了巨大的空間,特別是數組很大的情況下會消耗很多內存。為了不每次遞歸創建新的數組,可以在原來的數組上進行處理,將已經匹配的數字從數組中剔出,將后續數字前移替補。

三、數組動態改變算法

     這種算法的代碼如下:

         private static List<int[]> UseAdvancedWay(int[] arr, int sumTotal)
        {
            List<int[]> result = new List<int[]>();
            int startIndex = 0, endIndex = arr.Length - 1;

            while (startIndex < endIndex)
            {
                int expectNum = sumTotal - arr[startIndex];
                int findStartNumCount = 0;
                int findEndNumCount = 0;

                for (int i = startIndex + 1; i <= endIndex; i++)
                {
                    if (findStartNumCount > 0 || findEndNumCount > 0)
                    {
                        arr[i] = arr[i + findStartNumCount + findEndNumCount];
                    }

                    if (arr[i] == expectNum)
                    {
                        int circleCount = arr[startIndex] == expectNum ? findEndNumCount : findStartNumCount;
                        circleCount += 1;

                        for (int iStart = 0; iStart < circleCount; iStart++)
                        {
                            result.Add(new int[] { arr[startIndex], arr[i] });
                        }

                        findEndNumCount++;
                        endIndex--;
                        i--;
                    }
                    else if (arr[i] == arr[startIndex] && arr[startIndex] != expectNum)
                    {
                        for (int iEnd = 0; iEnd < findEndNumCount; iEnd++)
                        {
                            result.Add(new int[] { expectNum, arr[i] });
                        }

                        findStartNumCount++;
                        endIndex--;
                        i--;
                    }
                }
                startIndex++;
            }

            return result;
        }

       這種算法會破壞原有數組的數據的。

四、三種算法時間的比較

     雖然后兩種算法的初衷是為了減少時間復雜度,但在具體測試中并沒有比第一種算法優越多少,特別是遞歸的算法比第一種算法所用的時間還明顯加長。或許我的想法從基礎上就有問題,也或許是這個例子過于簡單使得移動數據占用的時間明顯凸現出來了。

     一直未對算法有過多研究,希望高手們能指點一二,我相信有肯定有更完美的解決方案。

五、所有碼

        static void Main(string[] args)
        {
            const int NUM_COUNT = 8000;
            const int MIN_NUM = -4;
            const int MAX_NUM = 12;
            const int TOTAL = 8;

            int[] arr = GenerateArray(NUM_COUNT, MIN_NUM, MAX_NUM);

            //Console.WriteLine("The numbers generated are:/n-------------------------------------");
            //PrintNumArray(arr);

            // Normal way
            TimeSpan normalTimeStart = Process.GetCurrentProcess().TotalProcessorTime;
            Stopwatch normalStw = new Stopwatch();
            normalStw.Start();

            List<int[]> resultUseNormalWay = UseNormalWay(arr, TOTAL);

            double normalCupTime = Process.GetCurrentProcess().TotalProcessorTime.Subtract(normalTimeStart).TotalMilliseconds;
            normalStw.Stop();
            double normalRealTime = normalStw.Elapsed.TotalMilliseconds;

            // Print Normal Result
            //Console.WriteLine("The result number pairs using normal way are:/n----------------------------------");
            //PrintNumPairs(resultUseNormalWay);

            // Recursion way
            TimeSpan recuTimeStart = Process.GetCurrentProcess().TotalProcessorTime;
            Stopwatch recuStw = new Stopwatch();
            recuStw.Start();

            List<int[]> resultUseRecursionWay = UseRecursion(arr, arr.Length, TOTAL);

            double recuCupTime = Process.GetCurrentProcess().TotalProcessorTime.Subtract(recuTimeStart).TotalMilliseconds;
            recuStw.Stop();
            double recuRealTime = recuStw.Elapsed.TotalMilliseconds;

            // Print Recursion Result
            //Console.WriteLine("The result number pairs using recusion way are:/n----------------------------------");
            //PrintNumPairs(resultUseRecursionWay);

            // Advanced way
            TimeSpan advTimeStart = Process.GetCurrentProcess().TotalProcessorTime;
            Stopwatch advStw = new Stopwatch();
            advStw.Start();

            List<int[]> resultUseAdvancedWay = UseAdvancedWay(arr, TOTAL);

            double advCupTime = Process.GetCurrentProcess().TotalProcessorTime.Subtract(advTimeStart).TotalMilliseconds;
            advStw.Stop();
            double advRealTime = advStw.Elapsed.TotalMilliseconds;

            // Print Advanced Result
            //Console.WriteLine("The result number pairs using advanced way are:/n----------------------------------");
            //PrintNumPairs(resultUseAdvancedWay);


            Console.WriteLine("/n================================/nThe time used:/n-----------------------------------");
            Console.WriteLine(String.Format("Normal   : count - {0}   Cpu Time - {1}  Real Time - {2}", resultUseNormalWay.Count, normalCupTime, normalRealTime));
            Console.WriteLine(String.Format("Recursion: count - {0}   Cpu Time - {1}  Real Time - {2}", resultUseRecursionWay.Count, recuCupTime, recuRealTime));
            Console.WriteLine(String.Format("Advanced : count - {0}   Cpu Time - {1}  Real Time - {2}", resultUseAdvancedWay.Count, advCupTime, advRealTime));

            Console.Read();
        }

        private static int[] GenerateArray(int numCount, int minValue, int maxValue)
        {
            int[] arr = new int[numCount];

            Random rdm = new Random((int)DateTime.Now.Ticks);
            for (int i = 0; i < arr.Length; i++)
            {
                arr[i] = rdm.Next(minValue, maxValue);
            }

            return arr;
        }

        private static void PrintNumArray(int[] arr)
        {
            for (int i = 0; i < arr.Length; i++)
            {
                if (i > 0 && i % 20 == 0)
                {
                    Console.Write("/n");
                }
                Console.Write(String.Format("{0,2}  ", arr[i]));
            }
            Console.Write("/n");
        }

        private static void PrintNumPairs(List<int[]> numList)
        {
            for (int i = 0; i < numList.Count; i++)
            {
                if (i > 0 && i % 10 == 0)
                {
                    Console.Write("/n");
                }
                Console.Write(string.Format("({0,2},{1,2})  ", numList[i][0], numList[i][1]));
            }
            Console.Write("/n");
        }

        private static List<int[]> UseNormalWay(int[] arr, int sumTotal)
        {
            List<int[]> result = new List<int[]>();

            for (int i = 0; i < arr.Length; i++)
            {
                int expectNum = sumTotal - arr[i];

                for (int j = i + 1; j < arr.Length; j++)
                {
                    if (arr[j] == expectNum)
                    {
                        result.Add(new int[]{arr[i], expectNum});
                    }
                }
            }

            return result;
        }

        private static List<int[]> UseRecursion(int[] arr, int length, int sumTotal)
        {
            List<int[]> result = new List<int[]>();
            int[] nextArr = new int[length];
            int nextLength = 0;
            int expectNum = sumTotal - arr[0];
            int findStartNumCount = 0;
            int findEndNumCount = 0;

            for (int i = 1; i < length; i++)
            {
                if (arr[i] == expectNum)
                {
                    int circleCount = arr[0] == expectNum ? findEndNumCount : findStartNumCount;
                    circleCount += 1;

                    for (int j = 0; j < circleCount; j++)
                    {
                        result.Add(new int[] { arr[0], expectNum });    
                    }

                    findEndNumCount++;                    
                }
                else if (arr[i] == arr[0])
                {
                    for (int j = 0; j < findEndNumCount; j++)
                    {
                        result.Add(new int[] { expectNum, arr[0] });
                    }
                    findStartNumCount++;
                }
                else
                {
                    nextArr[nextLength++] = arr[i];
                }                
            }

            if (nextLength > 0)
            {
                List<int[]> nextResult = UseRecursion(nextArr, nextLength, sumTotal);
                foreach (int[] item in nextResult)
                {
                    result.Add(item);
                }
            }

            return result;
        }

        private static List<int[]> UseAdvancedWay(int[] arr, int sumTotal)
        {
            List<int[]> result = new List<int[]>();
            int startIndex = 0, endIndex = arr.Length - 1;

            while (startIndex < endIndex)
            {
                int expectNum = sumTotal - arr[startIndex];
                int findStartNumCount = 0;
                int findEndNumCount = 0;

                for (int i = startIndex + 1; i <= endIndex; i++)
                {
                    if (findStartNumCount > 0 || findEndNumCount > 0)
                    {
                        arr[i] = arr[i + findStartNumCount + findEndNumCount];
                    }

                    if (arr[i] == expectNum)
                    {
                        int circleCount = arr[startIndex] == expectNum ? findEndNumCount : findStartNumCount;
                        circleCount += 1;

                        for (int iStart = 0; iStart < circleCount; iStart++)
                        {
                            result.Add(new int[] { arr[startIndex], arr[i] });
                        }

                        findEndNumCount++;
                        endIndex--;
                        i--;
                    }
                    else if (arr[i] == arr[startIndex] && arr[startIndex] != expectNum)
                    {
                        for (int iEnd = 0; iEnd < findEndNumCount; iEnd++)
                        {
                            result.Add(new int[] { expectNum, arr[i] });
                        }

                        findStartNumCount++;
                        endIndex--;
                        i--;
                    }
                }
                startIndex++;
            }

            return result;
        }

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
午夜精品久久久久久久男人的天堂| 欧美洲成人男女午夜视频| 亚洲精品综合精品自拍| 欧美高清视频在线| 国产精品jizz在线观看麻豆| 日韩av不卡在线| 欧美在线视频在线播放完整版免费观看| 欧美午夜片在线免费观看| 粗暴蹂躏中文一区二区三区| www国产亚洲精品久久网站| 欧美精品videosex性欧美| 一区二区中文字幕| 国产精品视频区| 国产精品99蜜臀久久不卡二区| 亚洲自拍偷拍色图| 亚洲视频自拍偷拍| 午夜精品久久久久久久久久久久久| 国产成人精品亚洲精品| 欧美亚洲国产日韩2020| 日本精品一区二区三区在线播放视频| 91福利视频在线观看| 国产成人涩涩涩视频在线观看| 日韩av手机在线| 欧美国产日韩xxxxx| 久久久国产一区| 国语自产精品视频在线看抢先版图片| 欧美日韩性生活视频| 黄色成人在线免费| 欧美日韩国产丝袜美女| 亚洲亚裔videos黑人hd| 亚洲一区二区三区在线免费观看| 国产精品久久久久久久一区探花| 日韩毛片在线看| 欧美成人午夜激情在线| 欧美日韩国产专区| 国产精品自拍偷拍视频| 欧美性猛交xxxx黑人猛交| 最新的欧美黄色| 成人日韩在线电影| 亚洲欧美资源在线| 高清视频欧美一级| 国产精品久久久久久久久久东京| 亚洲国产成人精品电影| 国产精品久久久| 精品国产一区二区三区久久久| 国产成人一区二区三区小说| 国产精品亚洲аv天堂网| 亚洲成人在线视频播放| 日韩电影第一页| 国产福利视频一区二区| 欧美精品videosex牲欧美| 成人天堂噜噜噜| 在线日韩av观看| 国产成人极品视频| 亚洲欧美在线磁力| 69av成年福利视频| 欧美亚洲第一区| 青青草一区二区| 爽爽爽爽爽爽爽成人免费观看| 国产精品网站入口| 国产免费观看久久黄| 欧美大片免费观看在线观看网站推荐| 在线视频欧美性高潮| 国产亚洲精品美女久久久久| 国产欧美婷婷中文| 欧美精品www在线观看| 国产极品精品在线观看| 国产精品扒开腿做爽爽爽男男| 午夜精品国产精品大乳美女| 国产精品麻豆va在线播放| 亚洲国产欧美自拍| 在线电影中文日韩| 免费91麻豆精品国产自产在线观看| 久久人人爽人人爽人人片av高清| 国产精品欧美激情在线播放| 视频直播国产精品| 日韩欧美在线视频观看| 国产成人在线精品| 欧美丰满老妇厨房牲生活| 欧美日韩亚洲91| 欧美猛交ⅹxxx乱大交视频| 国产日本欧美一区二区三区在线| 性金发美女69hd大尺寸| 欧美人与性动交a欧美精品| 欧美日韩中文字幕日韩欧美| 国产成人av在线播放| 日韩高清电影好看的电视剧电影| 亚洲字幕一区二区| 欧美视频一二三| 欧美精品videos性欧美| 原创国产精品91| 精品久久久在线观看| 日本久久久a级免费| 日韩电影在线观看中文字幕| 疯狂欧美牲乱大交777| 国产精品视频中文字幕91| 成人久久久久爱| 国模精品视频一区二区三区| 欧美怡春院一区二区三区| 热久久视久久精品18亚洲精品| 亚洲天堂男人天堂女人天堂| 国产精品欧美激情| 欧美综合在线第二页| 91精品国产高清久久久久久91| 午夜伦理精品一区| 欧美成人午夜激情| 九九热这里只有精品6| 亚洲欧美国产va在线影院| 国产精品美女免费| 成人免费直播live| 国产亚洲精品91在线| 亚洲аv电影天堂网| 亚洲国产另类 国产精品国产免费| 日韩亚洲第一页| 秋霞av国产精品一区| 色综合五月天导航| 日韩美女免费视频| 国内精品400部情侣激情| 精品女厕一区二区三区| 国产a级全部精品| 国产日韩综合一区二区性色av| 蜜臀久久99精品久久久无需会员| 国产亚洲精品久久久久久牛牛| 欧美日韩在线视频一区二区| 亚洲男人天堂2019| 国产有码一区二区| 91成人在线视频| 午夜精品久久久久久久久久久久久| 亚洲性生活视频| 91av视频导航| 成人国产精品一区| 亚洲无亚洲人成网站77777| 亚洲偷熟乱区亚洲香蕉av| 久久精品青青大伊人av| 黄色精品一区二区| 狠狠久久五月精品中文字幕| 亚洲成在人线av| 精品久久久久久久久久久久| 欧美性xxxx在线播放| 亚洲视频国产视频| 国产精品黄视频| 美女视频黄免费的亚洲男人天堂| 日本中文字幕成人| 久久久亚洲欧洲日产国码aⅴ| 综合av色偷偷网| 欧美日韩国产丝袜另类| 日本精品va在线观看| 2019中文在线观看| 亚洲欧美日韩国产成人| 久久久之久亚州精品露出| 日韩视频在线免费观看| 亚洲国产91精品在线观看| 国产一区二区三区视频免费| 最近2019年中文视频免费在线观看| 日韩风俗一区 二区| 国产精品丝袜视频| 91国内精品久久| 日韩精品视频在线免费观看| 成人免费自拍视频| 最新日韩中文字幕| 成人乱人伦精品视频在线观看| 久久精品99久久香蕉国产色戒| 午夜精品久久久99热福利| 91av成人在线|