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

feat: add solutions to lc problem: No.2926 #1942

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
Nov 8, 2023
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
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@
遍历字符串 $s$,对于当前字符 $c$:

- 如果当前字符为 `'0'`,我们判断此时 $one$ 是否大于 $0$,是则将 $zero$ 和 $one$ 重置为 $0$,接下来将 $zero$ 加 $1$。
- 如果当前字符为 `'1'`,则将 $one$ 加 $1$,并更新答案为 $ans = max(ans, 2 \times min(one, zero))$。
- 如果当前字符为 `'1'`,则将 $one$ 加 $1$,并更新答案为 $ans = \max(ans, 2 \times \min(one, zero))$。

遍历结束后,即可得到最长的平衡子串的长度。

Expand Down Expand Up @@ -326,7 +326,7 @@ impl Solution {
if s.as_bytes()[k] == b'1' {
cnt += 1;
} else if cnt > 0 {
return false
return false;
}
}

Expand Down Expand Up @@ -369,7 +369,7 @@ impl Solution {
zero += 1;
} else {
one += 1;
ans = std::cmp::max(ans, std::cmp::min(zero, one) * 2)
ans = std::cmp::max(ans, std::cmp::min(zero, one) * 2);
}
}

Expand Down
282 changes: 279 additions & 3 deletions solution/2900-2999/2926.Maximum Balanced Subsequence Sum/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,34 +67,310 @@ nums[3] - nums[0] >= 3 - 0 。

<!-- 这里可写通用的实现逻辑 -->

**方法一:动态规划 + 树状数组**

根据题目描述,我们可以将不等式 $nums[i] - nums[j] \ge i - j$ 转化为 $nums[i] - i \ge nums[j] - j$,因此,我们考虑定义一个新数组 $arr$,其中 $arr[i] = nums[i] - i$,那么平衡子序列满足对于任意 $j \lt i$,都有 $arr[j] \le arr[i]$。即题目转换为求在 $arr$ 中选出一个递增子序列,使得对应的 $nums$ 的和最大。

假设 $i$ 是子序列中最后一个元素的下标,那么我们考虑子序列倒数第二个元素的下标 $j$,如果 $arr[j] \le arr[i]$,我们可以考虑是否要将 $j$ 加入到子序列中。

因此,我们定义 $f[i]$ 表示子序列最后一个元素的下标为 $i$ 时,对应的 $nums$ 的最大和,那么答案为 $\max_{i=0}^{n-1} f[i]$。

状态转移方程为:

$$
f[i] = \max(\max_{j=0}^{i-1} f[j], 0) + nums[i]
$$

其中 $j$ 满足 $arr[j] \le arr[i]$。

我们可以使用树状数组来维护前缀的最大值,即对于每个 $arr[i]$,我们维护前缀 $arr[0..i]$ 中 $f[i]$ 的最大值。

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

<!-- tabs:start -->

### **Python3**

<!-- 这里可写当前语言的特殊实现逻辑 -->

```python

class BinaryIndexedTree:
def __init__(self, n: int):
self.n = n
self.c = [-inf] * (n + 1)

def update(self, x: int, v: int):
while x <= self.n:
self.c[x] = max(self.c[x], v)
x += x & -x

def query(self, x: int) -> int:
mx = -inf
while x:
mx = max(mx, self.c[x])
x -= x & -x
return mx


class Solution:
def maxBalancedSubsequenceSum(self, nums: List[int]) -> int:
arr = [x - i for i, x in enumerate(nums)]
s = sorted(set(arr))
tree = BinaryIndexedTree(len(s))
for i, x in enumerate(nums):
j = bisect_left(s, x - i) + 1
v = max(tree.query(j), 0) + x
tree.update(j, v)
return tree.query(len(s))
```

### **Java**

<!-- 这里可写当前语言的特殊实现逻辑 -->

```java

class BinaryIndexedTree {
private int n;
private long[] c;
private final long inf = 1L << 60;

public BinaryIndexedTree(int n) {
this.n = n;
c = new long[n + 1];
Arrays.fill(c, -inf);
}

public void update(int x, long v) {
while (x <= n) {
c[x] = Math.max(c[x], v);
x += x & -x;
}
}

public long query(int x) {
long mx = -inf;
while (x > 0) {
mx = Math.max(mx, c[x]);
x -= x & -x;
}
return mx;
}
}

class Solution {
public long maxBalancedSubsequenceSum(int[] nums) {
int n = nums.length;
int[] arr = new int[n];
for (int i = 0; i < n; ++i) {
arr[i] = nums[i] - i;
}
Arrays.sort(arr);
int m = 0;
for (int i = 0; i < n; ++i) {
if (i == 0 || arr[i] != arr[i - 1]) {
arr[m++] = arr[i];
}
}
BinaryIndexedTree tree = new BinaryIndexedTree(m);
for (int i = 0; i < n; ++i) {
int j = search(arr, nums[i] - i, m) + 1;
long v = Math.max(tree.query(j), 0) + nums[i];
tree.update(j, v);
}
return tree.query(m);
}

private int search(int[] nums, int x, int r) {
int l = 0;
while (l < r) {
int mid = (l + r) >> 1;
if (nums[mid] >= x) {
r = mid;
} else {
l = mid + 1;
}
}
return l;
}
}
```

### **C++**

```cpp

class BinaryIndexedTree {
private:
int n;
vector<long long> c;
const long long inf = 1e18;

public:
BinaryIndexedTree(int n) {
this->n = n;
c.resize(n + 1, -inf);
}

void update(int x, long long v) {
while (x <= n) {
c[x] = max(c[x], v);
x += x & -x;
}
}

long long query(int x) {
long long mx = -inf;
while (x > 0) {
mx = max(mx, c[x]);
x -= x & -x;
}
return mx;
}
};

class Solution {
public:
long long maxBalancedSubsequenceSum(vector<int>& nums) {
int n = nums.size();
vector<int> arr(n);
for (int i = 0; i < n; ++i) {
arr[i] = nums[i] - i;
}
sort(arr.begin(), arr.end());
arr.erase(unique(arr.begin(), arr.end()), arr.end());
int m = arr.size();
BinaryIndexedTree tree(m);
for (int i = 0; i < n; ++i) {
int j = lower_bound(arr.begin(), arr.end(), nums[i] - i) - arr.begin() + 1;
long long v = max(tree.query(j), 0LL) + nums[i];
tree.update(j, v);
}
return tree.query(m);
}
};
```

### **Go**

```go
const inf int = 1e18

type BinaryIndexedTree struct {
n int
c []int
}

func NewBinaryIndexedTree(n int) BinaryIndexedTree {
c := make([]int, n+1)
for i := range c {
c[i] = -inf
}
return BinaryIndexedTree{n: n, c: c}
}

func (bit *BinaryIndexedTree) update(x, v int) {
for x <= bit.n {
bit.c[x] = max(bit.c[x], v)
x += x & -x
}
}

func (bit *BinaryIndexedTree) query(x int) int {
mx := -inf
for x > 0 {
mx = max(mx, bit.c[x])
x -= x & -x
}
return mx
}

func maxBalancedSubsequenceSum(nums []int) int64 {
n := len(nums)
arr := make([]int, n)
for i, x := range nums {
arr[i] = x - i
}
sort.Ints(arr)
m := 0
for i, x := range arr {
if i == 0 || x != arr[i-1] {
arr[m] = x
m++
}
}
arr = arr[:m]
tree := NewBinaryIndexedTree(m)
for i, x := range nums {
j := sort.SearchInts(arr, x-i) + 1
v := max(tree.query(j), 0) + x
tree.update(j, v)
}
return int64(tree.query(m))
}
```

### **TypeScript**

```ts
class BinaryIndexedTree {
private n: number;
private c: number[];

constructor(n: number) {
this.n = n;
this.c = Array(n + 1).fill(-Infinity);
}

update(x: number, v: number): void {
while (x <= this.n) {
this.c[x] = Math.max(this.c[x], v);
x += x & -x;
}
}

query(x: number): number {
let mx = -Infinity;
while (x > 0) {
mx = Math.max(mx, this.c[x]);
x -= x & -x;
}
return mx;
}
}

function maxBalancedSubsequenceSum(nums: number[]): number {
const n = nums.length;
const arr = Array(n).fill(0);
for (let i = 0; i < n; ++i) {
arr[i] = nums[i] - i;
}
arr.sort((a, b) => a - b);
let m = 0;
for (let i = 0; i < n; ++i) {
if (i === 0 || arr[i] !== arr[i - 1]) {
arr[m++] = arr[i];
}
}
arr.length = m;
const tree = new BinaryIndexedTree(m);
const search = (nums: number[], x: number): number => {
let [l, r] = [0, nums.length];
while (l < r) {
const mid = (l + r) >> 1;
if (nums[mid] >= x) {
r = mid;
} else {
l = mid + 1;
}
}
return l;
};
for (let i = 0; i < n; ++i) {
const j = search(arr, nums[i] - i) + 1;
const v = Math.max(tree.query(j), 0) + nums[i];
tree.update(j, v);
}
return tree.query(m);
}
```

### **...**
Expand Down
Loading