在Careercup网站上发现了这道面试题:
给定一个有n个整数的数组A。重新排列数组,使得
A[0]<=A[1]>=A[2]<=A[3]>=A[4]<=A[5],以此类推。
编辑:数组未排序,您需要在O(N)的线性时间内完成它。
我无法在线性时间内找到解决方案,最接近的是对数组进行排序然后重新排列元素。 有人能想到如何在线性时间内完成吗?甚至可以在线性时间内完成吗?
我的建议是在nlogn时间内对数组进行排序,然后交替重新排列每个奇数元素i、i-1和i+1。
在Careercup网站上发现了这道面试题:
给定一个有n个整数的数组A。重新排列数组,使得
A[0]<=A[1]>=A[2]<=A[3]>=A[4]<=A[5],以此类推。
编辑:数组未排序,您需要在O(N)的线性时间内完成它。
我无法在线性时间内找到解决方案,最接近的是对数组进行排序然后重新排列元素。 有人能想到如何在线性时间内完成吗?甚至可以在线性时间内完成吗?
我的建议是在nlogn时间内对数组进行排序,然后交替重新排列每个奇数元素i、i-1和i+1。
A B A B A B A
A
都小于或等于每个B
。QuickSelect
算法总是可以在O(n)
的时间复杂度内完成吗?维基百科上确实说在最坏情况下它的时间复杂度是O(n^2)
。 - Luca Angelettifunc wave(inout list: [Int]) {
let evenIndexes = (0..<list.count).filter { $0 % 2 == 0 }
for index in evenIndexes {
if index > 0 && list[index] > list[index-1] {
swap(&list[index], &list[index-1])
}
if index < list.count - 1 && list[index] > list[index+1] {
swap(&list[index], &list[index+1])
}
}
}
这个解决方案基于这里描述的算法。
var test0 = [1,2,3,4,5,6]
wave(&test0)
print(test0) // [1, 3, 2, 5, 4, 6]
var test1 = [4, 6, 2, 1, 3, 7]
wave(&test1)
print(test1) // [4, 6, 1, 3, 2, 7]
var test2 = [20, 9, 4, 2, 0]
wave(&test2)
print(test2) // [9, 20, 2, 4, 0]
该函数有一个for循环
,执行n/2次(仅适用于偶数索引)。因此,for循环的时间复杂度为O(n)
。
在for循环
内部,我们发现了一对if then
语句,两者都在常量时间内执行,因此是O(1)
。
因此,时间复杂度为O(n) * O(1) = O(n)
,其中n是输入数组中的元素数量。
[4, 6, 2, 1, 3, 7]
,输出结果为 [6, 2, 4, 1, 7, 3]
。 - Luca Angeletti20, 9, 4, 2, 0
的输出应该是什么? - Luca Angeletti使用NthElement算法的O(n)解决方案的C#实现:
public void WaveSortTest(int[] a)
{
var nthElement = NthElement(a, a.Length / 2);
var element = a[nthElement];
var odd = 1;
var even = 0;
var r = new int[a.Length];
for (int i = 0; i < a.Length; i++)
{
if (a[i] <= element)
{
r[even] = a[i];
even += 2;
}
else
{
r[odd] = a[i];
odd += 2;
}
}
PrintArray(r);
}
private static readonly Random _rnd = new Random((int)DateTime.Today.ToFileTimeUtc());
private static int NthElement(int[] arr, int k)
{
return NthElement(arr, 0, arr.Length, k);
}
private static int NthElement(int[] arr, int low, int high, int k)
{
var pos = low + _rnd.Next(high - low);
Swap(arr, pos, high - 1);
var i = Partition(arr, low, high);
if (k < i)
{
return NthElement(arr, low, i, k);
}
if (k > i)
{
return NthElement(arr, i + 1, high, k);
}
return i;
}
private static int Partition(int[] arr, int low, int high)
{
var i = low - 1;
for (var j = low; j < high; j++)
{
if (arr[j] <= arr[high - 1])
{
i++;
Swap(arr, i, j);
}
}
return i;
}
private static void Swap<T>(T[] a, int first, int second)
{
var t = a[first];
a[first] = a[second];
a[second] = t;
}
private static void PrintArray(IEnumerable<int> arr)
{
foreach (var item in arr)
{
Console.Write(item + " ");
}
Console.WriteLine();
}