Hello Everyone,
Given an array of positive and negative numbers, arrange them such that all negative integers appear before all the positive integers in the array without using any additional data structure like a hash table, arrays, etc. The order of appearance should be maintained.
Examples:
Input : arr[] = [12, 11, -13, -5, 6, -7, 5, -3, -6] Output : arr[] = [-13, -5, -7, -3, -6, 12, 11, 6, 5] Input : arr[] = [-12, 11, 0, -5, 6, -7, 5, -3, -6] Output : arr[] = [-12, -5, -7, -3, -6, 0, 11, 6, 5]
Approach : There is another method to do so. In c++ STL, There is an inbuilt function std::sort(). We can modify the comp() function to obtain the desired result. As we have to place negative numbers first and then positive numbers. We also have to keep zero’s(if present) between positive and negative numbers.
The comp() function in this code rearranges the given array in the required order. Here in bool comp(int a, int b) , if integer ‘a’ is of j-th index and integer ‘b’ is of i-th index elements in the arr[], then j>i. comp() function will be called in this way. If the comp() return true then swap will be done.
- C++
// CPP program to rearrange positive
// and negative integers keeping
// order of elements.
#include <bits/stdc++.h>
using
namespace
std;
bool
comp(
int
a,
int
b)
{
// swap not needed
if
((a > 0 && b > 0) ||
(a < 0 && b < 0) ||
(a > 0 && b < 0 ))
return
false
;
// swap needed
if
(a < 0 && b > 0)
return
true
;
// swap not needed
if
((a == 0 && b < 0) ||
(a > 0 && b == 0))
return
false
;
// swap needed
if
((a == 0 && b > 0) ||
(a < 0 && b == 0))
return
true
;
}
void
rearrange(
int
arr[],
int
n)
{
sort(arr, arr + n, comp);
}
// Driver code
int
main()
{
int
arr[] = { -12, 11, -13, -5,
6, -7, 5, -3, -6 };
int
n =
sizeof
(arr) /
sizeof
(arr[0]);
rearrange(arr, n);
for
(
int
i = 0; i < n; i++)
cout <<
" "
<< arr[i];
return
0;
}
Output:
-12 -13 -5 -7 -3 -6 11 6 5
Time complexity is the same as sorting i.e. O(n log n) . As we are using the standard sort function. But it is really faster because the inbuilt sort function uses introsort.
Approach 4: There is yet another method to solve this problem. We recursively traverse the array cutting it into two halves ( array[start…start] & array[(start + 1)…end] , and keep on splitting the array till we reach the last element. Then we start merging it back. The idea is to, at any point, keep the array in the proper sequence of negative and positive integers. The merging logic would be:
(I) If the array[start] is negative, merge the rest of the array as it is so that the negative numbers’ order is maintained. The reason for this is that since we are tracing back from the recursive calls, we start moving right to left through the array, thus, naturally maintaining the original sequence.
(II) If the array[start] is positive, merge the rest of the array, but, after right-rotating the half of the array[(start + 1)…end] . The idea for the rotation is to merge the array so that the positive array[start] is always merged with the positive elements. But, the only thing here is that the merged array will have all the positive elements on the left and negative elements on the right. So we reverse the sequence in each recursion to get back the original sequence of negative elements and then positive elements subsequently.
It can be observed since we reverse the array while merging with a positive first element in each recursion, so the sequence of positive elements, although coming after the negative elements, are in reverse order. So, as a final step, we reverse only the positive half of the final array, and, subsequently getting the intended sequence.
Below is the implementation of the above approach:
- C++
// C++ implementation of
// the above approach
#include <iostream>
void
printArray(
int
array[],
int
length)
{
std::cout <<
"["
;
for
(
int
i = 0; i < length; i++)
{
std::cout << array[i];
if
(i < (length - 1))
std::cout <<
", "
;
else
std::cout <<
"]"
<< std::endl;
}
}
void
reverse(
int
array[],
int
start,
int
end)
{
while
(start < end)
{
int
temp = array[start];
array[start] = array[end];
array[end] = temp;
start++;
end--;
}
}
// Rearrange the array with all negative integers
// on left and positive integers on right
// use recursion to split the array with first element
// as one half and the rest array as another and then
// merge it with head of the array in each step
void
rearrange(
int
array[],
int
start,
int
end)
{
// exit condition
if
(start == end)
return
;
// rearrange the array except the first
// element in each recursive call
rearrange(array, (start + 1), end);
// If the first element of the array is positive,
// then right-rotate the array by one place first
// and then reverse the merged array.
if
(array[start] >= 0)
{
reverse(array, (start + 1), end);
reverse(array, start, end);
}
}
// Driver code
int
main()
{
int
array[] = {-12, -11, -13, -5, -6, 7, 5, 3, 6};
int
length = (
sizeof
(array) /
sizeof
(array[0]));
int
countNegative = 0;
for
(
int
i = 0; i < length; i++)
{
if
(array[i] < 0)
countNegative++;
}
std::cout <<
"array: "
;
printArray(array, length);
rearrange(array, 0, (length - 1));
reverse(array, countNegative, (length - 1));
std::cout <<
"rearranged array: "
;
printArray(array, length);
return
0;
}
Output:
array: [-12, -11, -13, -5, -6, 7, 5, 3, 6] rearranged array: [-12, -11, -13, -5, -6, 7, 5, 3, 6]
Time complexity: O(N)