Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

feat: add solutions to lc problem: No.1590 #3996

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jan 26, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
83 changes: 78 additions & 5 deletions solution/1500-1599/1590.Make Sum Divisible by P/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,17 +80,17 @@ tags:

### 方法一:前缀和 + 哈希表

我们可以先求出数组 $nums$ 所有元素之和模 $p$ 的值,记为 $k$。如果 $k$ 为 $0$,说明数组 $nums$ 所有元素之和就是 $p$ 的倍数,直接返回 $0$ 即可。
我们可以先求出数组 $\textit{nums}$ 所有元素之和模 $p$ 的值,记为 $k$。如果 $k$ 为 $0$,说明数组 $\textit{nums}$ 所有元素之和就是 $p$ 的倍数,直接返回 $0$ 即可。

如果 $k$ 不为 $0$,我们需要找到一个最短的子数组,使得删除该子数组后,剩余元素之和模 $p$ 的值为 $0$。

我们可以遍历数组 $nums$,维护当前的前缀和模 $p$ 的值,记为 $cur$。用哈希表 $last$ 记录每个前缀和模 $p$ 的值最后一次出现的位置。
我们可以遍历数组 $\textit{nums}$,维护当前的前缀和模 $p$ 的值,记为 $cur$。用哈希表 $last$ 记录每个前缀和模 $p$ 的值最后一次出现的位置。

如果当前存在一个以 $nums[i]$ 结尾的子数组,使得删除该子数组后,剩余元素之和模 $p$ 的值为 $0$。也就是说,我们需要找到此前的一个前缀和模 $p$ 的值为 $target$ 的位置 $j$,使得 $(target + k - cur) \bmod p = 0$。如果找到,我们就可以将 $j + 1$ 到 $i$ 这一段闭区间子数组 $nums[j+1,..i]$ 删除,使得剩余元素之和模 $p$ 的值为 $0$。
如果当前存在一个以 $\textit{nums}[i]$ 结尾的子数组,使得删除该子数组后,剩余元素之和模 $p$ 的值为 $0$。也就是说,我们需要找到此前的一个前缀和模 $p$ 的值为 $target$ 的位置 $j$,使得 $(target + k - cur) \bmod p = 0$。如果找到,我们就可以将 $j + 1$ 到 $i$ 这一段闭区间子数组 $\textit{nums}[j+1,..i]$ 删除,使得剩余元素之和模 $p$ 的值为 $0$。

因此,如果存在一个 $target = (cur - k + p) \bmod p$,那么我们可以更新答案为 $\min(ans, i - j)$。接下来,我们更新 $last[cur]$ 的值为 $i$。继续遍历数组 $nums$,直到遍历结束,即可得到答案。
因此,如果存在一个 $target = (cur - k + p) \bmod p$,那么我们可以更新答案为 $\min(ans, i - j)$。接下来,我们更新 $last[cur]$ 的值为 $i$。继续遍历数组 $\textit{nums}$,直到遍历结束,即可得到答案。

时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 为数组 $nums$ 的长度。
时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 为数组 $\textit{nums}$ 的长度。

<!-- tabs:start -->

Expand Down Expand Up @@ -234,6 +234,79 @@ function minSubarray(nums: number[], p: number): number {
}
```

#### Rust

```rust
use std::collections::HashMap;

impl Solution {
pub fn min_subarray(nums: Vec<i32>, p: i32) -> i32 {
let mut k = 0;
for &x in &nums {
k = (k + x) % p;
}
if k == 0 {
return 0;
}

let mut last = HashMap::new();
last.insert(0, -1);
let n = nums.len();
let mut ans = n as i32;
let mut cur = 0;

for i in 0..n {
cur = (cur + nums[i]) % p;
let target = (cur - k + p) % p;
if let Some(&prev_idx) = last.get(&target) {
ans = ans.min(i as i32 - prev_idx);
}
last.insert(cur, i as i32);
}

if ans == n as i32 {
-1
} else {
ans
}
}
}
```

#### JavaScript

```js
/**
* @param {number[]} nums
* @param {number} p
* @return {number}
*/
var minSubarray = function (nums, p) {
let k = 0;
for (const x of nums) {
k = (k + x) % p;
}
if (k === 0) {
return 0;
}
const last = new Map();
last.set(0, -1);
const n = nums.length;
let ans = n;
let cur = 0;
for (let i = 0; i < n; ++i) {
cur = (cur + nums[i]) % p;
const target = (cur - k + p) % p;
if (last.has(target)) {
const j = last.get(target);
ans = Math.min(ans, i - j);
}
last.set(cur, i);
}
return ans === n ? -1 : ans;
};
```

<!-- tabs:end -->

<!-- solution:end -->
Expand Down
87 changes: 86 additions & 1 deletion solution/1500-1599/1590.Make Sum Divisible by P/README_EN.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,19 @@ tags:

<!-- solution:start -->

### Solution 1
### Solution 1: Prefix Sum + Hash Table

First, we calculate the sum of all elements in the array $\textit{nums}$ modulo $p$, denoted as $k$. If $k$ is $0$, it means the sum of all elements in the array $\textit{nums}$ is a multiple of $p$, so we directly return $0$.

If $k$ is not $0$, we need to find the shortest subarray such that removing this subarray makes the sum of the remaining elements modulo $p$ equal to $0$.

We can traverse the array $\textit{nums}$, maintaining the current prefix sum modulo $p$, denoted as $cur$. We use a hash table $last$ to record the last occurrence of each prefix sum modulo $p$.

If there exists a subarray ending at $\textit{nums}[i]$ such that removing this subarray makes the sum of the remaining elements modulo $p$ equal to $0$, we need to find a previous prefix sum modulo $p$ equal to $target$ at position $j$ such that $(target + k - cur) \bmod p = 0$. If found, we can remove the subarray $\textit{nums}[j+1,..i]$ to make the sum of the remaining elements modulo $p$ equal to $0$.

Therefore, if there exists a $target = (cur - k + p) \bmod p$, we can update the answer to $\min(ans, i - j)$. Then, we update $last[cur]$ to $i$. We continue traversing the array $\textit{nums}$ until the end to get the answer.

The time complexity is $O(n)$, and the space complexity is $O(n)$. Here, $n$ is the length of the array $\textit{nums}$.

<!-- tabs:start -->

Expand Down Expand Up @@ -210,6 +222,79 @@ function minSubarray(nums: number[], p: number): number {
}
```

#### Rust

```rust
use std::collections::HashMap;

impl Solution {
pub fn min_subarray(nums: Vec<i32>, p: i32) -> i32 {
let mut k = 0;
for &x in &nums {
k = (k + x) % p;
}
if k == 0 {
return 0;
}

let mut last = HashMap::new();
last.insert(0, -1);
let n = nums.len();
let mut ans = n as i32;
let mut cur = 0;

for i in 0..n {
cur = (cur + nums[i]) % p;
let target = (cur - k + p) % p;
if let Some(&prev_idx) = last.get(&target) {
ans = ans.min(i as i32 - prev_idx);
}
last.insert(cur, i as i32);
}

if ans == n as i32 {
-1
} else {
ans
}
}
}
```

#### JavaScript

```js
/**
* @param {number[]} nums
* @param {number} p
* @return {number}
*/
var minSubarray = function (nums, p) {
let k = 0;
for (const x of nums) {
k = (k + x) % p;
}
if (k === 0) {
return 0;
}
const last = new Map();
last.set(0, -1);
const n = nums.length;
let ans = n;
let cur = 0;
for (let i = 0; i < n; ++i) {
cur = (cur + nums[i]) % p;
const target = (cur - k + p) % p;
if (last.has(target)) {
const j = last.get(target);
ans = Math.min(ans, i - j);
}
last.set(cur, i);
}
return ans === n ? -1 : ans;
};
```

<!-- tabs:end -->

<!-- solution:end -->
Expand Down
29 changes: 29 additions & 0 deletions solution/1500-1599/1590.Make Sum Divisible by P/Solution.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/**
* @param {number[]} nums
* @param {number} p
* @return {number}
*/
var minSubarray = function (nums, p) {
let k = 0;
for (const x of nums) {
k = (k + x) % p;
}
if (k === 0) {
return 0;
}
const last = new Map();
last.set(0, -1);
const n = nums.length;
let ans = n;
let cur = 0;
for (let i = 0; i < n; ++i) {
cur = (cur + nums[i]) % p;
const target = (cur - k + p) % p;
if (last.has(target)) {
const j = last.get(target);
ans = Math.min(ans, i - j);
}
last.set(cur, i);
}
return ans === n ? -1 : ans;
};
34 changes: 34 additions & 0 deletions solution/1500-1599/1590.Make Sum Divisible by P/Solution.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
use std::collections::HashMap;

impl Solution {
pub fn min_subarray(nums: Vec<i32>, p: i32) -> i32 {
let mut k = 0;
for &x in &nums {
k = (k + x) % p;
}
if k == 0 {
return 0;
}

let mut last = HashMap::new();
last.insert(0, -1);
let n = nums.len();
let mut ans = n as i32;
let mut cur = 0;

for i in 0..n {
cur = (cur + nums[i]) % p;
let target = (cur - k + p) % p;
if let Some(&prev_idx) = last.get(&target) {
ans = ans.min(i as i32 - prev_idx);
}
last.insert(cur, i as i32);
}

if ans == n as i32 {
-1
} else {
ans
}
}
}
Loading