面试问题: 给定这种形式的排序数组:
1,2,3,4,5,6,7,8,9
(一个更好的例子是10,20,35,42,51,66,71,84,99,但让我们在上面使用) 无需使用额外的内存或标准库即可将其转换为以下低位形式
1,9,2,8,3,7,4,6,5
从低到高的形式表示我们使用最小的然后是最高的。然后我们使用第二小的和第二高的。
最初,当他询问时,我使用了辅助数组并使用了2指针方法。我把一个指针放在前面,最后把第二个指针放在前面。然后我将左右数据一一复制到我的新数组中,然后向左移动为左++,向右移动为--right,直到它们交叉或变得相同为止。
此后,他要求我无记忆地做。
我在没有记忆的情况下解决该问题的方法如下。但这令人困惑并且无法正常工作
1) swap 2nd and last in **odd** (pos index 1)
1,2,3,4,5,6,7,8,9 becomes
1,9,3,4,5,6,7,8,2
then we reach even
2) swap 3rd and last in **even** (pos index 2 we are at 3 )
1,9,3,4,5,6,7,8,2 becomes (swapped 3 and 2_ )
1,9,2,4,5,6,7,8,3
and then sawp 8 and 3
1,9,2,4,5,6,7,8,3 becomes
1,9,2,4,5,6,7,3,8
3) we reach in odd (pos index 3 we are at 4 )
1,9,2,4,5,6,7,3,8
becomes
1,9,2,8,5,6,7,3,4
4) swap even 5 to last
and here it becomes wrong
答案 0 :(得分:0)
好的,假设在空间常数不变的情况下,我们需要损失一些时间复杂度,以下算法可能在O(n ^ 2)时间复杂度下工作。
我用python写的。我写得很快,因此对任何语法错误都道歉。
chrome://extensions/?errors=<extension-id>
快速说明:
假设给我们的初始列表是:
# s is the array passed.
def hi_low(s):
last = len(s)
for i in range(0, last, 2):
if s[i+1] == None:
break
index_to_swap = last
index_to_be_swapped = i+1
while s[index_to_be_swapped] != s[index_to_swap]:
# write your own swap func here
swap(s[index_to_swap], s[index_to_swap-1])
index_to_swap -=1
return s
因此,在我们的程序中,最初是
1 2 3 4 5 6 7 8 9
表示它指向9,而
index_to_swap = last
是i + 1,即比当前循环指针领先一步。 [也请记住,我们的循环差为2]。
所以最初,
index_to_be_swapped = i+1
,在内部循环中,我们要检查的是:直到这两个索引中的值相同,我们才继续进行交换 swap(s [index_to_swap],s [index_to_swap-1])
因此它看起来像:
i = 0
index_to_be_swapped = 1
index_to_swap = 9
现在,完成了内部循环的工作,并使用再次运行主循环
# initially:
1 2 3 4 5 6 7 8 9
^ ^---index_to_swap
^-----index_to_be_swapped
# after 1 loop
1 2 3 4 5 6 7 9 8
^ ^-----index_to_swap
^----- index_to_be_swapped
... goes on until
1 9 2 3 4 5 6 7 8
^-----index_to_swap
^-----index_to_be_swapped
此过程一直持续到2。
因此,外循环运行几乎n \ 2次,在最坏的情况下,内循环对于每个外循环运行几乎n \ 2次,因此如果n / 2 * n / 2 = n ^ 2,则时间复杂度/ 4,即n ^ 2的阶数,即O(n ^ 2)。
如果有任何错误,请随时指出。 希望这会有所帮助!
答案 1 :(得分:0)
它将适用于任何排序的数组
let arr = [1, 2, 3, 4, 5, 6, 7, 8, 9];
let i = arr[0];
let j = arr[arr.length - 1];
let k = 0;
while(k < arr.length) {
arr[k] = i;
if(arr[k+1]) arr[k+1] = j;
i++;
k += 2;
j--;
}
console.log(arr);
说明:由于它是一个排序数组,因此您需要知道3件事才能产生预期的输出。
let i = arr[0]
let j = arr[arr.length -1]
arr.length
遍历数组并像这样设置值
arr[firstIndex] = firstValue, arr[thirdIndex] = firstValue + 1 and so on..
arr[secondIndex] = lastValue, arr[fourthIndex] = lastValue - 1 and so on..
很显然,您可以用不同的方式来做相同的事情。但是我认为这是最简单的方法。
答案 2 :(得分:0)
让我首先指出,即使寄存器也是一种存储器。没有任何“额外”内存(除了已排序数组所占用的内存之外),我们什至没有计数器!也就是说,去了:
让a
是n > 2
个正整数的数组,这些数组按升序排序,位置从0
到n-1
索引。
从i = 1
到n-2
,对子数组进行泡沫排序,范围从位置i
到位置n-1
(包括端值),包括降序和升序。 (这意味着如果i
为奇数,则按降序对气泡进行排序,如果为偶数,则按升序对气泡进行排序。)
由于与bubble-sort相比,您只需要比较并可能交换相邻的元素,就不需要“额外的”内存。
(请注意,如果您从i = 0
开始并首先以升序排序,则您甚至都不需要a
进行预排序。)
还有另一件事:由于您的问题中没有提及,我将对上述算法的性能保持沉默...
答案 3 :(得分:0)
我们将进行n / 2次传递,并且在每次传递过程中,我们将从左至右交换每个元素,从位置2k-1的元素开始,与最后一个元素交换。示例:
pass 1
V
1,2,3,4,5,6,7,8,9
1,9,3,4,5,6,7,8,2
1,9,2,4,5,6,7,8,3
1,9,2,3,5,6,7,8,4
1,9,2,3,4,6,7,8,5
1,9,2,3,4,5,7,8,6
1,9,2,3,4,5,6,8,7
1,9,2,3,4,5,6,7,8
pass 2
V
1,9,2,3,4,5,6,7,8
1,9,2,8,4,5,6,7,3
1,9,2,8,3,5,6,7,4
1,9,2,8,3,4,6,7,5
1,9,2,8,3,4,5,7,6
1,9,2,8,3,4,5,6,7
pass 3
V
1,9,2,8,3,4,5,6,7
1,9,2,8,3,7,5,6,4
1,9,2,8,3,7,4,6,5
1,9,2,8,3,7,4,5,6
pass 4
V
1,9,2,8,3,7,4,5,6
1,9,2,8,3,7,4,6,5
这应该进行O(n ^ 2)交换,并且除了所涉及的计数器之外,不使用额外的内存。
要证明的循环不变性是循环的迭代k之后,前2k + 1个位置是正确的。