Skip to content

Commit 91e20e2

Browse files
authored
Merge pull request #2032 from shreyash3087/add/leetcode-915
Docs: Added Solutions to Leetcode 915
2 parents 2e50637 + 968722f commit 91e20e2

File tree

2 files changed

+287
-1
lines changed

2 files changed

+287
-1
lines changed

dsa-problems/leetcode-problems/0900-0999.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ export const problems = [
105105
problemName: "915. Partition Array into Disjoint Intervals",
106106
difficulty: "Medium",
107107
leetCodeLink: "https://leetcode.com/problems/partition-array-into-disjoint-intervals",
108-
solutionLink: "#"
108+
solutionLink: "/dsa-solutions/lc-solutions/0900-0999/partition-array-into-disjoint-intervals"
109109
},
110110
{
111111
problemName: "916. Word Subsets",
Lines changed: 286 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,286 @@
1+
---
2+
id: partition-array-into-disjoint-intervals
3+
title: Partition Array into Disjoint Intervals
4+
sidebar_label: 915 - Partition Array into Disjoint Intervals
5+
tags:
6+
- Suffix Array
7+
- Two Pointers
8+
- Prefix Sum
9+
description: "This is a solution to the Partition Array into Disjoint Intervals problem on LeetCode."
10+
---
11+
12+
## Problem Description
13+
14+
Given an integer array `nums`, partition it into two (contiguous) subarrays `left` and `right` so that:
15+
16+
- Every element in `left` is less than or equal to every element in `right`.
17+
- `left` and `right` are non-empty.
18+
- `left` has the smallest possible size.
19+
20+
Return the length of `left` after such a partitioning.
21+
22+
Test cases are generated such that partitioning exists.
23+
24+
### Examples
25+
26+
**Example 1:**
27+
28+
```
29+
Input: nums = [5,0,3,8,6]
30+
Output: 3
31+
Explanation: left = [5,0,3], right = [8,6]
32+
```
33+
**Example 2:**
34+
35+
```
36+
Input: nums = [1,1,1,0,6,12]
37+
Output: 4
38+
Explanation: left = [1,1,1,0], right = [6,12]
39+
```
40+
41+
### Constraints
42+
43+
- $2 \leq nums.length \leq 10^5$
44+
- $0 \leq nums[i] \leq 10^6$
45+
- There is at least one valid answer for the given input.
46+
47+
## Solution for Partition Array into Disjoint Intervals
48+
49+
## Approach 1: Two Arrays
50+
### Intuition
51+
52+
Instead of checking whether `all(L <= R for L in left for R in right)` , for each index let's only check whether the **largest element to the left** of the current index (inclusive) is less than or equal to the **smallest element to the right** of the current index (`max(left) <= min(right)`).
53+
54+
### Algorithm
55+
56+
Let's try to find `max(left)` for subarrays `left = nums[:1], left = nums[:2], left = nums[:3], ...` etc. Specifically, `max_left[i]` will be the maximum of subarray `nums[:i+1]`. They are related to each other: `max(nums[:4]) = max(max(nums[:3]), nums[3])`, so `max_left[4] = max(max_left[3], nums[4])`.
57+
58+
Similarly, `min(right)` for every possible right can be found in linear time.
59+
60+
Now that we can query `max(left)` and `min(right)` in constant time by checking `max_left[i]` and `min_right[i]`, we just need to iterate over `max_left` and `min_right` to find the first index where `max_left[i-1]` is less than or equal to `min_right[i]`.
61+
62+
### Code in Different Languages
63+
64+
<Tabs>
65+
<TabItem value="cpp" label="C++">
66+
<SolutionAuthor name="@Shreyash3087"/>
67+
68+
```cpp
69+
class Solution {
70+
public:
71+
int partitionDisjoint(vector<int>& nums) {
72+
int N = nums.size();
73+
int maxLeft[N];
74+
int minRight[N];
75+
76+
maxLeft[0] = nums[0];
77+
minRight[N - 1] = nums[N - 1];
78+
79+
for (int i = 1; i < N; ++i) {
80+
maxLeft[i] = max(maxLeft[i - 1], nums[i]);
81+
}
82+
83+
for (int i = N - 2; i >= 0; --i) {
84+
minRight[i] = min(minRight[i + 1], nums[i]);
85+
}
86+
87+
for (int i = 1; i < N; ++i) {
88+
if (maxLeft[i - 1] <= minRight[i]) {
89+
return i;
90+
}
91+
}
92+
// In case there is no solution, we'll return -1
93+
return -1;
94+
}
95+
};
96+
```
97+
</TabItem>
98+
<TabItem value="java" label="Java">
99+
<SolutionAuthor name="@Shreyash3087"/>
100+
101+
```java
102+
class Solution {
103+
public int partitionDisjoint(int[] nums) {
104+
int N = nums.length;
105+
int[] maxLeft = new int[N];
106+
int[] minRight = new int[N];
107+
108+
maxLeft[0] = nums[0];
109+
minRight[N - 1] = nums[N - 1];
110+
111+
for (int i = 1; i < N; ++i) {
112+
maxLeft[i] = Math.max(maxLeft[i - 1], nums[i]);
113+
}
114+
115+
for (int i = N - 2; i >= 0; --i) {
116+
minRight[i] = Math.min(minRight[i + 1], nums[i]);
117+
}
118+
119+
for (int i = 1; i < N; ++i) {
120+
if (maxLeft[i - 1] <= minRight[i]) {
121+
return i;
122+
}
123+
}
124+
// In case there is no solution, we'll return -1
125+
return -1;
126+
}
127+
}
128+
```
129+
130+
</TabItem>
131+
<TabItem value="python" label="Python">
132+
<SolutionAuthor name="@Shreyash3087"/>
133+
134+
```python
135+
class Solution:
136+
def partitionDisjoint(self, nums: List[int]) -> int:
137+
N = len(nums)
138+
max_left = [None] * N
139+
min_right = [None] * N
140+
141+
max_left[0] = nums[0]
142+
min_right[-1] = nums[-1]
143+
144+
for i in range(1, N):
145+
max_left[i] = max(max_left[i - 1], nums[i])
146+
147+
for i in range(N - 2, -1, -1):
148+
min_right[i] = min(min_right[i + 1], nums[i])
149+
150+
for i in range(1, N):
151+
if max_left[i - 1] <= min_right[i]:
152+
return i
153+
```
154+
</TabItem>
155+
</Tabs>
156+
157+
### Complexity Analysis
158+
159+
#### Time Complexity: $O(N)$
160+
161+
> **Reason**: where N is the length of `nums`. We iterate over the input array three times and create two arrays with size N each.
162+
163+
#### Space Complexity: $O(N)$
164+
165+
> **Reason**: We use two additional arrays of size N each.
166+
167+
## Approach 2: One Array
168+
### Intuition
169+
170+
Notice, in the first approach, we iterated from `1` to `N` twice. Once to create `max_left` and once to find which index to split the array at. We can slightly optimize our approach by performing both of these steps in the same for loop. Doing so will allow us to replace the `max_left` array with a single variable that tracks the maximum value seen so far (`curr_max`).
171+
172+
> How can we do this? Try to code it up yourself before looking at the solution below.
173+
174+
### Algorithm
175+
176+
1. Initialize a `min_right` array with the rightmost value equal to the rightmost value in nums.
177+
2. Iterate over nums in reverse order and at each iteration update the current index of `min_right` with the minimum value seen so far.
178+
3. Initialize `curr_max` as the leftmost value in nums.
179+
4. Iterate over nums from left to right and at each iteration, update `curr_max` as the maximum value seen so far. When `curr_max` is less than or equal to the minimum value to the right, then the current index is where nums should be split.
180+
181+
### Code in Different Languages
182+
183+
<Tabs>
184+
<TabItem value="cpp" label="C++">
185+
<SolutionAuthor name="@Shreyash3087"/>
186+
187+
```cpp
188+
class Solution {
189+
public:
190+
int partitionDisjoint(vector<int>& nums) {
191+
int N = nums.size();
192+
int minRight[N];
193+
minRight[N - 1] = nums[N - 1];
194+
195+
for (int i = N - 2; i >= 0; --i) {
196+
minRight[i] = min(minRight[i + 1], nums[i]);
197+
}
198+
199+
int currMax = nums[0];
200+
for (int i = 1; i < N; ++i) {
201+
currMax = max(currMax, nums[i - 1]);
202+
if (currMax <= minRight[i]) {
203+
return i;
204+
}
205+
}
206+
// In case there is no solution, we'll return -1
207+
return -1;
208+
}
209+
};
210+
```
211+
</TabItem>
212+
<TabItem value="java" label="Java">
213+
<SolutionAuthor name="@Shreyash3087"/>
214+
215+
```java
216+
class Solution {
217+
public int partitionDisjoint(int[] nums) {
218+
int N = nums.length;
219+
int[] minRight = new int[N];
220+
minRight[N - 1] = nums[N - 1];
221+
222+
for (int i = N - 2; i >= 0; --i) {
223+
minRight[i] = Math.min(minRight[i + 1], nums[i]);
224+
}
225+
226+
int currMax = nums[0];
227+
for (int i = 1; i < N; ++i) {
228+
currMax = Math.max(currMax, nums[i - 1]);
229+
if (currMax <= minRight[i]) {
230+
return i;
231+
}
232+
}
233+
// In case there is no solution, we'll return -1
234+
return -1;
235+
}
236+
}
237+
```
238+
239+
</TabItem>
240+
<TabItem value="python" label="Python">
241+
<SolutionAuthor name="@Shreyash3087"/>
242+
243+
```python
244+
class Solution:
245+
def partitionDisjoint(self, nums: List[int]) -> int:
246+
N = len(nums)
247+
min_right = [None] * N
248+
min_right[-1] = nums[-1]
249+
250+
for i in range(N - 2, -1, -1):
251+
min_right[i] = min(min_right[i + 1], nums[i])
252+
253+
curr_max = nums[0]
254+
for i in range(1, N):
255+
curr_max = max(curr_max, nums[i - 1])
256+
if curr_max <= min_right[i]:
257+
return i
258+
```
259+
</TabItem>
260+
</Tabs>
261+
262+
### Complexity Analysis
263+
264+
#### Time Complexity: $O(N)$
265+
266+
> **Reason**: where N is the length of nums. We iterate over the input array two times (instead of three times as in the previous approach) and create only one array with size N (as opposed to two as before).
267+
268+
#### Space Complexity: $O(N)$
269+
270+
> **Reason**: We use one additional array of size N.
271+
272+
273+
## Video Solution
274+
275+
<LiteYouTubeEmbed
276+
id="LvS4FcrGnD8"
277+
params="autoplay=1&autohide=1&showinfo=0&rel=0"
278+
title="Partition Array into Disjoint Intervals | LeetCode 915 | C++, Java, Python"
279+
poster="hqdefault"
280+
webp />
281+
282+
## References
283+
284+
- **LeetCode Problem**: [Partition Array into Disjoint Intervals](https://leetcode.com/problems/partition-array-into-disjoint-intervals/)
285+
286+
- **Solution Link**: [Partition Array into Disjoint Intervals](https://leetcode.com/problems/partition-array-into-disjoint-intervals/solutions/)

0 commit comments

Comments
 (0)