LeetCode #2149 Medium

Rearrange Array Elements by Sign

Rearrange Array Elements by Sign is LeetCode 2149 (Medium). You are given an integer array nums of even length that holds exactly as many positive numbers as negative ones. No element is zero.

Return the array rearranged so that all three conditions hold:

  • Signs alternate: every pair of neighbours has opposite signs.
  • Order is kept inside each sign: the positives appear in the same order they had in nums, and so do the negatives.
  • Positive first: the result starts with a positive number.

The array can hold up to 2 × 10⁵ elements, so the answer should come from a single linear pass rather than repeated shifting.

Constraints
  • 2 <= nums.length <= 2 * 10⁵
  • nums.length is even
  • 1 <= |nums[i]| <= 10⁵
  • nums consists of equal number of positive and negative integers.
arraytwo-pointers
Open on LeetCode ↗
02

Intuition

The three rules fix the answer completely. Positive first plus alternation means every positive sits at an even index and every negative at an odd one. Keeping each sign's order means the k-th positive read from nums must land on the k-th even slot, and the k-th negative on the k-th odd slot.

So nothing has to be searched or swapped. Read nums once and send each number to the next free slot of its own lane. Because the input is read in order and each lane fills in order, stability comes for free, and the equal-count guarantee makes both lanes fill up exactly as the input runs out.

How to spot this pattern

When the final position of each element is decided by a simple rule (its parity, its rank within a group), compute the position and write straight into a result array instead of moving elements around. Here the rule is "k-th positive goes to index 2k, k-th negative to index 2k + 1", which two strided pointers produce without ever computing k.

03

Approach

Try it first

Before reading on: write down which index the 3rd positive number must end up at, and which index the 3rd negative must end up at. Then aim for one pass and O(n) time.

1

Allocate the result

Create res with the same length as nums. Writing into a separate array lets each element go straight to its final slot without disturbing anything still unread.

2

Set the two lane pointers

pos = 0 is the next free even slot and neg = 1 the next free odd slot. Starting pos at 0 is what makes the answer begin with a positive.

3

Place each element in one pass

  • Positive x: res[pos] = x, then pos += 2.
  • Negative x: res[neg] = x, then neg += 2.

The step of 2 keeps each pointer inside its own lane and leaves the slot in between for the other sign.

4

Return res

With n/2 numbers of each sign, every even and every odd slot is written exactly once, so res alternates, starts positive and keeps both orders. It is the only array that does, so it is the answer.

04

Rearrange Array Elements by Sign solution in Python | C++ | Java

▶1class Solution:
▶2 def rearrangeArray(self, nums: List[int]) -> List[int]:
▶3 res = [0] * len(nums)
▶4 pos, neg = 0, 1
▶5 for x in nums:
▶6 if x > 0:
▶7 res[pos] = x
▶8 pos += 2
▶9 else:
▶10 res[neg] = x
▶11 neg += 2
▶12 return res
numsres03+0↑ pos11−1↑ neg2-2+23-5−342+45-4−5pos = 0, neg = 1
res[_, _, _, _, _, _]n = 6 empty slots
pos0next even slot
neg1next odd slot
Every slot is already decided. Starting positive and alternating means positives own indices 0, 2, 4… and negatives own 1, 3, 5…. Keeping order means the 1st positive takes the 1st even slot, the 2nd takes the 2nd, and so on. So one pointer per lane is enough: pos = 0, neg = 1.
numsres03P130P111−1↑ neg2-2+2↑ pos3-5−342+45-4−5P1 → res[0]
x3positive
res[0]3
pos2moved by 2
3 is positive, the 1st one so far, so it belongs in the 1st even slot, which is exactly where pos points: index 0. Then pos jumps 2 to 2, skipping the odd slot between, which belongs to a negative.
numsres03P130P111P2−1↑ neg2-212P23-5−342+4↑ pos5-4−5P2 → res[2]
x1positive
res[2]1
pos4moved by 2
1 is positive, the 2nd one so far, so it belongs in the 2nd even slot, which is exactly where pos points: index 2. Then pos jumps 2 to 4, skipping the odd slot between, which belongs to a negative.
numsres03P130P111P2-21N12-2N112P23-5−3↑ neg42+4↑ pos5-4−5N1 → res[1]
x-2negative
res[1]-2
neg3moved by 2
-2 is negative, the 1st one so far, so it goes to the 1st odd slot: index 1. neg jumps 2 to 3.
numsres03P130P111P2-21N12-2N112P23-5N2-53N242+4↑ pos5-4−5↑ negN2 → res[3]
x-5negative
res[3]-5
neg5moved by 2
-5 is negative, the 2nd one so far, so it goes to the 2nd odd slot: index 3. neg jumps 2 to 5.
numsres03P130P111P2-21N12-2N112P23-5N2-53N242P324P35-4−5↑ negP3 → res[4]
x2positive
res[4]2
pos6moved by 2
2 is positive, the 3rd one so far, so it belongs in the 3rd even slot, which is exactly where pos points: index 4. Then pos jumps 2 to 6, skipping the odd slot between, which belongs to a negative.
numsres03P130P111P2-21N12-2N112P23-5N2-53N242P324P35-4N3-45N3N3 → res[5]
x-4negative
res[5]-4
neg7moved by 2
-4 is negative, the 3rd one so far, so it goes to the 3rd odd slot: index 5. neg jumps 2 to 7. Both pointers have now run off the end together, which is the equal-count guarantee at work.
numsres03P130P111P2-21N12-2N112P23-5N2-53N242P324P35-4N3-45N3return res: alternates, order kept
result[3, -2, 1, -5, 2, -4]
Done in one pass. Read the tags under res: P1, N1, P2, N2… Positives appear in the order they had in nums, and so do negatives, because each lane was filled in reading order. No element was ever moved twice.
05

Split, then interleave

One pass collects the positives and the negatives in their original order. A second loop writes the i-th positive to index 2i and the i-th negative to index 2i + 1.

▶1class Solution:
▶2 def rearrangeArray(self, nums: List[int]) -> List[int]:
▶3 positives = [x for x in nums if x > 0]
▶4 negatives = [x for x in nums if x < 0]
▶5 res = [0] * len(nums)
▶6 for i in range(len(positives)):
▶7 res[2 * i] = positives[i]
▶8 res[2 * i + 1] = negatives[i]
▶9 return res
06

Common pitfalls

Swapping in place to fix wrong-sign slots

✗ Wrong
for i in range(len(nums)):
    if wrong_sign(i):
        j = next_with_other_sign(i)
        nums[i], nums[j] = nums[j], nums[i]
✓ Right
res = [0] * len(nums)
# write each x to its lane pointer

A swap sends nums[i] to position j, jumping over elements of the same sign and breaking their relative order. Keeping order in place needs a rotation instead of a swap, which is O(n) per fix and O(n²) overall.

Advancing a pointer by 1

✗ Wrong
res[pos] = x
pos += 1
✓ Right
res[pos] = x
pos += 2

With a step of 1 the positive pointer walks onto odd slots, and a later negative overwrites a positive already written there. Each lane has to skip the other lane's slot.

Starting the pointers the wrong way round

✗ Wrong
pos, neg = 1, 0
✓ Right
pos, neg = 0, 1

The output still alternates and keeps both orders, so it looks right, but it starts with a negative. The problem requires a positive at index 0.

07

Complexity

Time
O(n)
Space
O(n)
Each element is read once and written once. The result array is n long; the pointers are O(1) extra. The returned array is required output, so beyond it the extra space is O(1).
08

Rearrange Array Elements by Sign FAQ

Can rearrange array elements by sign LeetCode 2149 be done in place?

Not in linear time while keeping the relative order. A stable in-place rearrangement needs rotations, which cost O(n²) in the simple form. The two-pointer version with a result array is the accepted answer.

What if the numbers of positives and negatives are not equal?

That is the follow-up variant of rearrange array by sign (on GFG, Alternate positive and negative numbers). Split the numbers into a positive list and a negative list, interleave while both have elements, then append whatever is left of the longer list in its original order.