你有一个n个整数的列表,你想要x最小。例如,
x_smallest([1, 2, 5, 4, 3], 3)
应该返回[1, 2, 3]
。
我将在合理范围内对独特的运行时进行投票,并将绿色检查提供给最佳运行时。
我将从O(n * x)
开始:创建一个长度为x的数组。在列表中迭代x次,每次都拉出下一个最小的整数。
编辑
[1, 1, 1, 1, 1]
。答案 0 :(得分:13)
你可以在O(n)时间内找到第k个最小元素。 This has been discussed on StackOverflow before。有一些相对简单的随机算法,如QuickSelect,运行在O(n)预期时间和更复杂的算法,运行在O(n)最坏情况时间。
给定第k个最小元素,你可以在列表上进行一次传递,找到小于第k个最小值的所有元素,然后就完成了。 (我假设结果数组不需要排序。)
总运行时间为O(n)。
答案 1 :(得分:8)
在跳过列表中按排序顺序维护到目前为止最高的x列表。遍历数组。对于每个元素,找到它将在跳过列表中插入的位置(log x time)。如果在列表的内部,它是迄今为止最小的x之一,那么插入它并删除列表末尾的元素。否则什么都不做。
时间O(n * log(x))
替代实现:在最大堆中保持x最高集合,将每个新元素与堆的顶部元素进行比较,并且仅当新元素小于顶部元素时才弹出+插入新元素。由于与top元素的比较是O(1)和pop / insert O(log x),这也是O(nlog(x))
答案 2 :(得分:3)
将所有n个数字添加到堆中并删除其中的x个。复杂性为O((n + x) log n)
。由于x显然小于n,因此它是O(n log n)
。
答案 3 :(得分:3)
如果已知数字范围(L),则可以进行修改后的计数排序。
given L, x, input[]
counts <- array[0..L]
for each number in input
increment counts[number]
next
#populate the output
index <- 0
xIndex <- 0
while xIndex < x and index <= L
if counts[index] > 0 then
decrement counts[index]
output[xIndex] = index
increment xIndex
else
increment index
end if
loop
这有一个O(n + L)的运行时间(内存开销为O(L)),如果范围很小(L
答案 4 :(得分:1)
def x_smallest(items, x):
result = sorted(items[:x])
for i in items[x:]:
if i < result[-1]:
result[-1] = i
j = x - 1
while j > 0 and result[j] < result[j-1]:
result[j-1], result[j] = result[j], result[j-1]
j -= 1
return result
最坏情况是O(x * n),但通常更接近O(n)。
答案 5 :(得分:0)
Psudocode:
def x_smallest(array<int> arr, int limit)
array<int> ret = new array[limit]
ret = {INT_MAX}
for i in arr
for j in range(0..limit)
if (i < ret[j])
ret[j] = i
endif
endfor
endfor
return ret
enddef
答案 6 :(得分:0)
在伪代码中:
y = length of list / 2
if (x > y)
iterate and pop off the (length - x) largest
else
iterate and pop off the x smallest
O(n / 2 * x)?
答案 7 :(得分:0)
sort array
slice array 0 x
选择最佳排序算法,您就完成了:http://en.wikipedia.org/wiki/Sorting_algorithm#Comparison_of_algorithms
答案 8 :(得分:0)
您可以排序然后获取前x个值吗?
使用QuickSort O(n log n)Java:
import java.util.Arrays;
import java.util.Random;
public class Main {
public static void main(String[] args) {
Random random = new Random(); // Random number generator
int[] list = new int[1000];
int lenght = 3;
// Initialize array with positive random values
for (int i = 0; i < list.length; i++) {
list[i] = Math.abs(random.nextInt());
}
// Solution
int[] output = findSmallest(list, lenght);
// Display Results
for(int x : output)
System.out.println(x);
}
private static int[] findSmallest(int[] list, int lenght) {
// A tuned quicksort
Arrays.sort(list);
// Send back correct lenght
return Arrays.copyOf(list, lenght);
}
}
非常快。
答案 9 :(得分:0)
private static int[] x_smallest(int[] input, int x)
{
int[] output = new int[x];
for (int i = 0; i < x; i++) { // O(x)
output[i] = input[i];
}
for (int i = x; i < input.Length; i++) { // + O(n-x)
int current = input[i];
int temp;
for (int j = 0; j < output.Length; j++) { // * O(x)
if (current < output[j]) {
temp = output[j];
output[j] = current;
current = temp;
}
}
}
return output;
}
看看复杂性: O(x +(n-x)* x) - 假设x是某个常数,O(n)
答案 10 :(得分:0)
使用splay tree怎么样?由于splay树采用自适应平衡的独特方法,因此可以实现算法的灵活实现,并且可以在以后按顺序枚举x
项。这是一些伪代码。
public SplayTree GetSmallest(int[] array, int x)
{
var tree = new SplayTree();
for (int i = 0; i < array.Length; i++)
{
int max = tree.GetLargest();
if (array[i] < max || tree.Count < x)
{
if (tree.Count >= x)
{
tree.Remove(max);
}
tree.Add(array[i]);
}
}
return tree;
}
GetLargest
和Remove
操作的摊销复杂度为O(log(n)),但由于最后访问的项目冒泡到顶部,因此通常为O(1)。因此空间复杂度为O(x),运行时复杂度为O(n * log(x))。如果数组恰好已经被排序,则该算法将使用升序或降序有序数组实现其O(n)的最佳情况复杂度。然而,非常奇怪或奇怪的排序可能导致O(n ^ 2)复杂度。您能猜出为了实现这一目标需要如何订购数组吗?
答案 11 :(得分:0)
在scala中,可能还有其他函数式语言,不用脑子:
scala> List (1, 3, 6, 4, 5, 1, 2, 9, 4) sortWith ( _<_ ) take 5
res18: List[Int] = List(1, 1, 2, 3, 4)