这里有一个清单
[9,1,2,11,8]
我需要打印此列表中的前3位,如
[9,11,8]
很容易排序并获取最高值并循环遍历同一个复制列表,以查找给定顺序中的最高值 但我不应该使用新列表来完成这项任务。 这可能吗?
答案 0 :(得分:4)
def k_largest(iterable, k=3):
it = iter(iterable)
result = [next(it) for _ in range(k)] # O(k) space
r_min = min(result)
for elem in it:
if elem > r_min:
result.remove(r_min) # O(n*k) time
result.append(elem)
r_min = min(result)
return result
在平局的情况下,第一个值获胜。如果您希望获得最后一次胜利,只需将>
更改为>=
。
这是大数据和小选择的好方法,即n>> k是n是输入的长度,k是选择的数字。 在这种情况下,k项是无关紧要的,因此该方法是 O(n)时间复杂度,有利于基于排序的方法的 O(n log n)。如果k很大,这将不再是一个好的解决方案。您应该查看维护已排序的结果集,将其平分为插入,并使用quickselect来查找最大值。
使用Python stdlib' s heapq.nlargest
可以获得另一个具有更简单代码的选项,尽管它在实践中通常可能会更慢:
import heapq
from operator import itemgetter
def k_largest_heap(iterable, k=3):
ks = heapq.nlargest(k, enumerate(iterable), key=itemgetter(1))
return [k for i, k in sorted(ks)]
我认为这是 O(n log(k)),虽然我确实在这里达到了我的知识边缘。
一些包含10,000个整数列表的时间:
from random import randint
nums = [randint(1, 10000) for _ in range(10000)]
%timeit k_largest(nums)
# 331 µs ± 4.69 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
%timeit k_largest_heap(nums)
# 1.79 ms ± 27.5 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
%timeit top_three(nums)
# 1.39 ms ± 16.7 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
注意: top_three
实施是用户Delirious Lettuce here的解决方案。
答案 1 :(得分:0)
我会修改select-sort以捕获(n)为MAX而不是一个。而不是运行n2,只需通过列表一次。
所以[9,1,2,11,8]
您使用MAX列表初始化[0,0,0] 然后循环通过你的列表采摘大于MAX的东西
最棘手的部分是第4步,你需要决定保留9和2,并用11替换1。
答案 2 :(得分:0)
您还可以为列表实现包装类。拥有列表中最大值的私有数据成员(在您的情况下为3)。执行插入和删除后更新这些变量。
答案 3 :(得分:0)
我尝试根据您要求的输入和输出创建示例程序。我想过尝试一下。请随时优化或提供反馈。我试着解释代码本身的步骤。谢谢。
package com.test;
import java.util.ArrayList;
import java.util.List;
public class ArrangeList {
public static void main(String[] args) {
List<Integer> givenList = new ArrayList<>();
givenList.add(9);
givenList.add(1);
givenList.add(2);
givenList.add(11);
givenList.add(8);
int currentIndex = 0; //gives the current index
while (givenList.size() != 3) {
int nextIndex = currentIndex + 1; //gives you the next index
int currentValue = givenList.get(currentIndex); //gives you the current value for the current index
int nextValue = givenList.get(nextIndex); //gives you the next value for the next index
if (nextValue < currentValue) { //check if the next value is greater than current value. If true, then remove the next value from the list
givenList.remove(nextIndex);
} else {
currentIndex++; //increment the index if you if the current value is greater than the upcoming value from the list
}
}
System.out.println(givenList); //prints the values stored in the list
}
}
执行程序后的输出是:
[9, 11, 8]
答案 4 :(得分:-1)
编辑:
我很好奇我为什么被投票。 @wim
的解决方案自愿忽略原始问题中关于&#34;的限制,而没有制作新的列表&#34;。唯一的反应是暂时将其改为一个双端队列,以奇怪的方式绕过该限制。目前,这是唯一符合所有OP要求的答案(下面列为两个单独的评论)。
以相同顺序打印列表的最大值而不创建新列表
我需要在此列表中打印前3位,如
此答案假定您需要按原始顺序提取的顶部数字的数量始终为3。如果是这种情况,则此答案似乎为O(n)
时间和O(1)
空格。
def top_three(nums):
if len(nums) <= 3:
return nums
a = b = c = float('-inf')
dex_a = dex_b = dex_c = None
for i, num in enumerate(nums):
if num > a and num > b and num > c:
a, b, c = num, a, b
dex_a, dex_b, dex_c = i, dex_a, dex_b
elif num > b and num > c:
b, c = num, b
dex_b, dex_c = i, dex_b
elif num > c:
c = num
dex_c = i
if dex_a < dex_b < dex_c:
print(a, b, c)
elif dex_a < dex_c < dex_b:
print(a, c, b)
elif dex_b < dex_a < dex_c:
print(b, a, c)
elif dex_b < dex_c < dex_a:
print(b, c, a)
elif dex_c < dex_a < dex_b:
print(c, a, b)
elif dex_c < dex_b < dex_a:
print(c, b, a)
试验:
In[3]: top_three([9, 1, 2, 11, 8])
9 11 8
In[4]: top_three([9, 1, 2, 11, 8, 9])
9 11 9
In[5]: top_three([3, 3, 1, 0, 4, 3, 2, 5])
3 4 5