Skip to content
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

feat: add solutions to lc problem: No.3299 #3564

Merged
merged 1 commit into from
Sep 26, 2024
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
150 changes: 145 additions & 5 deletions solution/3200-3299/3299.Sum of Consecutive Subsequences/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,32 +70,172 @@ edit_url: https://github.com/doocs/leetcode/edit/main/solution/3200-3299/3299.Su

<!-- solution:start -->

### 方法一
### 方法一:枚举贡献

我们不妨统计每个元素 $\textit{nums}[i]$ 在多少个长度大于 $1$ 的连续子序列中出现,那么其个数乘以 $\textit{nums}[i]$ 就是 $\textit{nums}[i]$ 在所有长度大于 $1$ 的连续子序列中的贡献。我们将其累加,再加上所有元素的和,即为答案。

我们可以先统计连续递增子序列对答案的贡献,再统计连续递减子序列对答案的贡献,最后再加上所有元素的和即可。

在实现上,我们定义一个函数 $\textit{calc}(\textit{nums})$,其中 $\textit{nums}$ 是一个数组,返回 $\textit{nums}$ 所有长度大于 $1$ 的连续子序列的和。

在函数中,我们可以使用两个数组 $\textit{left}$ 和 $\textit{right}$ 分别记录每个元素 $\textit{nums}[i]$ 的左侧以 $\textit{nums}[i] - 1$ 结尾的连续递增子序列的个数,以及右侧以 $\textit{nums}[i] + 1$ 开头的连续递增子序列的个数。这样,我们就可以在 $O(n)$ 的时间复杂度内计算出 $\textit{nums}$ 在所有长度大于 $1$ 的连续子序列中的贡献。

在主函数中,我们首先调用 $\textit{calc}(\textit{nums})$ 计算出连续递增子序列对答案的贡献,然后将 $\textit{nums}$ 反转后再次调用 $\textit{calc}(\textit{nums})$ 计算出连续递减子序列对答案的贡献,最后再加上所有元素的和即为答案。

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

<!-- tabs:start -->

#### Python3

```python

class Solution:
def getSum(self, nums: List[int]) -> int:
def calc(nums: List[int]) -> int:
n = len(nums)
left = [0] * n
right = [0] * n
cnt = Counter()
for i in range(1, n):
cnt[nums[i - 1]] += 1 + cnt[nums[i - 1] - 1]
left[i] = cnt[nums[i] - 1]
cnt = Counter()
for i in range(n - 2, -1, -1):
cnt[nums[i + 1]] += 1 + cnt[nums[i + 1] + 1]
right[i] = cnt[nums[i] + 1]
return sum((l + r + l * r) * x for l, r, x in zip(left, right, nums)) % mod

mod = 10**9 + 7
x = calc(nums)
nums.reverse()
y = calc(nums)
return (x + y + sum(nums)) % mod
```

#### Java

```java

class Solution {
private final int mod = (int) 1e9 + 7;

public int getSum(int[] nums) {
long x = calc(nums);
for (int i = 0, j = nums.length - 1; i < j; ++i, --j) {
int t = nums[i];
nums[i] = nums[j];
nums[j] = t;
}
long y = calc(nums);
long s = Arrays.stream(nums).asLongStream().sum();
return (int) ((x + y + s) % mod);
}

private long calc(int[] nums) {
int n = nums.length;
long[] left = new long[n];
long[] right = new long[n];
Map<Integer, Long> cnt = new HashMap<>();
for (int i = 1; i < n; ++i) {
cnt.merge(nums[i - 1], 1 + cnt.getOrDefault(nums[i - 1] - 1, 0L), Long::sum);
left[i] = cnt.getOrDefault(nums[i] - 1, 0L);
}
cnt.clear();
for (int i = n - 2; i >= 0; --i) {
cnt.merge(nums[i + 1], 1 + cnt.getOrDefault(nums[i + 1] + 1, 0L), Long::sum);
right[i] = cnt.getOrDefault(nums[i] + 1, 0L);
}
long ans = 0;
for (int i = 0; i < n; ++i) {
ans = (ans + (left[i] + right[i] + left[i] * right[i] % mod) * nums[i] % mod) % mod;
}
return ans;
}
}
```

#### C++

```cpp

class Solution {
public:
int getSum(vector<int>& nums) {
using ll = long long;
const int mod = 1e9 + 7;
auto calc = [&](const vector<int>& nums) -> ll {
int n = nums.size();
vector<ll> left(n), right(n);
unordered_map<int, ll> cnt;

for (int i = 1; i < n; ++i) {
cnt[nums[i - 1]] += 1 + cnt[nums[i - 1] - 1];
left[i] = cnt[nums[i] - 1];
}

cnt.clear();

for (int i = n - 2; i >= 0; --i) {
cnt[nums[i + 1]] += 1 + cnt[nums[i + 1] + 1];
right[i] = cnt[nums[i] + 1];
}

ll ans = 0;
for (int i = 0; i < n; ++i) {
ans = (ans + (left[i] + right[i] + left[i] * right[i] % mod) * nums[i] % mod) % mod;
}
return ans;
};

ll x = calc(nums);
reverse(nums.begin(), nums.end());
ll y = calc(nums);
ll s = accumulate(nums.begin(), nums.end(), 0LL);
return static_cast<int>((x + y + s) % mod);
}
};
```

#### Go

```go

func getSum(nums []int) int {
const mod = 1e9 + 7

calc := func(nums []int) int64 {
n := len(nums)
left := make([]int64, n)
right := make([]int64, n)
cnt := make(map[int]int64)

for i := 1; i < n; i++ {
cnt[nums[i-1]] += 1 + cnt[nums[i-1]-1]
left[i] = cnt[nums[i]-1]
}

cnt = make(map[int]int64)

for i := n - 2; i >= 0; i-- {
cnt[nums[i+1]] += 1 + cnt[nums[i+1]+1]
right[i] = cnt[nums[i]+1]
}

var ans int64
for i, x := range nums {
ans = (ans + (left[i]+right[i]+(left[i]*right[i]%mod))*int64(x)%mod) % mod
}
return ans
}

x := calc(nums)
for i, j := 0, len(nums)-1; i < j; i, j = i+1, j-1 {
nums[i], nums[j] = nums[j], nums[i]
}
y := calc(nums)
s := int64(0)
for _, num := range nums {
s += int64(num)
}
return int((x + y + s) % mod)
}
```

<!-- tabs:end -->
Expand Down
150 changes: 145 additions & 5 deletions solution/3200-3299/3299.Sum of Consecutive Subsequences/README_EN.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,32 +70,172 @@ edit_url: https://github.com/doocs/leetcode/edit/main/solution/3200-3299/3299.Su

<!-- solution:start -->

### Solution 1
### Solution 1: Enumeration of Contributions

Let us count how many times each element $\textit{nums}[i]$ appears in a continuous subsequence of length greater than 1. Then, multiplying this count by $\textit{nums}[i]$ gives the contribution of $\textit{nums}[i]$ in all continuous subsequences of length greater than 1. We sum these contributions, and adding the sum of all elements, we get the answer.

We can first compute the contribution of strictly increasing subsequences, then the contribution of strictly decreasing subsequences, and finally add the sum of all elements.

To implement this, we define a function $\textit{calc}(\textit{nums})$, where $\textit{nums}$ is an array. This function returns the sum of all continuous subsequences of length greater than 1 in $\textit{nums}$.

In the function, we can use two arrays, $\textit{left}$ and $\textit{right}$, to record the number of strictly increasing subsequences ending with $\textit{nums}[i] - 1$ on the left of each element $\textit{nums}[i]$, and the number of strictly increasing subsequences starting with $\textit{nums}[i] + 1$ on the right of each element $\textit{nums}[i]$. In this way, we can calculate the contribution of $\textit{nums}$ in all continuous subsequences of length greater than 1 in $O(n)$ time complexity.

In the main function, we first call $\textit{calc}(\textit{nums})$ to compute the contribution of strictly increasing subsequences, then reverse $\textit{nums}$ and call $\textit{calc}(\textit{nums})$ again to compute the contribution of strictly decreasing subsequences. Finally, adding the sum of all elements gives the answer.

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

<!-- tabs:start -->

#### Python3

```python

class Solution:
def getSum(self, nums: List[int]) -> int:
def calc(nums: List[int]) -> int:
n = len(nums)
left = [0] * n
right = [0] * n
cnt = Counter()
for i in range(1, n):
cnt[nums[i - 1]] += 1 + cnt[nums[i - 1] - 1]
left[i] = cnt[nums[i] - 1]
cnt = Counter()
for i in range(n - 2, -1, -1):
cnt[nums[i + 1]] += 1 + cnt[nums[i + 1] + 1]
right[i] = cnt[nums[i] + 1]
return sum((l + r + l * r) * x for l, r, x in zip(left, right, nums)) % mod

mod = 10**9 + 7
x = calc(nums)
nums.reverse()
y = calc(nums)
return (x + y + sum(nums)) % mod
```

#### Java

```java

class Solution {
private final int mod = (int) 1e9 + 7;

public int getSum(int[] nums) {
long x = calc(nums);
for (int i = 0, j = nums.length - 1; i < j; ++i, --j) {
int t = nums[i];
nums[i] = nums[j];
nums[j] = t;
}
long y = calc(nums);
long s = Arrays.stream(nums).asLongStream().sum();
return (int) ((x + y + s) % mod);
}

private long calc(int[] nums) {
int n = nums.length;
long[] left = new long[n];
long[] right = new long[n];
Map<Integer, Long> cnt = new HashMap<>();
for (int i = 1; i < n; ++i) {
cnt.merge(nums[i - 1], 1 + cnt.getOrDefault(nums[i - 1] - 1, 0L), Long::sum);
left[i] = cnt.getOrDefault(nums[i] - 1, 0L);
}
cnt.clear();
for (int i = n - 2; i >= 0; --i) {
cnt.merge(nums[i + 1], 1 + cnt.getOrDefault(nums[i + 1] + 1, 0L), Long::sum);
right[i] = cnt.getOrDefault(nums[i] + 1, 0L);
}
long ans = 0;
for (int i = 0; i < n; ++i) {
ans = (ans + (left[i] + right[i] + left[i] * right[i] % mod) * nums[i] % mod) % mod;
}
return ans;
}
}
```

#### C++

```cpp

class Solution {
public:
int getSum(vector<int>& nums) {
using ll = long long;
const int mod = 1e9 + 7;
auto calc = [&](const vector<int>& nums) -> ll {
int n = nums.size();
vector<ll> left(n), right(n);
unordered_map<int, ll> cnt;

for (int i = 1; i < n; ++i) {
cnt[nums[i - 1]] += 1 + cnt[nums[i - 1] - 1];
left[i] = cnt[nums[i] - 1];
}

cnt.clear();

for (int i = n - 2; i >= 0; --i) {
cnt[nums[i + 1]] += 1 + cnt[nums[i + 1] + 1];
right[i] = cnt[nums[i] + 1];
}

ll ans = 0;
for (int i = 0; i < n; ++i) {
ans = (ans + (left[i] + right[i] + left[i] * right[i] % mod) * nums[i] % mod) % mod;
}
return ans;
};

ll x = calc(nums);
reverse(nums.begin(), nums.end());
ll y = calc(nums);
ll s = accumulate(nums.begin(), nums.end(), 0LL);
return static_cast<int>((x + y + s) % mod);
}
};
```

#### Go

```go

func getSum(nums []int) int {
const mod = 1e9 + 7

calc := func(nums []int) int64 {
n := len(nums)
left := make([]int64, n)
right := make([]int64, n)
cnt := make(map[int]int64)

for i := 1; i < n; i++ {
cnt[nums[i-1]] += 1 + cnt[nums[i-1]-1]
left[i] = cnt[nums[i]-1]
}

cnt = make(map[int]int64)

for i := n - 2; i >= 0; i-- {
cnt[nums[i+1]] += 1 + cnt[nums[i+1]+1]
right[i] = cnt[nums[i]+1]
}

var ans int64
for i, x := range nums {
ans = (ans + (left[i]+right[i]+(left[i]*right[i]%mod))*int64(x)%mod) % mod
}
return ans
}

x := calc(nums)
for i, j := 0, len(nums)-1; i < j; i, j = i+1, j-1 {
nums[i], nums[j] = nums[j], nums[i]
}
y := calc(nums)
s := int64(0)
for _, num := range nums {
s += int64(num)
}
return int((x + y + s) % mod)
}
```

<!-- tabs:end -->
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
class Solution {
public:
int getSum(vector<int>& nums) {
using ll = long long;
const int mod = 1e9 + 7;
auto calc = [&](const vector<int>& nums) -> ll {
int n = nums.size();
vector<ll> left(n), right(n);
unordered_map<int, ll> cnt;

for (int i = 1; i < n; ++i) {
cnt[nums[i - 1]] += 1 + cnt[nums[i - 1] - 1];
left[i] = cnt[nums[i] - 1];
}

cnt.clear();

for (int i = n - 2; i >= 0; --i) {
cnt[nums[i + 1]] += 1 + cnt[nums[i + 1] + 1];
right[i] = cnt[nums[i] + 1];
}

ll ans = 0;
for (int i = 0; i < n; ++i) {
ans = (ans + (left[i] + right[i] + left[i] * right[i] % mod) * nums[i] % mod) % mod;
}
return ans;
};

ll x = calc(nums);
reverse(nums.begin(), nums.end());
ll y = calc(nums);
ll s = accumulate(nums.begin(), nums.end(), 0LL);
return static_cast<int>((x + y + s) % mod);
}
};
Loading
Loading