【发布时间】:2017-12-14 18:58:12
【问题描述】:
是否可以(仅使用一个循环)将所有负整数和正整数移动到数组的任一侧而不使用任何额外的空间?
例如:
Input = [2,-4,45,-3,78,6,5,-72,8]
Output = [-3,-72,-4,2,45,78,8,5,6]
(Output order may Vary)
【问题讨论】:
标签: arrays loops sorting data-structures
是否可以(仅使用一个循环)将所有负整数和正整数移动到数组的任一侧而不使用任何额外的空间?
例如:
Input = [2,-4,45,-3,78,6,5,-72,8]
Output = [-3,-72,-4,2,45,78,8,5,6]
(Output order may Vary)
【问题讨论】:
标签: arrays loops sorting data-structures
这可以使用快速排序分区步骤来解决。在快速排序中,我们根据枢轴对输入数组进行分区。小于枢轴的元素将位于枢轴的左侧,大于枢轴的元素将位于枢轴的右侧。在我们的例子中,我们可以将 0 视为枢轴,并应用与快速排序相同的分区步骤。分区步骤后,数组左边的元素会小于0,右边的元素会大于0。
class Main {
public void swap(int[] array,int x,int y){
int temp = array[x];
array[x] = array[y];
array[y] = temp;
}
public void partition(int[] array){
int posDelim = 0;
for(int i = 0 ; i < array.length ; i++){
if(array[i] < 0){
swap(array,i,posDelim);
posDelim++;
}
}
}
public void printArray(int[] array){
for(int i : array)
System.out.print(i + " ");
System.out.println();
}
public static void main(String[] args) {
int[] array = {2,-4,45,-3,78,6,5,-72,8};
Main obj = new Main();
obj.printArray(array);
obj.partition(array);
obj.printArray(array);
}
}
【讨论】:
重新排列正数和负数
一个简单的解决方案是使用另一个数组。我们将原始数组的所有元素复制到新数组。然后我们遍历新数组,将所有负数和正数元素一个一个复制回原数组。这种方法的问题是它使用辅助数组,我们不允许使用任何数据结构来解决这个问题。一种方法不使用任何数据结构就是使用 QuickSort 的分区过程。这个想法是将 0 视为枢轴并围绕它划分数组。这种方法的问题在于它改变了元素的相对顺序
#include <stdio.h>
void printArray(int arr[], int n)
{
for (int i = 0; i < n; i++)
printf("%d ", arr[i]);
printf("\n"); }
void RearrangePosNeg(int arr[], int n)
{
int key, j;
for(int i = 1; i < n; i++)
{
key = arr[i];
if (key > 0)
continue;
j = i - 1;
while (j >= 0 && arr[j] > 0)
{
arr[j + 1] = arr[j];
j = j - 1;
}
arr[j + 1] = key;
}
}
int main()
{
int arr[] = { -12, 11, -13, -5, 6, -7, 5, -3, -6 };
int n = sizeof(arr) / sizeof(arr[0]);
RearrangePosNeg(arr, n);
printArray(arr, n);
return 0;
}
【讨论】:
等效的 Python 代码:
def swap(array1,x,y):
temp = array1[x]
array1[x]=array1[y]
array1[y]=temp
return array1
array1 = [-2,-4,9,45,-3,78,6,5,-72,8]
index = 0
for i in range(len(array1)-1):
if array1[i] < 0:
swap(array1,i,index)
index += 1
print(array1)
感谢@Mainak 和@Nisar
【讨论】:
基本思想是在数组的开头以一个索引开始,在数组末尾以另一个索引开始。向前移动起始索引,直到遇到一个正数。然后向后移动结束索引,直到找到负数。交换两个值,然后再次开始向前移动起始索引。以这种方式继续,直到索引相遇。
所以,给定您的示例数组:
[2,-4,45,-3,78,6,5,-72,8]
` ^ ^ 开始结束
start 指向一个正数,因此将end 索引向后移动,直到遇到负数:
[2,-4,45,-3,78,6,5,-72,8]
^ ^
start end
交换值
[-72,-4,45,-3,78,6,5,2,8]
^ ^
start end
然后再次将start 索引向前移动,直到找到另一个正数:
[-72,-4,45,-3,78,6,5,2,8]
^ ^
start end
将end 向后移动到下一个负数:
[-72,-4,45,-3,78,6,5,2,8]
^ ^
start end
交换
[-72,-4,-3,45,78,6,5,2,8]
^ ^
start end
向前移动start,你会遇到end,这样你就完成了。
你可以用一个循环来做到这一点。将其编码留作练习。
【讨论】:
def rearrange(self, list):
#Shift all negative at the start of the array
i = -1
for j in range(len(list)):
if list[j] < 0:
i += 1
list[i], list[j] = list[j], list[i]
k = i+1
l=1
while list[k-1] < 0:
if l%2 !=0:
temp = list[k]
list[l+1:k+1] =list[l:k]
list[l] = temp
k += 1
l += 2
else:
l += 1
return list
这个想法是将所有负数移动到数组的开头,然后将指针固定到数组中的第一个正数。遍历所有负数以在 O(n) 和 O(1) 内存的负值 Python 代码之前或之后修复指针上和之后的下一个正整数
【讨论】: