首先从未排序的数组长度M中搜索N个排序的整数?

时间:2014-10-24 06:06:10

标签: c# arrays algorithm data-structures binary-search-tree

关于如何在M天前从未排序的整数数组大小中搜索前N个最小/最大有序整数的算法问题的采访失败。

从我的角度来看,所有搜索问题都可以转换为二进制搜索树数据结构,它具有log2N时间复杂度或其扩展名,如B +树。

对于这个问题,我首先构建一个二叉搜索树,然后在之后进行搜索N计数。 因此,复杂性应该是

  • 在建筑树中消耗:M * Log2 M +
  • 搜索树时消耗:N * Log2 M
  • 总计:=(M + N)log2 M

我找不到更好的解决方案,所以我在这里发布我的代码,真诚地希望你们有更好的代码。 代码非常随意但有效。这只是为了指出我的想法。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace SearchFirstNFromM
{
    class Program
    {
        static void Main(string[] args)
        {
            int[] m = new int[10000];   //INPUT M - int array
            int n = 10;                 //INPUT N - int

            Console.WriteLine("Integer Array");
            Random rd = new Random();
            for (int i = 0; i < m.Length; i++)
            {
                m[i] = rd.Next(0, m.Length);
                Console.Write(m[i] + " ");
            }

            Console.WriteLine();
            Console.WriteLine();
            Node root = BuildBinarySearchTree(m); //Building binary search tree
            Console.WriteLine("First N in ordered tree");
            Console.Write("Expected Result : ");
            m.OrderBy(t => t).Take(N_Counter).ToList().ForEach(t => Console.Write(t + " "));
            Console.WriteLine();
            Console.Write("Actual Result : ");
            DisplayFirstN(root);
            Console.WriteLine();
            Console.WriteLine();
            N_Counter = n; //Counter Reset
            Console.WriteLine("Last N in ordered tree");
            Console.Write("Expected Result : ");
            m.OrderByDescending(t => t).Take(N_Counter).ToList().ForEach(t => Console.Write(t + " "));
            Console.WriteLine();
            Console.Write("Actual Result : ");
            DisplayLastN(root);
            Console.WriteLine();

            Console.ReadKey();
        }

        static int N_Counter = 10;

        static void DisplayFirstN(Node root)
        {
            if (root != null)
            {
                if (root.Left != null)
                    DisplayFirstN(root.Left);

                if (N_Counter-- > 0)
                    Console.Write(root.Data + " ");

                if (root.Right != null)
                    DisplayFirstN(root.Right);
            }
        }

        static void DisplayLastN(Node root)
        {
            if (root != null)
            {
                if (root.Right != null)
                    DisplayLastN(root.Right);

                if (N_Counter-- > 0)
                    Console.Write(root.Data + " ");

                if (root.Left != null)
                    DisplayLastN(root.Left);
            }
        }

        static void DisplayTree(Node current)
        {
            if (current != null)
            {
                if (current.Left != null)
                    DisplayTree(current.Left);

                Console.Write(current.Data + " ");

                if (current.Right != null)
                    DisplayTree(current.Right);
            }
        }

        static Node BuildBinarySearchTree(int[] m)
        {
            Node root = new Node(m[0]);
            for (int i = 1; i < m.Length; i++)
            {
                Node current = root;
                while (true)
                {
                    if (m[i] >= current.Data)
                    {
                        if (current.Right == null)
                        {
                            var newNode = new Node(m[i]);
                            newNode.Parent = current;
                            current.Right = newNode;
                            break;
                        }

                        current = current.Right;
                    }
                    else
                    {
                        if (current.Left == null)
                        {
                            var newNode = new Node(m[i]);
                            newNode.Parent = current;
                            current.Left = newNode;
                            break;
                        }

                        current = current.Left;
                    }
                }
            }
            return root;
        }

        class Node
        {
            public Node(int data)
            {
                this.Data = data;
            }

            public Node Parent { get; set; }
            public Node Left { get; set; }
            public Node Right { get; set; }
            public int Data { get; set; }
        }
    }
}

OUTPUT

3 个答案:

答案 0 :(得分:2)

更好且相对简单的解决方法是使用a heap data structure。 然后算法将是:

对于前N个元素,插入堆(O [log N])。 对于每个剩余的M-N元素,将其与堆中的最小值(O 1)进行比较。 如果它更大,删除最小的堆值并将其插入堆中(O [log N])。 最后,从堆中生成一个排序列表(O [N log N])。

总复杂度:M log N + N log N.如果M远大于N,则胜过M log M排序。

答案 1 :(得分:1)

如果没有性能要求,最简单的方法是:

using System.Linq;
...
var rnd = new Random();
var m = Enumerable.Range(0, 10000).Select(i => rnd.Next(10000));
var result = m.OrderBy(i => i).Take(n);

您的代码很好,但是对于面试官期待的简单答案来说可能过于复杂。下次试着询问他/她是否想要一个简单/直接的解决问题的方法。

祝你好运,你有可能远远超出该公司的要求。

答案 2 :(得分:1)

对于那些不知道他们为什么来这里的观众。

在这种情况下,有一个完美的解决方案解决问题的有用链接,它由各种编程语言描述。

http://rosettacode.org/wiki/Quickselect_algorithm

顺便说一下,受该算法的启发,我创建了一个新的选择算法。 欢迎任何评论!

 public class myQuickSelect
    {
        public static int[] TakeSmallestNthNumbers(int[] array, int n)
        {
            int startIndex = 0;
            int endIndex = array.Length - 1;
            int remainingCount = n;

            array = (int[])array.Clone();

            Random rd = new Random();
            while (startIndex < endIndex)
            {
                //Randomly pick a number in searching section
                int pivotIndex = rd.Next(startIndex, endIndex);

                pivotIndex = Partition(array, startIndex, endIndex, pivotIndex);

                int foundCount = pivotIndex - startIndex + 1;

                if (foundCount == remainingCount)
                    break;

                if (foundCount > remainingCount)
                {
                    endIndex = --pivotIndex;
                }
                else
                {
                    remainingCount -= foundCount;
                    startIndex = ++pivotIndex;
                }
            }

            return array.Take(n).ToArray();
        }

        private static int Partition(int[] array, int startIndex, int endIndex, int pivotIndex)
        {
            //Console.WriteLine("Pivot Index:" + pivotIndex);

            Swap(array, startIndex, pivotIndex);
            int pivot = array[startIndex];
            while (startIndex < endIndex)
            {
                while (startIndex < endIndex && array[endIndex] >= pivot) endIndex--;
                array[startIndex] = array[endIndex];
                while (startIndex < endIndex && array[startIndex] < pivot) startIndex++;
                array[endIndex] = array[startIndex];
            }
            array[startIndex] = pivot;
            return startIndex;
        }

        private static void Swap(int[] array, int index1, int index2)
        {
            if (index1 == index2)
                return;

            int t = array[index1];
            array[index1] = array[index2];
            array[index2] = t;
        }
    }