我有一个我认为可行的实现(用 C# 编码):
public static int[] LastKHighestValues(int[] array, int k)
{
int[] maxes = new int[array.Length];
int indexOfCurrentMax = 0;
int indexOfNextMax = 0;
for (int i = 0; i < array.Length; i++)
{
if (indexOfNextMax <= indexOfCurrentMax ||
array[i] > array[indexOfNextMax])
{
indexOfNextMax = i;
}
if (i - indexOfCurrentMax >= k)
{
indexOfCurrentMax = indexOfNextMax;
}
if (array[i] > array[indexOfCurrentMax])
{
indexOfCurrentMax = i;
}
maxes[i] = array[indexOfCurrentMax];
}
return maxes;
}
这个想法是你保留两个“指针”:一个指向当前最大值,一个指向当前最大值到期后要转到的下一件事。这可以通过数组一次性实现(所以 O(n))。
我有一些通过测试,但我不能确定我已经涵盖了所有极端情况:
Puzzle.LastKHighestValues(new[] {4, 3, 1}, 1).Should().Equal(new[] {4, 3, 1});
Puzzle.LastKHighestValues(new[] { 7, 7, 7 }, 3).Should().Equal(new[] { 7, 7, 7 });
Puzzle.LastKHighestValues(new[] { 7, 7, 7 }, 4).Should().Equal(new[] { 7, 7, 7 });
Puzzle.LastKHighestValues(new[] { 3, 2, 1 }, 2).Should().Equal(new[] { 3, 3, 2 });
Puzzle.LastKHighestValues(new[] { 7, 1, 4, 1, 1 }, 3).Should().Equal(new[] { 7, 7, 7, 4, 4 });
Puzzle.LastKHighestValues(new[] { 7, 8, 4, 9, 10 }, 2).Should().Equal(new[] { 7, 8, 8, 9, 10 });