Algorithm 排列0';标准普尔;1';在一个数组中
这是我最近的一个面试问题之一。我想知道其他人对这个问题的看法 问题: 您将获得一个包含员工详细信息的结构,其中包含两个元素,Algorithm 排列0';标准普尔;1';在一个数组中,algorithm,language-agnostic,Algorithm,Language Agnostic,这是我最近的一个面试问题之一。我想知道其他人对这个问题的看法 问题: 您将获得一个包含员工详细信息的结构,其中包含两个元素,intdepartment和stringname struct Employee { string Name; int Dept; } 给您提供了N名员工的详细信息,其中N/2名员工的Dept==0,N/2名员工的Dept==1,按任意顺序排列。您需要根据员工的Dept值对员工详细信息进行排序,也就是说,应保持原始记录中1和0的顺序 例如,给定以下示例数
int
department和string
name
struct Employee
{
string Name;
int Dept;
}
给您提供了N名员工的详细信息,其中N/2名员工的Dept==0
,N/2名员工的Dept==1
,按任意顺序排列。您需要根据员工的Dept
值对员工详细信息进行排序,也就是说,应保持原始记录中1和0的顺序
例如,给定以下示例数据:
Name Dept
X1 0
X2 1
X3 0
X4 1
X5 0
姓名部门
x10
X2 1
X3 0
X4 1
X5 0
排序后,结果应为:
Name Dept
X2 1
X4 1
X1 0
X3 0
X5 0
姓名部门
X2 1
X4 1
x10
X3 0
X5 0
算法应该是稳定的,时间复杂度应该是O(N),为其他变量提供恒定的空间(这意味着排序应该在适当的位置进行)。分配第二个数组(O(N))。迭代第一个数组,并按第二个数组中出现的顺序移动所有1。再次迭代并将按相同顺序保留的0移动到第二个数组。所有操作为O(N)。这不是原位(就地)解决方案。通过运行一次快速排序分割算法,可获得非稳定的原位解
经过一些研究,似乎没有任何额外内存的已知O(N)解是不稳定的。学术界对有效的0-1稳定原位排序(就地)进行了研究,但解决方案需要一些额外的内存。我想知道最初的问题陈述是否没有以准确的方式复制。没有稳定性要求,问题很容易解决;它也很容易,无需现场要求。由于这两种要求(原位、稳定),解决方案似乎难以实现
在这里的答案中,有一个算法可以在O(N)中工作,并且是原位的,但是只有当关键字段(1)是可变的并且(2)可以包含整数而不是单个位时。这是可行的,但不是原位0-1稳定排序,因为假定每个数组元素都有O(log N)个可写内存。原始问题文本没有提到除整数以外的任何其他字段(此后已编辑)
在这种情况下,稳定性是没有意义的,因为两个相等的数字在其他方面是无法区分的。解决方案是只遍历数组,然后将1的n/2次放入,然后将0的n/2次放入。抽象地说,您可以使用修改后的插入排序,将所有零值向右交换,将所有一个值向左交换。然而,这将具有比O(n)更大的复杂性 我有点困惑,为什么排序很重要,正如前面所说,字节是无法区分的 编辑:新的示例很有帮助。我的算法的好处是,即使在最坏的情况下它比线性时间慢,但它的内存使用率只有O(n)。由于1和0只是较大对象(可能任意大)的键,内存可能是一个问题。简单:
function sort(array):
new_array = new Array(array.length)
x = 0
for(i : array): if(i): new_array(x++) = 1
return new_array
如果你真的想要相同的1和0:
function sort(array):
new_array = new Array(array.length)
x, y = 0, array.length / 2
for(i : array):
if(i): new_array(x++) = i
else: new_array(y++) = i
return new_array
使用
std::stable_partition
以及std::equal_to
和std::binder1st
应该以一种很好的、功能性的、类似STL的方式来完成这项任务:
using namespace std
stable_partition(&array[0], &array[N], binder1st(equal_to(), 1));
当然,这假设数组的元素定义了一些比较运算符(即,您可以说array[i]==1
…)。如果它们只是整数,那么维持顺序就没有任何意义了
至于复杂性:为了成为O(N),
稳定分区
需要额外的内存。如果算法无法分配额外的内存,它将在O(N log N)中执行。好的,下面是我的方法
e、 g a[]={1,0,0,0,1,1,1,0,0,1}
伪代码:
count1=0
和count2=(n/2)+1
if(arr[ i ] == 1)
{
arr[ i ] = count1++;
} else {
arr[ i ] = count2++
};
a[ ] = { 0, 5, 6, 7, 1, 2, 3, 8, 9 4}
for(j = 0; j <= 1; j++)
{
for(i = 0; i<n; i++)
{
if(arr[ i ] != i)
{
swap(arr[ i ], arr[ arr[ i ] ]);
}
}
}
for(j=0;j为了简单起见,使用了整数而不是位,但基本概念是相同的。不同的1和0的顺序并不重要
var emps = new[]
{
new Employee(X1, 0),
new Employee(X2, 1),
new Employee(X3, 0),
new Employee(X4, 1),
new Employee(X5, 0),
new Employee(X6, 1)
};
var sortedEmps = new Employee[bits.Length];
var oneIndex = 0;
var zeroIndex = bits.Length/2;
foreach (var employee in employees)
{
if (employee.Dept == 1)
sortedEmps[oneIndex++] = employee;
else
sortedEmps[zeroIndex++] = employee;
}
更新以解决员工问题。添加了一名额外员工,因为原始问题表示每个问题都有N/2名员工,因此必须有一个偶数才能为真。否则情况相同
不确定现在是否可以编译,所以将其视为伪代码!见鬼,以下是完整的解决方案:
arr是项目列表,item.id为0或1,存储为int。
此代码将0移到前面
count = { 0:0, 1:len(arr)/2 }
for ii in range(len( arr )):
id = arr[ii].id
arr[ii].id = count[id]
count[id] += 1
for ii in range(len( arr )):
while arr[ii].id != ii:
T = arr[ii]
arr[ii] = arr[arr[ii].id]
arr[T.id] = T
for ii in range(len( arr )):
arr[ii].id = (ii >= len(arr)/2)
这是我的(完整的)在C#中尝试一下。它会生成一个列表并随机加入员工,所以你可以随意制作numberOfEmployees
。我意识到可能有一种更简单的方法可以做到这一点,因为最初的海报规定0部门员工与1部门员工数量相等,但我无法控制自己
struct Employee
{
public Employee(string name, int dept)
{
this.name = name;
this.dept = dept;
}
public string name;
public int dept;
}
class Program
{
static void Main(string[] args)
{
int numberOfEmployees = 100;
Random r = new Random();
Employee[] emps = new Employee[numberOfEmployees];
var empBuf = new Employee[numberOfEmployees];
int nextAvail = 0;
// Initialize array of employees with random data
for (int i = 0; i < numberOfEmployees; i++)
{
emps[i] = new Employee("x" + i.ToString(), r.Next(0, 2));
}
Console.WriteLine("Old list:");
foreach (var e in emps)
{
Console.WriteLine("Name: {0}, Dept: {1}", e.name, e.dept);
}
// throw employees with dept == 1 in first
for (int i = 0; i < numberOfEmployees; i++)
{
if (emps[i].dept == 1)
{
empBuf[nextAvail] = emps[i];
nextAvail++;
}
}
// stick the employees with dept == 0 in last
for (int i = 0; i < numberOfEmployees; i++)
{
if (emps[i].dept == 0)
{
empBuf[nextAvail] = emps[i];
nextAvail++;
}
}
Console.WriteLine("New list:");
foreach (Employee e in empBuf)
{
Console.WriteLine("Name: {0}, Dept: {1}", e.name, e.dept);
}
}
}
struct Employee
{
公共员工(字符串名称,内部部门)
{
this.name=名称;
this.dept=dept;
}
公共字符串名称;
公共关系部;
}
班级计划
{
静态void Main(字符串[]参数)
{
int numberOfEmployees=100;
随机r=新随机();
员工[]emps=新员工[员工人数];
var empBuf=新员工[员工人数];
int-nextAvail=0;
//使用随机数据初始化员工数组
对于(int i=0;iuse Modern::Perl;
my @data;
{
use List::MoreUtils qw'natatime';
my $iter = natatime 2, qw'
X1 0
X2 1
X3 0
X4 1
X5 0
';
while( my($a,$b) = $iter->() ){
push @data, [$a,$b]
}
}
my @sorted = sort {
($a->[1] <=> $b->[1]) * -2 + # gives more weight to second element
($a->[0] cmp $b->[0])
} @data;
say "Name\tDept\n";
say join "\t", @$_ for @sorted;
Name Dept
X2 1
X4 1
X1 0
X3 0
X5 0
a b a1 b1 a0 b0
X1,0 -> X2,1 0 --> 1 X1 <- X2
X3,0 -> X4,1 0 --> 1 X3 <- X4
X2,1 <- X4,1 1 - 1 X2 <- X4
X4,1 <- X1,0 1 <-- 0 X4 -> X1
X1,0 <- X3,0 0 - 0 X1 <- X3
X2,1 <<- X5,0 1 <-- 0 X2 <- X5
X5,0 ->> X4,1 0 --> 1 X5 -> X4
X5,0 -> X1,0 0 - 0 X5 -> X1
X5,0 -> X3,0 0 - 0 X5 -> X3
The arrows point at the earlier value.
sort (int [] a) {
int pos = 0;
for (int i = 1; i < a.length; i++) {
if (a[i] == 0 && a[pos] == 1) {
swap(a, pos, i); // this makes all 0's go to the left.
pos++;
}
}
}
#include<stdio.h>
//#include<conio.h>
int main()
{
int i,a[20]={0};
int *ptr1,*ptr2;
//clrscr();
//a[2]=a[4]=a[6]=a[8]=a[16]=1;
a[19]=a[18]=1;
for(i=0;i<20;i++)
printf("%d",a[i]);
printf("\n\nafter");
ptr1=ptr2=a;
for(i=0;i<20;i++)
{
if(*ptr1==0&&*ptr2==1)
{
int temp=*ptr1;*ptr1=*ptr2;*ptr2=temp;
ptr1++;ptr2++;
}
else if(*ptr1==1&&*ptr2==0)
{
ptr1++;ptr2++;
}
else if(*ptr1==0&&*ptr2==0)
{
ptr2++;
}
else
{
if(ptr1<ptr2)
ptr1++;
else
{
ptr1++;ptr2++;
}
}
}
for(i=0;i<20;i++)
{
printf("%d",a[i]);
}
// getch();
return 0;
}
while(s less than end)
{
if(list[s]==1)
{
while(list[end] == 1)
end--;
if(list[end] == 0 && s less than end)
{
tmp = list[s];
list[s] = list[end];
list[end] = tmp;
s++;end--;
}
}
else s++;
}
for(s=0;s less than N;s++)
{
printf("%d ",list[s]);
}
return;
}
private static int[] foo(int[] array) {
int counter = 0;
int i;
for(i = 0; i < array.length; i++) {
if (array[i] == 1) {
array[i] = 0;
counter++;
}
}
while(counter > 0) {
array[--i] = 1;
counter--;
}
return array;
}
left = 0;
right = n-1;
while(left<right){
while(left < right && array[left]==0){
left++;
}
while(left < right && array[right]==1){
right--;
}
while(left<right){
array[left]=0;
array[right]=1;
left++;
right--;
}
}