diff --git a/problems/2161-partition-array-according-to-given-pivot/analysis_daily_20260608.md b/problems/2161-partition-array-according-to-given-pivot/analysis_daily_20260608.md new file mode 100644 index 0000000..210dcdd --- /dev/null +++ b/problems/2161-partition-array-according-to-given-pivot/analysis_daily_20260608.md @@ -0,0 +1,101 @@ +# 2161. Partition Array According to Given Pivot + +[LeetCode Link](https://leetcode.com/problems/partition-array-according-to-given-pivot/) + +Difficulty: Medium +Topics: Array, Two Pointers, Simulation +Acceptance Rate: 90.1% + +## Hints + +### Hint 1 + +This problem is really a *stable partition*. Notice the three buckets that the +result must contain, in order: elements `< pivot`, then elements `== pivot`, +then elements `> pivot`. Whenever you see "group items into ordered categories +while preserving relative order," think about a single linear scan that decides +which bucket each element belongs to. + +### Hint 2 + +You only need to make decisions based on a comparison with `pivot`: less, +equal, or greater. Since the relative order *within* the "less" group and +*within* the "greater" group must be preserved, you cannot sort the array — +sorting would destroy that original ordering. Instead, walk the array in its +original order and append each element to the correct group. + +### Hint 3 + +The "equal to pivot" elements are all identical, so you never need to store +them — you only need to **count** how many there are. So one pass can build a +"less than" list (in order) and a "greater than" list (in order) and a count of +pivots. The answer is simply: the less-than list, followed by `count` copies of +the pivot, followed by the greater-than list. You can even do this in place with +two pointers writing from the front for the "less" group and from the back for +the "greater" group. + +## Approach + +We need a stable three-way partition around `pivot`. Sorting is off the table +because it would reorder elements that compare equal in our three-way sense but +differ in value (e.g. `9` and `5` are both `< 10` and must keep their order). + +A clean linear approach uses **two pointers writing into the result**: + +1. Allocate a result slice of the same length `n`. +2. Keep a write index `left` starting at `0` (the next slot for a "less than" + element) and a write index `right` starting at `n-1` (the next slot for a + "greater than" element). +3. Scan `nums` left to right. For each value `< pivot`, place it at + `result[left]` and increment `left`. This preserves the relative order of the + smaller elements because we encounter and place them in their original order. +4. Scan `nums` right to left in a second loop. For each value `> pivot`, place it + at `result[right]` and decrement `right`. Scanning from the right and writing + from the right keeps the greater elements in their original relative order. +5. Every index strictly between the final `left` and `right` belongs to a pivot + value. Fill `result[left..=right]` with `pivot`. + +Why it works: after the first loop, slots `0..left-1` hold all smaller elements +in order. After the second loop, slots `right+1..n-1` hold all larger elements +in order. The remaining middle slots count exactly the number of elements equal +to the pivot, so we fill them with `pivot`. + +Walking through Example 1, `nums = [9,12,5,10,14,3,10]`, `pivot = 10`: + +- Less-than pass collects `9, 5, 3` into front slots → `[9,5,3,_,_,_,_]`. +- Greater-than pass (right to left) sees `10(skip),3(skip... no, <),14(>),...]` + collecting `14, 12` from the back, but written back-to-front so they land as + `... 12, 14` → `[9,5,3,_,_,12,14]`. +- The middle two slots get the pivot → `[9,5,3,10,10,12,14]`. ✓ + +An equivalent and perhaps more obviously-correct alternative is the +**three-bucket** method: build a `less` slice, count `equal`, build a `greater` +slice in one pass, then concatenate `less + equalCopies + greater`. Same time and +space complexity; pick whichever reads more clearly to you. The implementation +uses the two-pointer in-place-style write because it avoids extra slice +allocations beyond the single result. + +## Complexity Analysis + +Time Complexity: O(n) — a constant number of linear passes over `nums`. +Space Complexity: O(n) — for the returned result array. (This is unavoidable +since we must return a rearranged array; no extra space is used beyond the +output.) + +## Edge Cases + +- **All elements equal to the pivot**: e.g. `[5,5,5]`, `pivot = 5`. The + less-than and greater-than passes write nothing, and the entire array is filled + with the pivot. The two write pointers must correctly leave the whole range to + the middle. +- **No elements equal to the pivot beyond required**: the constraint guarantees + `pivot` appears at least once, so the middle region is never empty, but the + code should still behave if the less/greater groups are empty. +- **All elements less than the pivot** (or all greater): one group fills the + front (or back) and the rest is pivots. Verify pointers don't overlap + incorrectly. +- **Single element array**: `[x]` with `pivot = x`. Result is just `[x]`. +- **Negative numbers**: values can be negative (down to `-10^6`); comparisons + must use the raw integer values, not absolute values. +- **Large input (up to 10^5)**: the O(n) approach handles this comfortably; + anything involving sorting or nested scans risks being slower than necessary. diff --git a/problems/2161-partition-array-according-to-given-pivot/problem.md b/problems/2161-partition-array-according-to-given-pivot/problem.md new file mode 100644 index 0000000..a73ee8d --- /dev/null +++ b/problems/2161-partition-array-according-to-given-pivot/problem.md @@ -0,0 +1,62 @@ +--- +number: "2161" +frontend_id: "2161" +title: "Partition Array According to Given Pivot" +slug: "partition-array-according-to-given-pivot" +difficulty: "Medium" +topics: + - "Array" + - "Two Pointers" + - "Simulation" +acceptance_rate: 9013.1 +is_premium: false +created_at: "2026-06-08T05:10:54.037940+00:00" +fetched_at: "2026-06-08T05:10:54.037940+00:00" +link: "https://leetcode.com/problems/partition-array-according-to-given-pivot/" +date: "2026-06-08" +--- + +# 2161. Partition Array According to Given Pivot + +You are given a **0-indexed** integer array `nums` and an integer `pivot`. Rearrange `nums` such that the following conditions are satisfied: + + * Every element less than `pivot` appears **before** every element greater than `pivot`. + * Every element equal to `pivot` appears **in between** the elements less than and greater than `pivot`. + * The **relative order** of the elements less than `pivot` and the elements greater than `pivot` is maintained. + * More formally, consider every `pi`, `pj` where `pi` is the new position of the `ith` element and `pj` is the new position of the `jth` element. If `i < j` and **both** elements are smaller (_or larger_) than `pivot`, then `pi < pj`. + + + +Return `nums` _after the rearrangement._ + + + +**Example 1:** + + + **Input:** nums = [9,12,5,10,14,3,10], pivot = 10 + **Output:** [9,5,3,10,10,12,14] + **Explanation:** + The elements 9, 5, and 3 are less than the pivot so they are on the left side of the array. + The elements 12 and 14 are greater than the pivot so they are on the right side of the array. + The relative ordering of the elements less than and greater than pivot is also maintained. [9, 5, 3] and [12, 14] are the respective orderings. + + +**Example 2:** + + + **Input:** nums = [-3,4,3,2], pivot = 2 + **Output:** [-3,2,4,3] + **Explanation:** + The element -3 is less than the pivot so it is on the left side of the array. + The elements 4 and 3 are greater than the pivot so they are on the right side of the array. + The relative ordering of the elements less than and greater than pivot is also maintained. [-3] and [4, 3] are the respective orderings. + + + + +**Constraints:** + + * `1 <= nums.length <= 105` + * `-106 <= nums[i] <= 106` + * `pivot` equals to an element of `nums`. diff --git a/problems/2161-partition-array-according-to-given-pivot/solution_daily_20260608.go b/problems/2161-partition-array-according-to-given-pivot/solution_daily_20260608.go new file mode 100644 index 0000000..fc937c0 --- /dev/null +++ b/problems/2161-partition-array-according-to-given-pivot/solution_daily_20260608.go @@ -0,0 +1,37 @@ +package main + +// Problem 2161: Partition Array According to Given Pivot +// +// Approach: stable three-way partition around pivot using two write pointers. +// We scan nums left-to-right placing every value < pivot into the front of the +// result (preserving their original relative order), then scan right-to-left +// placing every value > pivot into the back of the result (also preserving +// order). The remaining middle slots are exactly the elements equal to pivot, +// so we fill them with pivot. Runs in O(n) time with a single result slice. +func pivotArray(nums []int, pivot int) []int { + n := len(nums) + result := make([]int, n) + + left := 0 + for _, v := range nums { + if v < pivot { + result[left] = v + left++ + } + } + + right := n - 1 + for i := n - 1; i >= 0; i-- { + if nums[i] > pivot { + result[right] = nums[i] + right-- + } + } + + // Every slot in [left, right] is an element equal to the pivot. + for i := left; i <= right; i++ { + result[i] = pivot + } + + return result +} diff --git a/problems/2161-partition-array-according-to-given-pivot/solution_daily_20260608_test.go b/problems/2161-partition-array-according-to-given-pivot/solution_daily_20260608_test.go new file mode 100644 index 0000000..ac1f6c9 --- /dev/null +++ b/problems/2161-partition-array-according-to-given-pivot/solution_daily_20260608_test.go @@ -0,0 +1,67 @@ +package main + +import ( + "reflect" + "testing" +) + +func TestPivotArray(t *testing.T) { + tests := []struct { + name string + nums []int + pivot int + expected []int + }{ + { + name: "example 1: mixed values with two pivots", + nums: []int{9, 12, 5, 10, 14, 3, 10}, + pivot: 10, + expected: []int{9, 5, 3, 10, 10, 12, 14}, + }, + { + name: "example 2: includes negatives", + nums: []int{-3, 4, 3, 2}, + pivot: 2, + expected: []int{-3, 2, 4, 3}, + }, + { + name: "edge case: single element equal to pivot", + nums: []int{5}, + pivot: 5, + expected: []int{5}, + }, + { + name: "edge case: all elements equal to pivot", + nums: []int{7, 7, 7, 7}, + pivot: 7, + expected: []int{7, 7, 7, 7}, + }, + { + name: "edge case: all less than pivot except one pivot", + nums: []int{4, 1, 3, 5}, + pivot: 5, + expected: []int{4, 1, 3, 5}, + }, + { + name: "edge case: all greater than pivot except one pivot", + nums: []int{5, 9, 6, 8}, + pivot: 5, + expected: []int{5, 9, 6, 8}, + }, + { + name: "edge case: negatives on both sides", + nums: []int{-5, 0, -2, 1, 0, -1}, + pivot: 0, + expected: []int{-5, -2, -1, 0, 0, 1}, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + result := pivotArray(tt.nums, tt.pivot) + if !reflect.DeepEqual(result, tt.expected) { + t.Errorf("pivotArray(%v, %d) = %v, want %v", tt.nums, tt.pivot, result, tt.expected) + } + }) + } +}