• 顺序统计:寻找序列中第k小的数


    最直观的解法,排序之后取下标为k的值即可。

    但是此处采取的方法为类似快速排序分块的方法,利用一个支点将序列分为两个子序列(支点左边的值小于支点的值,支点右边大于等于支点的值)。

    如果支点下标等于k,则支点就是查找的值,如果支点的下标大于k,则在左子序列里继续寻找,如果支点下标小于k,则继续在支点右子序列里面继续寻找第(k-支点下标)小的值。

    c#实现算法如下:

     public class FindSpecialOrderElement<T> where T : IComparable<T>
        {
            public T FindElementWithOrder(T[] array, int startIndex, int endIndex, int order)
            {
                int pivot = Partition(array, startIndex, endIndex);
                //pivot支点为第(pivot-startIndex+1)小的值
                int pivotOrder = pivot - startIndex + 1;
                if (pivotOrder == order)
                { return array[pivot]; }
                else if (pivotOrder > order)
                {
                    return FindElementWithOrder(array, startIndex, pivot - 1, order);
                }
                else//pivotOrder < order
                {
                    return FindElementWithOrder(array, pivot + 1, endIndex, order - pivotOrder);
                }
            }
            public static int Partition(T[] array, int leftIndex, int rightIndex)
            {
                //leftIndex的位置空出来了
                T pivotValue = array[leftIndex];
                //将所有<pivotValue的值移动到pivotValue的左边(不稳定排序,因为相等值得相对位置可能被此步骤改变)
                //将所有>=pivotValue的值移到右边
                //移动的结果就是所有<pivotValue的值都在pivotValue的左边,>=它的都在右边
                //记录之后pivotValue所在位置,返回该位置,完成一次分区划分。
                while (leftIndex < rightIndex)
                {
                    //因为是leftIndex先空出来位置,所以第一步要从右侧rightIndex向左寻找小于pivotValue的数值位置
                    while (leftIndex < rightIndex && array[rightIndex].CompareTo(pivotValue) >= 0) rightIndex--;
                    //将找到的小于pivotValue的位置的元素放到空出的leftIndex位置,leftIndex++
                    if (leftIndex < rightIndex) array[leftIndex++] = array[rightIndex];
                    //leftIndex向右寻找>=pivotValue的值的位置
                    while (leftIndex < rightIndex && array[leftIndex].CompareTo(pivotValue) < 0) leftIndex++;
                    //将找到的>=pivotValue的位置的leftIndex元素放到上一步空出的rightIndex位置
                    //此时leftIndex所在位置变成待插入位置,重新回到外圈循坏的初始状态
                    if (leftIndex < rightIndex) array[rightIndex--] = array[leftIndex];
                }
                //最后while循环结束的位置就是leftIndex==rightIndex,并且这个位置是空出来的,正好把pivotValue放到这个位置
                //这就是轴的概念,轴两边的值时由轴正好分开的,一边小于轴,一边大于等于轴
                array[leftIndex] = pivotValue;
                return leftIndex;
            }
    
        }

    方法调用方法:

     static void Main(string[] args)
            {
                FindSpecialOrderElement<int> ESOE = new FindSpecialOrderElement<int>();
                int[] data1 = new int[10] { 1, 2, 3, 20, 5, 6, 7, 8, 9, 10 };
                Console.WriteLine();
                data1.ToList<int>().ForEach(i => Console.Write("{0},", i));
                int e = ESOE.FindElementWithOrder(data1, 0, data1.Length - 1, 4);
                Console.WriteLine("Find the 4th small element:{0}", e);
    
                int[] data2 = new int[10] { 6, 90, 8, 9, 10, 1, 2, 3, 4, 5 };
                Console.WriteLine();
                data2.ToList<int>().ForEach(i => Console.Write("{0},", i));
                int f = ESOE.FindElementWithOrder(data2, 0, data1.Length - 1, 7);
                Console.WriteLine("Find the 7th small element:{0}", f);
                Console.ReadKey();
            }

    作者:Andy Zeng

    欢迎任何形式的转载,但请务必注明出处。

    http://www.cnblogs.com/andyzeng/p/3695478.html

  • 相关阅读:
    当虚拟空间(主机)不支持301时,该怎样重定向域名
    总结高权重论坛
    一个错
    layui树形框架
    命令模式
    《编写有效用例》读书笔记2
    jieba安装与简单使用
    list正序倒序排列
    每日博客
    每日博客
  • 原文地址:https://www.cnblogs.com/andyzeng/p/3695478.html
Copyright © 2020-2023  润新知