我在C编程。在少于,等于和大于某个值x
的元素上吐出数组的最佳方法(我的意思是线性时间)是什么。
例如,如果我有数组
{1, 4, 6, 7, 13, 1, 7, 3, 5, 11}
和x = 7
那么它应该是
{1, 4, 6, 1, 3, 5, 7, 7, 13, 11 }
我不想对元素进行排序,因为我需要更有效的方法。当然,在此示例中,可以是{1, 4, 6, 1, 3, 5}
和{13, 11}
的任何排列。
我的理解:比数组中的某些元素更少或更大......在这个例子中它是7。
我的功能是:
int x = 7;
int u =0, z = 0;
for(int i=0; i<size-1; i++) // size - 1 because the last element will be choosen value
{
if(A[i] == x)
swap(A[i], A[u]);
else if(A[i] == x)
{
swap(A[i], A[n-(++z)]);
continue;
}
i++
}
for(int i = 0; i<z; i++)
swap(A[u+i],A[size-(++z)];
其中u是当前较少元素的数量,z是等于元素的数量
但是如果我有数组中的每个元素等于那里它不起作用(大小 - (++ z))是低于0
答案 0 :(得分:4)
这是所谓的Dutch national flag problem,以三条条纹的荷兰国旗命名。 (由荷兰人EW Dijkstra命名。)它类似于实现快速排序所需的partition
函数,但在快速排序的大多数解释中,提出了一种双向分区算法,而在这里我们正在寻找一个三分区。经典的快速分配算法将矢量分为两部分,一部分由不大于枢轴的元素组成,另一部分由严格更大的元素组成。 [见注1]
维基百科文章为Dijkstra的解决方案提供了伪代码,该解决方案(与通常在快速排序的讨论中提出的经典分区算法不同)从向左移动到向量:
void dutchflag(int* v, size_t n, int x) {
for (size_t lo = 0, hi = n, j = 0; j < hi; ) {
if (v[j] < x) {
swap(v, lo, j); ++lo; ++j;
} else if (v[j] > x) {
--hi; swap(v, j, hi);
} else {
++j;
}
}
还有另一种算法,由Bentley和McIlroy于1993年发现并发表在他们的论文"Engineering a Sort Function"中,其中有一些很好的图表说明了各种分区函数的工作原理,以及一些关于分区算法为何重要的讨论。宾利&amp;如果枢轴元素在列表中不常出现,则McIlroy算法更好,而Dijkstra在经常出现时更好,因此您必须了解有关数据的信息才能在它们之间进行选择。我相信大多数现代快速排序算法都使用Bentley&amp; McIlroy,因为常见的情况是要排序的数组几乎没有重复。
答案 1 :(得分:1)
你可以这样做:
1)循环遍历数组,如果element小于x,则将其放入新的array1中
2)如果元素大于x,则放入新的array2
这是线性时间O(n)
答案 2 :(得分:0)
我尝试过下面这样的事情,我认为是O(n)。我花了一点时间来解决这个问题,但我认为它与上面的荷兰标志答案非常相似。
我的ouptput
a.exe
1 4 6 5 3 1 7 7 11 13
1 4 5 6 3 1 7 7 7 11 13
代码:
#define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0]))
void order(int * list, int size, int orderVal)
{
int firstIdx, lastIdx, currVal, tempVal;
firstIdx = 0;
lastIdx = size-1;
for ( ;lastIdx>firstIdx;firstIdx++)
{
currVal = list[firstIdx];
if (currVal >= orderVal)
{
tempVal = list[lastIdx];
list[lastIdx] = currVal;
lastIdx--;
list[firstIdx] = tempVal;
if (tempVal >= orderVal)
firstIdx--;
}
}
lastIdx = size-1;
for( ;lastIdx>firstIdx && middleNum>0;lastIdx--)
{
currVal = list[lastIdx];
if (currVal == orderVal)
{
tempVal = list[firstIdx];
list[firstIdx] = currVal;
firstIdx++;
list[lastIdx] = tempVal;
if (tempVal == orderVal)
lastIdx++;
}
}
}
int main(int argc, char * argv[])
{
int i;
int list[] = {1, 4, 6, 7, 13, 1, 7, 3, 5, 11};
int list2[] = {1, 4, 7, 6, 7, 13, 1, 7, 3, 5, 11};
order(list, ARRAY_SIZE(list), 7);
for (i=0; i<ARRAY_SIZE(list); i++)
printf("%d ", list[i]);
printf("\n");
order(list2, ARRAY_SIZE(list2), 7);
for (i=0; i<ARRAY_SIZE(list2); i++)
printf("%d ", list2[i]);
}
答案 3 :(得分:-1)
以下是使用冒泡排序的示例。哪种类型的排序算法最好,取决于您,这只是为了演示。在这里,我对待价值&lt; x为-1
,值== x为0
,值为&gt; x为1
。
注意元素&lt; x和那些&gt; x仍然是相同的序列。
#include <stdio.h>
int main(void)
{
int array[] = { 1, 4, 6, 7, 13, 1, 7, 3, 5, 11 };
int x = 7;
int len = sizeof array / sizeof array[0];
int i, j, m, n, tmp;
for (i=0; i<len-1; i++) {
m = array[i] < x ? -1 : array[i] == x ? 0 : 1;
for (j=i+1; j<len; j++) {
n = array[j] < x ? -1 : array[j] == x ? 0 : 1;
if (m > n) {
tmp = array[i]; // swap the array element
array[i] = array[j];
array[j] = tmp;
m = n; // and replace alias
}
}
}
for(i=0; i<len; i++)
printf("%d ", array[i]);
printf("\n");
return 0;
}
节目输出:
1 4 6 1 3 5 7 7 13 11