Problem Walkthrough

Max Odd Binary Number LeetCode 2864

Count the total number of 1s in the binary string, reserve one for the last position to guarantee oddness, then place all remaining 1s at the front to maximize the binary value — zeros fill the middle positions between the leading 1s and the trailing 1.

6 min read|

Max Odd Binary Number

LeetCode 2864

Problem Overview

LeetCode 2864 — Maximum Odd Binary Number — gives you a binary string s that is guaranteed to contain at least one "1". Your task is to rearrange the characters of s to form the maximum possible odd binary number and return that number as a string.

A binary number is odd if and only if its last (least significant) bit is 1. Maximizing a binary number means placing the highest-value bits as far left (most significant) as possible. These two requirements — oddness and maximum value — interact in a simple, elegant way that makes this a classic greedy problem.

The input string may contain any mix of "0"s and "1"s with at least one "1". You must use all characters exactly once. Constraints allow strings up to length 10⁵, so O(n) is the target complexity.

  • Rearrange all characters of s to form the largest possible odd binary number
  • A binary number is odd if and only if its last digit is 1
  • Must use every character from s exactly once
  • Input guaranteed to have at least one "1"
  • Constraints: 1 ≤ s.length ≤ 10⁵, s contains only "0" and "1"

Greedy Construction

To maximize a binary number, we want as many 1s as possible in the most significant positions — that is, at the left end of the string. Each position k from the right contributes 2^k to the total value, so a 1 in position k is worth twice a 1 in position k-1. Packing 1s to the left is the only optimal strategy.

To ensure oddness, the last bit must be 1. So we must reserve exactly one "1" for the final position. All remaining 1s go to the front. Zeros fill the gap in between. This construction satisfies both constraints simultaneously and cannot be improved upon.

This is greedy at its most transparent: a single scan to count 1s and zeros, then direct construction. No sorting, no backtracking, no dynamic programming. The problem reduces to arithmetic on character counts.

💡

The Greedy Formula

The greedy strategy is: (ones - 1) leading 1s + all zeros + one trailing 1. This maximizes value by placing as many 1s as possible at the most significant positions while guaranteeing oddness with the mandatory trailing 1.

Algorithm

The algorithm is a two-step process: count, then construct. Count the number of 1s in the string (ones = s.count("1") in Python). The number of zeros follows as zeros = len(s) - ones. Construct the result as "1" * (ones - 1) + "0" * zeros + "1".

This is O(n) time because counting the characters requires one pass and building the result string requires another. Space is O(n) for the output string. No extra data structures are needed.

The formula works for all valid inputs: if ones == 1, the result is zeros zeros followed by a single trailing 1 — the smallest possible odd number using those characters. If ones == len(s) (all 1s), the result is (len(s) - 1) leading 1s and a trailing 1, which is just all 1s reordered identically.

  1. 1Count ones = s.count("1")
  2. 2Derive zeros = len(s) - ones
  3. 3Build result = "1" * (ones - 1) + "0" * zeros + "1"
  4. 4Return result

Why This Maximizes

Binary value depends on position. The leftmost bit has the highest place value: position k from the right contributes 2^k. A 1 in the most significant position is worth more than all lower positions combined. Therefore, placing all available 1s as far left as possible is always optimal.

The trailing 1 is unavoidable — without it the number would be even. But it sits at position 0 (value 1), the least significant position. Any swap that moved this trailing 1 leftward would either create an even number (if we left a 0 at the end) or require moving a 1 from the left to the right (decreasing overall value). Neither helps.

No arrangement can outperform (ones-1) leading 1s + all zeros + trailing 1. We have used every available 1 in the highest possible positions while satisfying the oddness constraint. This greedy argument is tight: any deviation from this layout produces a strictly smaller or even number.

ℹ️

Why No Swap Can Improve It

This is greedy at its simplest: the most significant positions get 1s first because each position is worth 2x the next. No swapping can improve the result — moving a 1 from the left to any other position decreases value, and moving the trailing 1 leftward would require either leaving a 0 at the end (making it even) or swapping with another 1 (net zero gain).

Walk-Through Example

Consider s = "010". We have ones = 1, zeros = 2. Result = "1" * (1-1) + "0" * 2 + "1" = "" + "00" + "1" = "001". In decimal that is 1 — the only odd number we can form from one 1 and two 0s. Any other arrangement ("010" = 2, "100" = 4) is even, so "001" is the correct answer.

Consider s = "0101". We have ones = 2, zeros = 2. Result = "1" * 1 + "0" * 2 + "1" = "1001". In decimal that is 9. The other candidate arrangements that end in 1 include "0101" = 5 and "0011" = 3 and "1001" = 9. Our greedy picks 9, the maximum.

Both examples confirm the pattern: leading 1s first, zeros in the middle, trailing 1 at the end. The formula is deterministic and requires no comparison between candidate strings.

  1. 1s = "010": ones=1, zeros=2 → result = "" + "00" + "1" = "001" (decimal 1)
  2. 2s = "0101": ones=2, zeros=2 → result = "1" + "00" + "1" = "1001" (decimal 9)
  3. 3"1001" is the maximum odd arrangement of digits 0, 1, 0, 1
  4. 4All other arrangements ending in 1 ("0101"=5, "0011"=3) are smaller

Code Walkthrough — Python and Java

In Python, the solution is a one-liner: return "1" * (s.count("1") - 1) + "0" * s.count("0") + "1". For clarity, split into ones = s.count("1"); zeros = len(s) - ones; return "1" * (ones - 1) + "0" * zeros + "1". String repetition in Python is O(n), so the total time is O(n).

In Java, use StringBuilder: int ones = 0; for (char c : s.toCharArray()) if (c == "1") ones++; int zeros = s.length() - ones; StringBuilder sb = new StringBuilder(); for (int i = 0; i < ones - 1; i++) sb.append("1"); for (int i = 0; i < zeros; i++) sb.append("0"); sb.append("1"); return sb.toString(). Same O(n) time and O(n) space.

Time complexity is O(n) for both count and construction passes. Space complexity is O(n) for the output string. The solution handles all edge cases within the problem constraints: ones ≥ 1 is guaranteed, so ones - 1 ≥ 0 and the leading block is always valid.

⚠️

Edge Case: Only One 1

The problem guarantees at least one 1 exists, but if ones == 1, then ones - 1 == 0 and the leading block is an empty string — that is correct. The result is all zeros followed by a trailing 1. Do not subtract 1 from 0 ones; that case cannot occur given the problem constraints, but if ones were 0 you would get an invalid result of -1 leading 1s.

Ready to master algorithm patterns?

YeetCode flashcards help you build pattern recognition through active recall and spaced repetition.

Start practicing now