Algorithm 按相对位置对数组排序
给出一个包含负整数和正整数的数组,实现一个算法,花费O(n)个时间和O(1)个空间使所有负整数位于所有正整数之前,并保持相对位置。 例如:{1,7,-5,9,-12,15}------>{-5,-12,1,7,9,15}Algorithm 按相对位置对数组排序,algorithm,position,sorting,Algorithm,Position,Sorting,给出一个包含负整数和正整数的数组,实现一个算法,花费O(n)个时间和O(1)个空间使所有负整数位于所有正整数之前,并保持相对位置。 例如:{1,7,-5,9,-12,15}------>{-5,-12,1,7,9,15} 你有什么想法吗?你要求的是一个稳定的就地配分函数 这篇论文声称有这样一种算法,但有些人对其可行性表示怀疑。我对算法的想法: 具有类似于基于分区的常规选择中的轴心点 围绕轴交换值旋转,直到所有负数都在数组的一个分区中(所有正数都在它后面..或者可能在它周围) 但是,这种交换将稍微
你有什么想法吗?你要求的是一个稳定的就地配分函数
这篇论文声称有这样一种算法,但有些人对其可行性表示怀疑。我对算法的想法: 具有类似于基于分区的常规选择中的轴心点 围绕轴交换值旋转,直到所有负数都在数组的一个分区中(所有正数都在它后面..或者可能在它周围) 但是,这种交换将稍微影响订购。 我将解释如何更正负数的顺序(您也可以这样更正正数的顺序) 每次你交换两个号码。。更改数字的符号 这意味着,如果通过负数分区,所有的正数都是交换的负数。这意味着一个正数和下一个正数之间的所有负数都应该在第一个正数之前。通读并交换它们(一行中不应该有太多,所以你应该得到O(N))
这段代码在大多数情况下都适用。。我只是没有做过这样的部分,它反转x,j和j,y之间交换的值。(你可以在原地倒车……我还没做那件事) 无论如何。。恐怕我没有时间完成,但希望你能:
def brute_force(nums):
neg = [i for i in nums if i<0]
pos = [i for i in nums if i>=0]
return neg+pos
def in_place(nums,i,j,depth):
x,y = i,j
print 'running on ',nums[i:j+1]
if j-i==1:
a,b = nums[i],nums[j]
if a>=0 and b<0:
nums[i],nums[j] = b,a
return None
#print i,j
while i<j:
a,b = nums[i],nums[j]
if (a<0 and b>=0):
i+=1
j-=1
elif (a>=0 and b<0):
nums[i],nums[j]=-b,-a
i+=1
j-=1
elif a<0:
i+=1
else:
j-=1
print "changed1 to ", nums
print nums[x:j+1],nums[j+1:y+1]
start = (i for i in reversed(nums[x:j+1]) if i>=0)
for i in range(x,j):
if nums[i]>=0:
nums[i]=next(start)
print "changed2 to ", nums
end = (i for i in reversed(nums[j+1:y+1]) if i<0)
for i in range(j+1,y+1):
if nums[i]<0:
nums[i]=next(end)
print "changed3 to ", nums
if depth == 0:
in_place(nums,0,j,depth+1)
in_place(nums,j+1,len(nums)-1,depth+1)
nums = [1,2,-4,-5,3,-6]
print brute_force(nums)
in_place(nums,0,len(nums)-1,0)
print nums
print "going z"
#z = [-2,3,-1]
#in_place(z,0,2,0)
#print z
def暴力(nums):
neg=[如果i=0,则i代表nums中的i]
返回负+正
def到位(nums、i、j、深度):
x、 y=i,j
打印“正在运行”,nums[i:j+1]
如果j-i==1:
a、 b=nums[i],nums[j]
如果a>=0且b这可以通过更改合并排序算法中的合并函数来实现
输入:int[]A,int低,int中,int高
开始前循环差异:
[low]到[mid]的数字后面有-ve个数字,后面是+ve个数字,并且数字最初出现在[low]到[mid]的数字中。
上述条件适用于[mid+1]至[high]
合并步骤:
跳过从低到中为-ve的所有元素,将+ve数字的起点保存在变量j中
将mid之前为+ve的其余元素复制到临时数组
从A[j]开始,在递增j的同时,复制中+1到高范围内的所有-ve元素
将存储在临时数组中的元素从j复制回A
+A的下半部分中的ve元素已经就位,因此无需执行任何操作
public static void rearrange(int[] a){
merge_arrange(a, 0, a.length-1);
}
public static void merge_arrange(int[] a, int low, int high){
if(low < high){
int mid = (low+high)/2;
merge_arrange(a, low, mid);
merge_arrange(a, mid+1, high);
merge(a, low, mid, high);
}
}
public static void merge(int[] a, int low, int mid, int high){
ArrayList<Integer> temp = new ArrayList<Integer>();
int i;
for(i=low;i<=mid && a[i]<0;i++);
int j=i;
while(i<=mid){
temp.add(a[i++]);
}
int k;
for(k=mid+1;k<=high && a[k]<0;k++){
a[j] = a[k];
j++;
}
for(int num:temp){
a[j] = num;
j++;
}
}
publicstaticvoid重排(int[]a){
合并排列(a,0,a.length-1);
}
公共静态无效合并排列(int[]a,int低,int高){
如果(低<高){
int mid=(低+高)/2;
合并排列(a、低、中);
合并排列(a、中+1、高);
合并(a、低、中、高);
}
}
公共静态无效合并(int[]a、int-low、int-mid、int-high){
ArrayList temp=新的ArrayList();
int i;
对于(i=low;i参考文献引文:“此外,我们假设有固定数量的额外存储位置,每个存储位置能够存储一个O(log2n)位的字。”我不知道他们为什么称之为O(1)额外空间。(1,2,-4,-5,3,-6)-->(-4,2,1,-5,3,-6)-->(-4,-5,1,-2,3,-6)-->(-4,-5,-6,2,-1)-->(-1,--3)经过5个步骤后,1和2的顺序不正确。我有什么问题吗?你能看到如何将6,5,-4更改为-4,-5,-6?-4应该先执行,因为它没有被交换。6,5以相反的顺序出现在-4之后(因为交换会翻转它们)因此,你的算法只需要从左到右遍历列表,将翻转的一个交换到末尾,并在每次交换时将末尾减少1。然后将未翻转的一个移动到前面的位置。未交换的负数总是在交换的负数之前。我不这么认为,例如1,-4,2,-5,3,-6-->(i=2,j=-5,交换到[1,-4,5,-2,3,-6])-->(i=-4,j=3,然后增加j,减少i,i=1,j=-6,交换到[6,-4,5,-2,3,-1]),然后修复3个负[6,-4,5]-->(i=6,j=-4,交换到[4,-6,5],然后到[-4,-6,-5])。所以非交换和交换是混合的,如何修复到正确的结果?顺便说一下,这个算法是NLOO而不是O(n),因为你应该一次遍历所有左边的数字,T(2n)=2T(n)+n=nlogn。我的算法中,让你到达[6,-4,5]的部分是O(n)。现在你需要把负数移到前面,把正数倒过来,移到后面,得到[-4,5,6],这是答案。我声称最后一步可以在O(n)中完成也在适当的地方。我在我的代码结束时正在做这件事,但没有时间完成如何做。我必须说谢谢你。你不仅要给出你的想法,还要实现你的想法。这是我从你那里学到的,说真的。与你的讨论很愉快。
_list = [1,-4,2,-5,3,-6]
def in_place(nums,i,j,depth):
x,y = i,j
print 'running on ',nums[i:j+1]
if j-i==1:
a,b = nums[i],nums[j]
if a>=0 and b<0:
nums[i],nums[j] = b,a
return None
#print i,j
while i<j:
a,b = nums[i],nums[j]
if (a<0 and b>=0):
i+=1
j-=1
elif (a>=0 and b<0):
nums[i],nums[j]=-b,-a
i+=1
j-=1
elif a<0:
i+=1
else:
j-=1
print "changed1 to ", nums
in_place(_list,0,len(_list)-1,0)
>>>
running on [1, -4, 2, -5, 3, -6]
changed1 to [6, -4, 5, -2, 3, -1]
public static void rearrange(int[] a){
merge_arrange(a, 0, a.length-1);
}
public static void merge_arrange(int[] a, int low, int high){
if(low < high){
int mid = (low+high)/2;
merge_arrange(a, low, mid);
merge_arrange(a, mid+1, high);
merge(a, low, mid, high);
}
}
public static void merge(int[] a, int low, int mid, int high){
ArrayList<Integer> temp = new ArrayList<Integer>();
int i;
for(i=low;i<=mid && a[i]<0;i++);
int j=i;
while(i<=mid){
temp.add(a[i++]);
}
int k;
for(k=mid+1;k<=high && a[k]<0;k++){
a[j] = a[k];
j++;
}
for(int num:temp){
a[j] = num;
j++;
}
}