This is one of an interview question which I had recently. I would like to know others perception of approach for this problem.
Question:
Yo
Okey, here is my approach.
e.g a[] = { 1,0,0,0,1,1,1,0,0,1};
Pseudocode:
count1 = 0
and count2 = (n/2)+1
Traverse through the array,
if(arr[ i ] == 1)
{
arr[ i ] = count1++;
} else {
arr[ i ] = count2++
};
At the end of the traversal, you have array filled with numbers 0 to n-1 like:
a[ ] = { 0, 5, 6, 7, 1, 2, 3, 8, 9 4}
Now the problem comes to sort the above resultant array, this can be done in O(N) as below:
for(j = 0; j <= 1; j++)
{
for(i = 0; i<n; i++)
{
if(arr[ i ] != i)
{
swap(arr[ i ], arr[ arr[ i ] ]);
}
}
}
Note: j loop runs only twice irrespective on 'n' and has constant complexity. The order of this whole loop is 2*n = O(n).
After the array is sorted, Again traverse through the array and set elements arr[0]
to arr[n/2]
to '1'
and arr[(n/2)+1]
to arr[n]
as '0'
.
Space complexity is constant and time complexity is O(step2) + O(step4) + O(step5) = n + 2n +n = 4*n = O(n).
In abstract terms, you could use a modified insertion sort, swapping all zero values to the right and all one values to the left. That would have complexity greater than O(n), however.
I'm slightly confused why ordering matters, as posted previously, bytes are indistinguishable.
EDIT: The new example helps. The benefit of my algorithm, even though it's slower than linear time in the worst case, is that it's only O(n) in memory usage. Since the ones and zeros are only keys for larger objects (which may be arbitrarily large), memory may be a concern.
Here's my (complete) stab at it in C#. It generates the list and sticks random employees in, so make numberOfEmployees
whatever you like. I realize there is probably a simpler way of doing this, because the original poster specified that there are an equal amount of 0-dept employees as 1-dept employees, but I couldn't help myself.
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);
}
}
}
Here is solution that works for an array of int
. You can modify it.
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++;
}
}
}