zoukankan      html  css  js  c++  java
  • 查找最小的k 个元素之C#算法实现

    紧接着上一篇微软编程面试100题,这次想解决的是查找最小的K个元素,题目是:输入n 个整数,输出其中最小的k 个。例如输入1,2,3,4,5,6,7 和8 这8 个数字,则最小的4 个数字为1,2,3 和4。

    看到题目的时候我第一反应,这题很简单,使用任何方式的排序将数列按顺序存储,之后遍历需要的k个元素即可,于是自己动手很容易就完成了,但是后来在网络上发现很多人对这题的解决方式是用小根堆(MinHeap)或者大根堆(MaxHeap),这才意识到,其实出题人是醉翁之意不在酒,在乎复杂度的考虑也。

    先写用排序的方式完成题目的方式吧,不仅简单,不需要费太多脑子,重要的是,正好趁这时候复习下排序,这里用快速排序完成:

            public static void Quick_Sort(int[] sort, int left, int right)
            {
                int mid = sort[(left + right) / 2];
                int i = left;
                int j = right;
                do
                {
                    while (sort[i] < mid && i < right) i++;
                    while (sort[j] > mid && j > left) j--;
                    if (i <= j)
                    {
                        int temp = sort[i];
                        sort[i] = sort[j];
                        sort[j] = temp;
                        i++;
                        j--;
                    }
    
                } while (i <= j);
    
                if (j > left) Quick_Sort(sort, left, j);
                if (i < right) Quick_Sort(sort, i, right);
            }  
    

    然后定义一个MinKMethod的方法来获取所需元素:

            public static void MinKMethod(int[] sort, int k)
            {
                Quick_Sort(sort, 0, sort.Length - 1);
                if (k > sort.Length)
                {
                    for (int j = 0; j < sort.Length; j++)
                    {
                        Console.Write(sort[j] + " ");
                    }
                    Console.WriteLine();
                }
                if (k <= 0)
                {
                    Console.WriteLine("Nothing Output");
                }
                if (k > 0 && k < sort.Length)
                {
                    for (int j = 0; j < k; j++)
                    {
                        Console.Write(sort[j] + " ");
                    }
                }
    
            } 
    

    这么做的话,最快需要O(NlogN)的时间进行排序,然后在O(1)的时间内将k个数取出。

    接下来看看如何用堆完成这个题:

            public static void FindKMin(int[] sort, int k)
            {
                int[] heap = sort;
                int rootIndex = k / 2 - 1;
                while (rootIndex >= 0)
                {
                    reheap(heap, rootIndex, k - 1);
                    rootIndex--;
                }
    
                for (int i = k, len=heap.Length; i < len; i++)
                {
                    if (heap[i]<heap[0])
                    {
                        heap[0] = heap[i];
                        reheap(heap, 0, k - 1);
                    }
                }
    
                Console.WriteLine("The {0} min element =",k);
                for (int i = 0; i < k; i++)
                {
                    Console.Write(heap[i] + " ");
                }
            }
    
            private static void reheap(int[] heap, int rootIndex, int lastInddex)
            {
                int orphan = heap[rootIndex];
                bool done = false;
                int leftIndex = rootIndex * 2 + 1;
                while (!done && leftIndex <= lastInddex)
                {
                    int largerIndex = leftIndex;
                    if (leftIndex+1 <= lastInddex)
                    {
                        int rightIndex = leftIndex + 1;
                        if (heap[rightIndex] > heap[leftIndex])
                        {
                            largerIndex = rightIndex;
                        }
                    }
    
                    if (orphan < heap[largerIndex])
                    {
                        heap[rootIndex] = heap[largerIndex];
                        rootIndex = largerIndex;
                        leftIndex = rootIndex * 2 + 1;
                    }
                    else
                    {
                        done = true;
                    }
                }
    
                heap[rootIndex] = orphan;
            }
    

    用堆解决这个问题其实思路并不难,前提是,需要对堆有一定的理解。

    作者:Ribbon 出处: http://www.cnblogs.com/Ribbon/ 本文版权归作者和博客园共有,欢迎转载。未经作者同意下,必须在文章页面明显标出原文链接及作者,否则保留追究法律责任的权利。 如果您认为这篇文章还不错或者有所收获,可以点击右下角的【推荐】按钮,因为你的支持是我继续写作,分享的最大动力!
  • 相关阅读:
    一个简单的knockout.js 和easyui的绑定
    knockoutjs + easyui.treegrid 可编辑的自定义绑定插件
    Knockout自定义绑定my97datepicker
    去除小数后多余的0
    Windows Azure Web Site (15) 取消Azure Web Site默认的IIS ARR
    Azure ARM (1) UI初探
    Azure Redis Cache (3) 创建和使用P级别的Redis Cache
    Windows Azure HandBook (7) 基于Azure Web App的企业官网改造
    Windows Azure Storage (23) 计算Azure VHD实际使用容量
    Windows Azure Virtual Network (11) 创建VNet-to-VNet的连接
  • 原文地址:https://www.cnblogs.com/Ribbon/p/3629676.html
Copyright © 2011-2022 走看看