关于如何在M天前从未排序的整数数组大小中搜索前N个最小/最大有序整数的算法问题的采访失败。
从我的角度来看,所有搜索问题都可以转换为二进制搜索树数据结构,它具有log2N时间复杂度或其扩展名,如B +树。
对于这个问题,我首先构建一个二叉搜索树,然后在之后进行搜索N计数。 因此,复杂性应该是
我找不到更好的解决方案,所以我在这里发布我的代码,真诚地希望你们有更好的代码。 代码非常随意但有效。这只是为了指出我的想法。
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; }
}
}
}
答案 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;
}
}