From ac93bdf781a9ec955f52bdb1e313f0fed6b398b7 Mon Sep 17 00:00:00 2001 From: yanglbme Date: Sat, 17 Aug 2024 14:14:55 +0800 Subject: [PATCH 1/2] feat: add solutions to lc problems: No.1424,1425 * No.1424.Diagonal Traverse II * No.1425.Constrained Subsequence Sum --- .../1424.Diagonal Traverse II/README.md | 19 +- .../1424.Diagonal Traverse II/README_EN.md | 27 +- .../1424.Diagonal Traverse II/Solution.ts | 10 + .../README.md | 271 ++++++++++++++--- .../README_EN.md | 273 +++++++++++++++--- .../Solution.cpp | 19 +- .../Solution.go | 86 +++++- .../Solution.java | 21 +- .../Solution.py | 14 +- .../Solution.ts | 115 ++++++++ 10 files changed, 740 insertions(+), 115 deletions(-) create mode 100644 solution/1400-1499/1424.Diagonal Traverse II/Solution.ts create mode 100644 solution/1400-1499/1425.Constrained Subsequence Sum/Solution.ts diff --git a/solution/1400-1499/1424.Diagonal Traverse II/README.md b/solution/1400-1499/1424.Diagonal Traverse II/README.md index 48385ce570025..f515c12354555 100644 --- a/solution/1400-1499/1424.Diagonal Traverse II/README.md +++ b/solution/1400-1499/1424.Diagonal Traverse II/README.md @@ -77,9 +77,9 @@ tags: - 下一条对角线的 $i + j$ 的值比前一条对角线的大; - 在同一条对角线中的 $i + j$ 是相同的,而 $j$ 值是从小到大递增。 -因此,我们将所有数字以 `(i + j, j, nums[i][j])` 的形式存进 `arr`,然后按照前两项排序。最后返回 `arr` 所有元素第二项组成的数组即可。 +因此,我们将所有数字以 $(i, j, \textit{nums}[i][j])$ 的形式存进 $\textit{arr}$,然后按照前两项排序。最后返回 $\textit{arr}$ 所有元素下标为 $2$ 的值组成的数组即可。 -时间复杂度 $O(n\log n)$,其中 $n$ 是 `nums` 数组元素的个数。 +时间复杂度 $O(n \times \log n)$,其中 $n$ 是数组 $\textit{nums}$ 中元素的个数。空间复杂度 $O(n)$。 @@ -163,6 +163,21 @@ func findDiagonalOrder(nums [][]int) []int { } ``` +#### TypeScript + +```ts +function findDiagonalOrder(nums: number[][]): number[] { + const arr: number[][] = []; + for (let i = 0; i < nums.length; ++i) { + for (let j = 0; j < nums[i].length; ++j) { + arr.push([i + j, j, nums[i][j]]); + } + } + arr.sort((a, b) => (a[0] === b[0] ? a[1] - b[1] : a[0] - b[0])); + return arr.map(x => x[2]); +} +``` + #### C# ```cs diff --git a/solution/1400-1499/1424.Diagonal Traverse II/README_EN.md b/solution/1400-1499/1424.Diagonal Traverse II/README_EN.md index d3001f93376b6..0e428edd54e24 100644 --- a/solution/1400-1499/1424.Diagonal Traverse II/README_EN.md +++ b/solution/1400-1499/1424.Diagonal Traverse II/README_EN.md @@ -53,7 +53,17 @@ tags: -### Solution 1 +### Solution 1: Sorting + +We observe that: + +- The value of $i + j$ is the same for each diagonal; +- The value of $i + j$ for the next diagonal is greater than that of the previous diagonal; +- Within the same diagonal, the value of $i + j$ is the same, and the value of $j$ increases from small to large. + +Therefore, we store all numbers in the form of $(i, j, \textit{nums}[i][j])$ into $\textit{arr}$, and then sort according to the first two items. Finally, return the array composed of the values at index 2 of all elements in $\textit{arr}$. + +The time complexity is $O(n \times \log n)$, where $n$ is the number of elements in the array $\textit{nums}$. The space complexity is $O(n)$. @@ -137,6 +147,21 @@ func findDiagonalOrder(nums [][]int) []int { } ``` +#### TypeScript + +```ts +function findDiagonalOrder(nums: number[][]): number[] { + const arr: number[][] = []; + for (let i = 0; i < nums.length; ++i) { + for (let j = 0; j < nums[i].length; ++j) { + arr.push([i + j, j, nums[i][j]]); + } + } + arr.sort((a, b) => (a[0] === b[0] ? a[1] - b[1] : a[0] - b[0])); + return arr.map(x => x[2]); +} +``` + #### C# ```cs diff --git a/solution/1400-1499/1424.Diagonal Traverse II/Solution.ts b/solution/1400-1499/1424.Diagonal Traverse II/Solution.ts new file mode 100644 index 0000000000000..bd3c93ca6fd96 --- /dev/null +++ b/solution/1400-1499/1424.Diagonal Traverse II/Solution.ts @@ -0,0 +1,10 @@ +function findDiagonalOrder(nums: number[][]): number[] { + const arr: number[][] = []; + for (let i = 0; i < nums.length; ++i) { + for (let j = 0; j < nums[i].length; ++j) { + arr.push([i + j, j, nums[i][j]]); + } + } + arr.sort((a, b) => (a[0] === b[0] ? a[1] - b[1] : a[0] - b[0])); + return arr.map(x => x[2]); +} diff --git a/solution/1400-1499/1425.Constrained Subsequence Sum/README.md b/solution/1400-1499/1425.Constrained Subsequence Sum/README.md index f96e8760a7d7c..3fd8621508fc5 100644 --- a/solution/1400-1499/1425.Constrained Subsequence Sum/README.md +++ b/solution/1400-1499/1425.Constrained Subsequence Sum/README.md @@ -67,6 +67,23 @@ tags: ### 方法一:动态规划 + 单调队列 +我们定义 $f[i]$ 表示以 $\textit{nums}[i]$ 结尾的满足条件的子序列的最大和。初始时 $f[i] = 0$,答案为 $\max_{0 \leq i \lt n} f(i)$。 + +我们注意到题目需要我们维护滑动窗口的最大值,这就是一个典型的单调队列应用场景。我们可以使用单调队列来优化动态规划的转移。 + +我们维护一个从队首到队尾单调递减的单调队列 $q$,队列中存储的是下标 $i$,初始时,我们将一个哨兵 $0$ 加入队列中。 + +我们遍历 $i$ 从 $0$ 到 $n - 1$,对于每个 $i$,我们执行以下操作: + +- 如果队首元素 $q[0]$ 满足 $i - q[0] > k$,说明队首元素已经不在滑动窗口内,我们需要从队首弹出队首元素; +- 然后,我们计算 $f[i] = \max(0, f[q[0]]) + \textit{nums}[i]$,表示我们将 $\textit{nums}[i]$ 加入滑动窗口后的最大子序列和; +- 接下来,我们更新答案 $\textit{ans} = \max(\textit{ans}, f[i])$; +- 最后,我们将 $i$ 加入队列尾部,并且保持队列的单调性,即如果 $f[q[\textit{back}]] \leq f[i]$,我们需要将队尾元素弹出,直到队列为空或者 $f[q[\textit{back}]] > f[i]$。 + +最终答案即为 $\textit{ans}$。 + +时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 为数组 $\textit{nums}$ 的长度。 + #### Python3 @@ -74,18 +91,18 @@ tags: ```python class Solution: def constrainedSubsetSum(self, nums: List[int], k: int) -> int: + q = deque([0]) n = len(nums) - dp = [0] * n + f = [0] * n ans = -inf - q = deque() - for i, v in enumerate(nums): - if q and i - q[0] > k: + for i, x in enumerate(nums): + while i - q[0] > k: q.popleft() - dp[i] = max(0, 0 if not q else dp[q[0]]) + v - while q and dp[q[-1]] <= dp[i]: + f[i] = max(0, f[q[0]]) + x + ans = max(ans, f[i]) + while q and f[q[-1]] <= f[i]: q.pop() q.append(i) - ans = max(ans, dp[i]) return ans ``` @@ -94,20 +111,21 @@ class Solution: ```java class Solution { public int constrainedSubsetSum(int[] nums, int k) { - int n = nums.length; - int[] dp = new int[n]; - int ans = Integer.MIN_VALUE; Deque q = new ArrayDeque<>(); + q.offer(0); + int n = nums.length; + int[] f = new int[n]; + int ans = -(1 << 30); for (int i = 0; i < n; ++i) { - if (!q.isEmpty() && i - q.peek() > k) { - q.poll(); + while (i - q.peekFirst() > k) { + q.pollFirst(); } - dp[i] = Math.max(0, q.isEmpty() ? 0 : dp[q.peek()]) + nums[i]; - while (!q.isEmpty() && dp[q.peekLast()] <= dp[i]) { + f[i] = Math.max(0, f[q.peekFirst()]) + nums[i]; + ans = Math.max(ans, f[i]); + while (!q.isEmpty() && f[q.peekLast()] <= f[i]) { q.pollLast(); } - q.offer(i); - ans = Math.max(ans, dp[i]); + q.offerLast(i); } return ans; } @@ -120,15 +138,20 @@ class Solution { class Solution { public: int constrainedSubsetSum(vector& nums, int k) { + deque q = {0}; int n = nums.size(); - vector dp(n); + int f[n]; + f[0] = 0; int ans = INT_MIN; - deque q; for (int i = 0; i < n; ++i) { - if (!q.empty() && i - q.front() > k) q.pop_front(); - dp[i] = max(0, q.empty() ? 0 : dp[q.front()]) + nums[i]; - ans = max(ans, dp[i]); - while (!q.empty() && dp[q.back()] <= dp[i]) q.pop_back(); + while (i - q.front() > k) { + q.pop_front(); + } + f[i] = max(0, f[q.front()]) + nums[i]; + ans = max(ans, f[i]); + while (!q.empty() && f[q.back()] <= f[i]) { + q.pop_back(); + } q.push_back(i); } return ans; @@ -140,26 +163,202 @@ public: ```go func constrainedSubsetSum(nums []int, k int) int { + q := Deque{} + q.PushFront(0) n := len(nums) - dp := make([]int, n) - ans := math.MinInt32 - q := []int{} - for i, v := range nums { - if len(q) > 0 && i-q[0] > k { - q = q[1:] - } - dp[i] = v - if len(q) > 0 && dp[q[0]] > 0 { - dp[i] += dp[q[0]] + f := make([]int, n) + ans := nums[0] + for i, x := range nums { + for i-q.Front() > k { + q.PopFront() } - for len(q) > 0 && dp[q[len(q)-1]] < dp[i] { - q = q[:len(q)-1] + f[i] = max(0, f[q.Front()]) + x + ans = max(ans, f[i]) + for !q.Empty() && f[q.Back()] <= f[i] { + q.PopBack() } - q = append(q, i) - ans = max(ans, dp[i]) + q.PushBack(i) } return ans } + +// template +type Deque struct{ l, r []int } + +func (q Deque) Empty() bool { + return len(q.l) == 0 && len(q.r) == 0 +} + +func (q Deque) Size() int { + return len(q.l) + len(q.r) +} + +func (q *Deque) PushFront(v int) { + q.l = append(q.l, v) +} + +func (q *Deque) PushBack(v int) { + q.r = append(q.r, v) +} + +func (q *Deque) PopFront() (v int) { + if len(q.l) > 0 { + q.l, v = q.l[:len(q.l)-1], q.l[len(q.l)-1] + } else { + v, q.r = q.r[0], q.r[1:] + } + return +} + +func (q *Deque) PopBack() (v int) { + if len(q.r) > 0 { + q.r, v = q.r[:len(q.r)-1], q.r[len(q.r)-1] + } else { + v, q.l = q.l[0], q.l[1:] + } + return +} + +func (q Deque) Front() int { + if len(q.l) > 0 { + return q.l[len(q.l)-1] + } + return q.r[0] +} + +func (q Deque) Back() int { + if len(q.r) > 0 { + return q.r[len(q.r)-1] + } + return q.l[0] +} + +func (q Deque) Get(i int) int { + if i < len(q.l) { + return q.l[len(q.l)-1-i] + } + return q.r[i-len(q.l)] +} +``` + +#### TypeScript + +```ts +function constrainedSubsetSum(nums: number[], k: number): number { + const q = new Deque(); + const n = nums.length; + q.pushBack(0); + let ans = nums[0]; + const f: number[] = Array(n).fill(0); + for (let i = 0; i < n; ++i) { + while (i - q.frontValue()! > k) { + q.popFront(); + } + f[i] = Math.max(0, f[q.frontValue()!]!) + nums[i]; + ans = Math.max(ans, f[i]); + while (!q.isEmpty() && f[q.backValue()!]! <= f[i]) { + q.popBack(); + } + q.pushBack(i); + } + return ans; +} + +class Node { + value: T; + next: Node | null; + prev: Node | null; + + constructor(value: T) { + this.value = value; + this.next = null; + this.prev = null; + } +} + +class Deque { + private front: Node | null; + private back: Node | null; + private size: number; + + constructor() { + this.front = null; + this.back = null; + this.size = 0; + } + + pushFront(val: T): void { + const newNode = new Node(val); + if (this.isEmpty()) { + this.front = newNode; + this.back = newNode; + } else { + newNode.next = this.front; + this.front!.prev = newNode; + this.front = newNode; + } + this.size++; + } + + pushBack(val: T): void { + const newNode = new Node(val); + if (this.isEmpty()) { + this.front = newNode; + this.back = newNode; + } else { + newNode.prev = this.back; + this.back!.next = newNode; + this.back = newNode; + } + this.size++; + } + + popFront(): T | undefined { + if (this.isEmpty()) { + return undefined; + } + const value = this.front!.value; + this.front = this.front!.next; + if (this.front !== null) { + this.front.prev = null; + } else { + this.back = null; + } + this.size--; + return value; + } + + popBack(): T | undefined { + if (this.isEmpty()) { + return undefined; + } + const value = this.back!.value; + this.back = this.back!.prev; + if (this.back !== null) { + this.back.next = null; + } else { + this.front = null; + } + this.size--; + return value; + } + + frontValue(): T | undefined { + return this.front?.value; + } + + backValue(): T | undefined { + return this.back?.value; + } + + getSize(): number { + return this.size; + } + + isEmpty(): boolean { + return this.size === 0; + } +} ``` diff --git a/solution/1400-1499/1425.Constrained Subsequence Sum/README_EN.md b/solution/1400-1499/1425.Constrained Subsequence Sum/README_EN.md index ba1cc253f1591..f54456af13198 100644 --- a/solution/1400-1499/1425.Constrained Subsequence Sum/README_EN.md +++ b/solution/1400-1499/1425.Constrained Subsequence Sum/README_EN.md @@ -66,7 +66,24 @@ tags: -### Solution 1 +### Solution 1: Dynamic Programming + Monotonic Queue + +We define $f[i]$ to represent the maximum sum of the subsequence ending at $\textit{nums}[i]$ that meets the conditions. Initially, $f[i] = 0$, and the answer is $\max_{0 \leq i \lt n} f(i)$. + +We notice that the problem requires us to maintain the maximum value of a sliding window, which is a typical application scenario for a monotonic queue. We can use a monotonic queue to optimize the dynamic programming transition. + +We maintain a monotonic queue $q$ that is decreasing from the front to the back, storing the indices $i$. Initially, we add a sentinel $0$ to the queue. + +We traverse $i$ from $0$ to $n - 1$. For each $i$, we perform the following operations: + +- If the front element $q[0]$ satisfies $i - q[0] > k$, it means the front element is no longer within the sliding window, and we need to remove the front element from the queue; +- Then, we calculate $f[i] = \max(0, f[q[0]]) + \textit{nums}[i]$, which means we add $\textit{nums}[i]$ to the sliding window to get the maximum subsequence sum; +- Next, we update the answer $\textit{ans} = \max(\textit{ans}, f[i])$; +- Finally, we add $i$ to the back of the queue and maintain the monotonicity of the queue. If $f[q[\textit{back}]] \leq f[i]$, we need to remove the back element until the queue is empty or $f[q[\textit{back}]] > f[i]$. + +The final answer is $\textit{ans}$. + +The time complexity is $O(n)$, and the space complexity is $O(n)$. Here, $n$ is the length of the array $\textit{nums}$. @@ -75,18 +92,18 @@ tags: ```python class Solution: def constrainedSubsetSum(self, nums: List[int], k: int) -> int: + q = deque([0]) n = len(nums) - dp = [0] * n + f = [0] * n ans = -inf - q = deque() - for i, v in enumerate(nums): - if q and i - q[0] > k: + for i, x in enumerate(nums): + while i - q[0] > k: q.popleft() - dp[i] = max(0, 0 if not q else dp[q[0]]) + v - while q and dp[q[-1]] <= dp[i]: + f[i] = max(0, f[q[0]]) + x + ans = max(ans, f[i]) + while q and f[q[-1]] <= f[i]: q.pop() q.append(i) - ans = max(ans, dp[i]) return ans ``` @@ -95,20 +112,21 @@ class Solution: ```java class Solution { public int constrainedSubsetSum(int[] nums, int k) { - int n = nums.length; - int[] dp = new int[n]; - int ans = Integer.MIN_VALUE; Deque q = new ArrayDeque<>(); + q.offer(0); + int n = nums.length; + int[] f = new int[n]; + int ans = -(1 << 30); for (int i = 0; i < n; ++i) { - if (!q.isEmpty() && i - q.peek() > k) { - q.poll(); + while (i - q.peekFirst() > k) { + q.pollFirst(); } - dp[i] = Math.max(0, q.isEmpty() ? 0 : dp[q.peek()]) + nums[i]; - while (!q.isEmpty() && dp[q.peekLast()] <= dp[i]) { + f[i] = Math.max(0, f[q.peekFirst()]) + nums[i]; + ans = Math.max(ans, f[i]); + while (!q.isEmpty() && f[q.peekLast()] <= f[i]) { q.pollLast(); } - q.offer(i); - ans = Math.max(ans, dp[i]); + q.offerLast(i); } return ans; } @@ -121,15 +139,20 @@ class Solution { class Solution { public: int constrainedSubsetSum(vector& nums, int k) { + deque q = {0}; int n = nums.size(); - vector dp(n); + int f[n]; + f[0] = 0; int ans = INT_MIN; - deque q; for (int i = 0; i < n; ++i) { - if (!q.empty() && i - q.front() > k) q.pop_front(); - dp[i] = max(0, q.empty() ? 0 : dp[q.front()]) + nums[i]; - ans = max(ans, dp[i]); - while (!q.empty() && dp[q.back()] <= dp[i]) q.pop_back(); + while (i - q.front() > k) { + q.pop_front(); + } + f[i] = max(0, f[q.front()]) + nums[i]; + ans = max(ans, f[i]); + while (!q.empty() && f[q.back()] <= f[i]) { + q.pop_back(); + } q.push_back(i); } return ans; @@ -141,26 +164,202 @@ public: ```go func constrainedSubsetSum(nums []int, k int) int { + q := Deque{} + q.PushFront(0) n := len(nums) - dp := make([]int, n) - ans := math.MinInt32 - q := []int{} - for i, v := range nums { - if len(q) > 0 && i-q[0] > k { - q = q[1:] - } - dp[i] = v - if len(q) > 0 && dp[q[0]] > 0 { - dp[i] += dp[q[0]] + f := make([]int, n) + ans := nums[0] + for i, x := range nums { + for i-q.Front() > k { + q.PopFront() } - for len(q) > 0 && dp[q[len(q)-1]] < dp[i] { - q = q[:len(q)-1] + f[i] = max(0, f[q.Front()]) + x + ans = max(ans, f[i]) + for !q.Empty() && f[q.Back()] <= f[i] { + q.PopBack() } - q = append(q, i) - ans = max(ans, dp[i]) + q.PushBack(i) } return ans } + +// template +type Deque struct{ l, r []int } + +func (q Deque) Empty() bool { + return len(q.l) == 0 && len(q.r) == 0 +} + +func (q Deque) Size() int { + return len(q.l) + len(q.r) +} + +func (q *Deque) PushFront(v int) { + q.l = append(q.l, v) +} + +func (q *Deque) PushBack(v int) { + q.r = append(q.r, v) +} + +func (q *Deque) PopFront() (v int) { + if len(q.l) > 0 { + q.l, v = q.l[:len(q.l)-1], q.l[len(q.l)-1] + } else { + v, q.r = q.r[0], q.r[1:] + } + return +} + +func (q *Deque) PopBack() (v int) { + if len(q.r) > 0 { + q.r, v = q.r[:len(q.r)-1], q.r[len(q.r)-1] + } else { + v, q.l = q.l[0], q.l[1:] + } + return +} + +func (q Deque) Front() int { + if len(q.l) > 0 { + return q.l[len(q.l)-1] + } + return q.r[0] +} + +func (q Deque) Back() int { + if len(q.r) > 0 { + return q.r[len(q.r)-1] + } + return q.l[0] +} + +func (q Deque) Get(i int) int { + if i < len(q.l) { + return q.l[len(q.l)-1-i] + } + return q.r[i-len(q.l)] +} +``` + +#### TypeScript + +```ts +function constrainedSubsetSum(nums: number[], k: number): number { + const q = new Deque(); + const n = nums.length; + q.pushBack(0); + let ans = nums[0]; + const f: number[] = Array(n).fill(0); + for (let i = 0; i < n; ++i) { + while (i - q.frontValue()! > k) { + q.popFront(); + } + f[i] = Math.max(0, f[q.frontValue()!]!) + nums[i]; + ans = Math.max(ans, f[i]); + while (!q.isEmpty() && f[q.backValue()!]! <= f[i]) { + q.popBack(); + } + q.pushBack(i); + } + return ans; +} + +class Node { + value: T; + next: Node | null; + prev: Node | null; + + constructor(value: T) { + this.value = value; + this.next = null; + this.prev = null; + } +} + +class Deque { + private front: Node | null; + private back: Node | null; + private size: number; + + constructor() { + this.front = null; + this.back = null; + this.size = 0; + } + + pushFront(val: T): void { + const newNode = new Node(val); + if (this.isEmpty()) { + this.front = newNode; + this.back = newNode; + } else { + newNode.next = this.front; + this.front!.prev = newNode; + this.front = newNode; + } + this.size++; + } + + pushBack(val: T): void { + const newNode = new Node(val); + if (this.isEmpty()) { + this.front = newNode; + this.back = newNode; + } else { + newNode.prev = this.back; + this.back!.next = newNode; + this.back = newNode; + } + this.size++; + } + + popFront(): T | undefined { + if (this.isEmpty()) { + return undefined; + } + const value = this.front!.value; + this.front = this.front!.next; + if (this.front !== null) { + this.front.prev = null; + } else { + this.back = null; + } + this.size--; + return value; + } + + popBack(): T | undefined { + if (this.isEmpty()) { + return undefined; + } + const value = this.back!.value; + this.back = this.back!.prev; + if (this.back !== null) { + this.back.next = null; + } else { + this.front = null; + } + this.size--; + return value; + } + + frontValue(): T | undefined { + return this.front?.value; + } + + backValue(): T | undefined { + return this.back?.value; + } + + getSize(): number { + return this.size; + } + + isEmpty(): boolean { + return this.size === 0; + } +} ``` diff --git a/solution/1400-1499/1425.Constrained Subsequence Sum/Solution.cpp b/solution/1400-1499/1425.Constrained Subsequence Sum/Solution.cpp index ddddd9b3b97f5..a8c73b28dacea 100644 --- a/solution/1400-1499/1425.Constrained Subsequence Sum/Solution.cpp +++ b/solution/1400-1499/1425.Constrained Subsequence Sum/Solution.cpp @@ -1,17 +1,22 @@ class Solution { public: int constrainedSubsetSum(vector& nums, int k) { + deque q = {0}; int n = nums.size(); - vector dp(n); + int f[n]; + f[0] = 0; int ans = INT_MIN; - deque q; for (int i = 0; i < n; ++i) { - if (!q.empty() && i - q.front() > k) q.pop_front(); - dp[i] = max(0, q.empty() ? 0 : dp[q.front()]) + nums[i]; - ans = max(ans, dp[i]); - while (!q.empty() && dp[q.back()] <= dp[i]) q.pop_back(); + while (i - q.front() > k) { + q.pop_front(); + } + f[i] = max(0, f[q.front()]) + nums[i]; + ans = max(ans, f[i]); + while (!q.empty() && f[q.back()] <= f[i]) { + q.pop_back(); + } q.push_back(i); } return ans; } -}; \ No newline at end of file +}; diff --git a/solution/1400-1499/1425.Constrained Subsequence Sum/Solution.go b/solution/1400-1499/1425.Constrained Subsequence Sum/Solution.go index 29433a5b8a943..328f87223c8eb 100644 --- a/solution/1400-1499/1425.Constrained Subsequence Sum/Solution.go +++ b/solution/1400-1499/1425.Constrained Subsequence Sum/Solution.go @@ -1,21 +1,77 @@ func constrainedSubsetSum(nums []int, k int) int { + q := Deque{} + q.PushFront(0) n := len(nums) - dp := make([]int, n) - ans := math.MinInt32 - q := []int{} - for i, v := range nums { - if len(q) > 0 && i-q[0] > k { - q = q[1:] + f := make([]int, n) + ans := nums[0] + for i, x := range nums { + for i-q.Front() > k { + q.PopFront() } - dp[i] = v - if len(q) > 0 && dp[q[0]] > 0 { - dp[i] += dp[q[0]] + f[i] = max(0, f[q.Front()]) + x + ans = max(ans, f[i]) + for !q.Empty() && f[q.Back()] <= f[i] { + q.PopBack() } - for len(q) > 0 && dp[q[len(q)-1]] < dp[i] { - q = q[:len(q)-1] - } - q = append(q, i) - ans = max(ans, dp[i]) + q.PushBack(i) } return ans -} \ No newline at end of file +} + +// template +type Deque struct{ l, r []int } + +func (q Deque) Empty() bool { + return len(q.l) == 0 && len(q.r) == 0 +} + +func (q Deque) Size() int { + return len(q.l) + len(q.r) +} + +func (q *Deque) PushFront(v int) { + q.l = append(q.l, v) +} + +func (q *Deque) PushBack(v int) { + q.r = append(q.r, v) +} + +func (q *Deque) PopFront() (v int) { + if len(q.l) > 0 { + q.l, v = q.l[:len(q.l)-1], q.l[len(q.l)-1] + } else { + v, q.r = q.r[0], q.r[1:] + } + return +} + +func (q *Deque) PopBack() (v int) { + if len(q.r) > 0 { + q.r, v = q.r[:len(q.r)-1], q.r[len(q.r)-1] + } else { + v, q.l = q.l[0], q.l[1:] + } + return +} + +func (q Deque) Front() int { + if len(q.l) > 0 { + return q.l[len(q.l)-1] + } + return q.r[0] +} + +func (q Deque) Back() int { + if len(q.r) > 0 { + return q.r[len(q.r)-1] + } + return q.l[0] +} + +func (q Deque) Get(i int) int { + if i < len(q.l) { + return q.l[len(q.l)-1-i] + } + return q.r[i-len(q.l)] +} diff --git a/solution/1400-1499/1425.Constrained Subsequence Sum/Solution.java b/solution/1400-1499/1425.Constrained Subsequence Sum/Solution.java index b9f2d95789a36..cae54e5014f36 100644 --- a/solution/1400-1499/1425.Constrained Subsequence Sum/Solution.java +++ b/solution/1400-1499/1425.Constrained Subsequence Sum/Solution.java @@ -1,20 +1,21 @@ class Solution { public int constrainedSubsetSum(int[] nums, int k) { - int n = nums.length; - int[] dp = new int[n]; - int ans = Integer.MIN_VALUE; Deque q = new ArrayDeque<>(); + q.offer(0); + int n = nums.length; + int[] f = new int[n]; + int ans = -(1 << 30); for (int i = 0; i < n; ++i) { - if (!q.isEmpty() && i - q.peek() > k) { - q.poll(); + while (i - q.peekFirst() > k) { + q.pollFirst(); } - dp[i] = Math.max(0, q.isEmpty() ? 0 : dp[q.peek()]) + nums[i]; - while (!q.isEmpty() && dp[q.peekLast()] <= dp[i]) { + f[i] = Math.max(0, f[q.peekFirst()]) + nums[i]; + ans = Math.max(ans, f[i]); + while (!q.isEmpty() && f[q.peekLast()] <= f[i]) { q.pollLast(); } - q.offer(i); - ans = Math.max(ans, dp[i]); + q.offerLast(i); } return ans; } -} \ No newline at end of file +} diff --git a/solution/1400-1499/1425.Constrained Subsequence Sum/Solution.py b/solution/1400-1499/1425.Constrained Subsequence Sum/Solution.py index cdaade9562397..0e76b39093b9e 100644 --- a/solution/1400-1499/1425.Constrained Subsequence Sum/Solution.py +++ b/solution/1400-1499/1425.Constrained Subsequence Sum/Solution.py @@ -1,15 +1,15 @@ class Solution: def constrainedSubsetSum(self, nums: List[int], k: int) -> int: + q = deque([0]) n = len(nums) - dp = [0] * n + f = [0] * n ans = -inf - q = deque() - for i, v in enumerate(nums): - if q and i - q[0] > k: + for i, x in enumerate(nums): + while i - q[0] > k: q.popleft() - dp[i] = max(0, 0 if not q else dp[q[0]]) + v - while q and dp[q[-1]] <= dp[i]: + f[i] = max(0, f[q[0]]) + x + ans = max(ans, f[i]) + while q and f[q[-1]] <= f[i]: q.pop() q.append(i) - ans = max(ans, dp[i]) return ans diff --git a/solution/1400-1499/1425.Constrained Subsequence Sum/Solution.ts b/solution/1400-1499/1425.Constrained Subsequence Sum/Solution.ts new file mode 100644 index 0000000000000..a4c4cb0048041 --- /dev/null +++ b/solution/1400-1499/1425.Constrained Subsequence Sum/Solution.ts @@ -0,0 +1,115 @@ +function constrainedSubsetSum(nums: number[], k: number): number { + const q = new Deque(); + const n = nums.length; + q.pushBack(0); + let ans = nums[0]; + const f: number[] = Array(n).fill(0); + for (let i = 0; i < n; ++i) { + while (i - q.frontValue()! > k) { + q.popFront(); + } + f[i] = Math.max(0, f[q.frontValue()!]!) + nums[i]; + ans = Math.max(ans, f[i]); + while (!q.isEmpty() && f[q.backValue()!]! <= f[i]) { + q.popBack(); + } + q.pushBack(i); + } + return ans; +} + +class Node { + value: T; + next: Node | null; + prev: Node | null; + + constructor(value: T) { + this.value = value; + this.next = null; + this.prev = null; + } +} + +class Deque { + private front: Node | null; + private back: Node | null; + private size: number; + + constructor() { + this.front = null; + this.back = null; + this.size = 0; + } + + pushFront(val: T): void { + const newNode = new Node(val); + if (this.isEmpty()) { + this.front = newNode; + this.back = newNode; + } else { + newNode.next = this.front; + this.front!.prev = newNode; + this.front = newNode; + } + this.size++; + } + + pushBack(val: T): void { + const newNode = new Node(val); + if (this.isEmpty()) { + this.front = newNode; + this.back = newNode; + } else { + newNode.prev = this.back; + this.back!.next = newNode; + this.back = newNode; + } + this.size++; + } + + popFront(): T | undefined { + if (this.isEmpty()) { + return undefined; + } + const value = this.front!.value; + this.front = this.front!.next; + if (this.front !== null) { + this.front.prev = null; + } else { + this.back = null; + } + this.size--; + return value; + } + + popBack(): T | undefined { + if (this.isEmpty()) { + return undefined; + } + const value = this.back!.value; + this.back = this.back!.prev; + if (this.back !== null) { + this.back.next = null; + } else { + this.front = null; + } + this.size--; + return value; + } + + frontValue(): T | undefined { + return this.front?.value; + } + + backValue(): T | undefined { + return this.back?.value; + } + + getSize(): number { + return this.size; + } + + isEmpty(): boolean { + return this.size === 0; + } +} From bdb25f174c1c69be37e3cb17ba2c0d95cd0f5fc8 Mon Sep 17 00:00:00 2001 From: yanglbme Date: Sat, 17 Aug 2024 14:47:26 +0800 Subject: [PATCH 2/2] feat: add solutions --- .../README.md | 237 +++++------------ .../README_EN.md | 239 +++++------------- .../Solution.cpp | 16 +- .../Solution.go | 26 +- .../Solution.java | 26 +- .../Solution.py | 8 +- .../Solution.rs | 30 +-- .../Solution.ts | 27 +- .../Solution2.cpp | 14 - .../Solution2.go | 22 -- .../Solution2.java | 19 -- .../Solution2.py | 7 - 12 files changed, 181 insertions(+), 490 deletions(-) delete mode 100644 solution/1400-1499/1422.Maximum Score After Splitting a String/Solution2.cpp delete mode 100644 solution/1400-1499/1422.Maximum Score After Splitting a String/Solution2.go delete mode 100644 solution/1400-1499/1422.Maximum Score After Splitting a String/Solution2.java delete mode 100644 solution/1400-1499/1422.Maximum Score After Splitting a String/Solution2.py diff --git a/solution/1400-1499/1422.Maximum Score After Splitting a String/README.md b/solution/1400-1499/1422.Maximum Score After Splitting a String/README.md index 3bbc25b38b792..c52c53c201fcb 100644 --- a/solution/1400-1499/1422.Maximum Score After Splitting a String/README.md +++ b/solution/1400-1499/1422.Maximum Score After Splitting a String/README.md @@ -28,13 +28,13 @@ tags:

示例 1:

输入:s = "011101"
-输出:5 
+输出:5
 解释:
 将字符串 s 划分为两个非空子字符串的可行方案有:
-左子字符串 = "0" 且 右子字符串 = "11101",得分 = 1 + 4 = 5 
-左子字符串 = "01" 且 右子字符串 = "1101",得分 = 1 + 3 = 4 
-左子字符串 = "011" 且 右子字符串 = "101",得分 = 1 + 2 = 3 
-左子字符串 = "0111" 且 右子字符串 = "01",得分 = 1 + 1 = 2 
+左子字符串 = "0" 且 右子字符串 = "11101",得分 = 1 + 4 = 5
+左子字符串 = "01" 且 右子字符串 = "1101",得分 = 1 + 3 = 4
+左子字符串 = "011" 且 右子字符串 = "101",得分 = 1 + 2 = 3
+左子字符串 = "0111" 且 右子字符串 = "01",得分 = 1 + 1 = 2
 左子字符串 = "01110" 且 右子字符串 = "1",得分 = 2 + 1 = 3
 
@@ -66,7 +66,13 @@ tags: -### 方法一 +### 方法一:计数 + +我们用两个变量 $l$ 和 $r$ 分别记录左子字符串中 $0$ 的数量和右子字符串中 $1$ 的数量。初始时 $l = 0$,而 $r$ 则等于字符串 $s$ 中 $1$ 的数量。 + +遍历字符串 $s$ 的前 $n - 1$ 个字符,对于每一个位置 $i$,如果 $s[i] = 0$,则 $l$ 自增 $1$,否则 $r$ 自减 $1$。然后我们更新答案为 $l + r$ 的最大值。 + +时间复杂度 $O(n)$,其中 $n$ 为字符串 $s$ 的长度。空间复杂度 $O(1)$。 @@ -75,7 +81,13 @@ tags: ```python class Solution: def maxScore(self, s: str) -> int: - return max(s[:i].count('0') + s[i:].count('1') for i in range(1, len(s))) + l, r = 0, s.count("1") + ans = 0 + for x in s[:-1]: + l += int(x) ^ 1 + r -= int(x) + ans = max(ans, l + r) + return ans ``` #### Java @@ -83,20 +95,18 @@ class Solution: ```java class Solution { public int maxScore(String s) { - int ans = 0; - for (int i = 1; i < s.length(); ++i) { - int t = 0; - for (int j = 0; j < i; ++j) { - if (s.charAt(j) == '0') { - ++t; - } - } - for (int j = i; j < s.length(); ++j) { - if (s.charAt(j) == '1') { - ++t; - } + int l = 0, r = 0; + int n = s.length(); + for (int i = 0; i < n; ++i) { + if (s.charAt(i) == '1') { + ++r; } - ans = Math.max(ans, t); + } + int ans = 0; + for (int i = 0; i < n - 1; ++i) { + l += (s.charAt(i) - '0') ^ 1; + r -= s.charAt(i) - '0'; + ans = Math.max(ans, l + r); } return ans; } @@ -109,16 +119,12 @@ class Solution { class Solution { public: int maxScore(string s) { + int l = 0, r = count(s.begin(), s.end(), '1'); int ans = 0; - for (int i = 1, n = s.size(); i < n; ++i) { - int t = 0; - for (int j = 0; j < i; ++j) { - t += s[j] == '0'; - } - for (int j = i; j < n; ++j) { - t += s[j] == '1'; - } - ans = max(ans, t); + for (int i = 0; i < s.size() - 1; ++i) { + l += (s[i] - '0') ^ 1; + r -= s[i] - '0'; + ans = max(ans, l + r); } return ans; } @@ -128,23 +134,17 @@ public: #### Go ```go -func maxScore(s string) int { - ans := 0 - for i, n := 1, len(s); i < n; i++ { - t := 0 - for j := 0; j < i; j++ { - if s[j] == '0' { - t++ - } - } - for j := i; j < n; j++ { - if s[j] == '1' { - t++ - } +func maxScore(s string) (ans int) { + l, r := 0, strings.Count(s, "1") + for _, c := range s[:len(s)-1] { + if c == '0' { + l++ + } else { + r-- } - ans = max(ans, t) + ans = max(ans, l+r) } - return ans + return } ``` @@ -152,27 +152,20 @@ func maxScore(s string) int { ```ts function maxScore(s: string): number { - const n = s.length; - let res = 0; - let score = 0; - if (s[0] === '0') { - score++; + let [l, r] = [0, 0]; + for (const c of s) { + r += c === '1' ? 1 : 0; } - for (let i = 1; i < n; i++) { - if (s[i] === '1') { - score++; - } - } - res = Math.max(res, score); - for (let i = 1; i < n - 1; i++) { + let ans = 0; + for (let i = 0; i < s.length - 1; ++i) { if (s[i] === '0') { - score++; - } else if (s[i] === '1') { - score--; + ++l; + } else { + --r; } - res = Math.max(res, score); + ans = Math.max(ans, l + r); } - return res; + return ans; } ``` @@ -181,121 +174,17 @@ function maxScore(s: string): number { ```rust impl Solution { pub fn max_score(s: String) -> i32 { - let n = s.len(); - let mut res = 0; - let mut score = 0; - let bs = s.as_bytes(); - if bs[0] == b'0' { - score += 1; - } - for i in 1..n { - if bs[i] == b'1' { - score += 1; - } - } - res = res.max(score); - for i in 1..n - 1 { - if bs[i] == b'0' { - score += 1; - } else if bs[i] == b'1' { - score -= 1; - } - res = res.max(score); - } - res - } -} -``` - - - - - - - -### 方法二 - - - -#### Python3 - -```python -class Solution: - def maxScore(self, s: str) -> int: - ans = t = (s[0] == '0') + s[1:].count('1') - for i in range(1, len(s) - 1): - t += 1 if s[i] == '0' else -1 - ans = max(ans, t) - return ans -``` - -#### Java - -```java -class Solution { - public int maxScore(String s) { - int t = 0; - if (s.charAt(0) == '0') { - t++; - } - for (int i = 1; i < s.length(); ++i) { - if (s.charAt(i) == '1') { - t++; - } - } - int ans = t; - for (int i = 1; i < s.length() - 1; ++i) { - t += s.charAt(i) == '0' ? 1 : -1; - ans = Math.max(ans, t); - } - return ans; - } -} -``` - -#### C++ - -```cpp -class Solution { -public: - int maxScore(string s) { - int t = 0; - if (s[0] == '0') ++t; - for (int i = 1; i < s.size(); ++i) t += s[i] == '1'; - int ans = t; - for (int i = 1; i < s.size() - 1; ++i) { - t += s[i] == '0' ? 1 : -1; - ans = max(ans, t); + let mut l = 0; + let mut r = s.bytes().filter(|&b| b == b'1').count() as i32; + let mut ans = 0; + let cs = s.as_bytes(); + for i in 0..s.len() - 1 { + l += ((cs[i] - b'0') ^ 1) as i32; + r -= (cs[i] - b'0') as i32; + ans = ans.max(l + r); } - return ans; + ans } -}; -``` - -#### Go - -```go -func maxScore(s string) int { - t := 0 - if s[0] == '0' { - t++ - } - n := len(s) - for i := 1; i < n; i++ { - if s[i] == '1' { - t++ - } - } - ans := t - for i := 1; i < n-1; i++ { - if s[i] == '0' { - t++ - } else { - t-- - } - ans = max(ans, t) - } - return ans } ``` diff --git a/solution/1400-1499/1422.Maximum Score After Splitting a String/README_EN.md b/solution/1400-1499/1422.Maximum Score After Splitting a String/README_EN.md index 835d2d1d96eda..7baca8a654425 100644 --- a/solution/1400-1499/1422.Maximum Score After Splitting a String/README_EN.md +++ b/solution/1400-1499/1422.Maximum Score After Splitting a String/README_EN.md @@ -28,13 +28,13 @@ tags:
 Input: s = "011101"
-Output: 5 
-Explanation: 
+Output: 5
+Explanation:
 All possible ways of splitting s into two non-empty substrings are:
-left = "0" and right = "11101", score = 1 + 4 = 5 
-left = "01" and right = "1101", score = 1 + 3 = 4 
-left = "011" and right = "101", score = 1 + 2 = 3 
-left = "0111" and right = "01", score = 1 + 1 = 2 
+left = "0" and right = "11101", score = 1 + 4 = 5
+left = "01" and right = "1101", score = 1 + 3 = 4
+left = "011" and right = "101", score = 1 + 2 = 3
+left = "0111" and right = "01", score = 1 + 1 = 2
 left = "01110" and right = "1", score = 2 + 1 = 3
 
@@ -67,7 +67,13 @@ left = "01110" and right = "1", score = 2 + 1 = 3 -### Solution 1 +### Solution 1: Counting + +We use two variables $l$ and $r$ to record the number of 0s in the left substring and the number of 1s in the right substring, respectively. Initially, $l = 0$, and $r$ is equal to the number of 1s in the string $s$. + +We traverse the first $n - 1$ characters of the string $s$. For each position $i$, if $s[i] = 0$, then $l$ is incremented by 1; otherwise, $r$ is decremented by 1. Then we update the answer to be the maximum value of $l + r$. + +The time complexity is $O(n)$, where $n$ is the length of the string $s$. The space complexity is $O(1)$. @@ -76,7 +82,13 @@ left = "01110" and right = "1", score = 2 + 1 = 3 ```python class Solution: def maxScore(self, s: str) -> int: - return max(s[:i].count('0') + s[i:].count('1') for i in range(1, len(s))) + l, r = 0, s.count("1") + ans = 0 + for x in s[:-1]: + l += int(x) ^ 1 + r -= int(x) + ans = max(ans, l + r) + return ans ``` #### Java @@ -84,20 +96,18 @@ class Solution: ```java class Solution { public int maxScore(String s) { - int ans = 0; - for (int i = 1; i < s.length(); ++i) { - int t = 0; - for (int j = 0; j < i; ++j) { - if (s.charAt(j) == '0') { - ++t; - } - } - for (int j = i; j < s.length(); ++j) { - if (s.charAt(j) == '1') { - ++t; - } + int l = 0, r = 0; + int n = s.length(); + for (int i = 0; i < n; ++i) { + if (s.charAt(i) == '1') { + ++r; } - ans = Math.max(ans, t); + } + int ans = 0; + for (int i = 0; i < n - 1; ++i) { + l += (s.charAt(i) - '0') ^ 1; + r -= s.charAt(i) - '0'; + ans = Math.max(ans, l + r); } return ans; } @@ -110,16 +120,12 @@ class Solution { class Solution { public: int maxScore(string s) { + int l = 0, r = count(s.begin(), s.end(), '1'); int ans = 0; - for (int i = 1, n = s.size(); i < n; ++i) { - int t = 0; - for (int j = 0; j < i; ++j) { - t += s[j] == '0'; - } - for (int j = i; j < n; ++j) { - t += s[j] == '1'; - } - ans = max(ans, t); + for (int i = 0; i < s.size() - 1; ++i) { + l += (s[i] - '0') ^ 1; + r -= s[i] - '0'; + ans = max(ans, l + r); } return ans; } @@ -129,23 +135,17 @@ public: #### Go ```go -func maxScore(s string) int { - ans := 0 - for i, n := 1, len(s); i < n; i++ { - t := 0 - for j := 0; j < i; j++ { - if s[j] == '0' { - t++ - } - } - for j := i; j < n; j++ { - if s[j] == '1' { - t++ - } +func maxScore(s string) (ans int) { + l, r := 0, strings.Count(s, "1") + for _, c := range s[:len(s)-1] { + if c == '0' { + l++ + } else { + r-- } - ans = max(ans, t) + ans = max(ans, l+r) } - return ans + return } ``` @@ -153,27 +153,20 @@ func maxScore(s string) int { ```ts function maxScore(s: string): number { - const n = s.length; - let res = 0; - let score = 0; - if (s[0] === '0') { - score++; + let [l, r] = [0, 0]; + for (const c of s) { + r += c === '1' ? 1 : 0; } - for (let i = 1; i < n; i++) { - if (s[i] === '1') { - score++; - } - } - res = Math.max(res, score); - for (let i = 1; i < n - 1; i++) { + let ans = 0; + for (let i = 0; i < s.length - 1; ++i) { if (s[i] === '0') { - score++; - } else if (s[i] === '1') { - score--; + ++l; + } else { + --r; } - res = Math.max(res, score); + ans = Math.max(ans, l + r); } - return res; + return ans; } ``` @@ -182,121 +175,17 @@ function maxScore(s: string): number { ```rust impl Solution { pub fn max_score(s: String) -> i32 { - let n = s.len(); - let mut res = 0; - let mut score = 0; - let bs = s.as_bytes(); - if bs[0] == b'0' { - score += 1; - } - for i in 1..n { - if bs[i] == b'1' { - score += 1; - } - } - res = res.max(score); - for i in 1..n - 1 { - if bs[i] == b'0' { - score += 1; - } else if bs[i] == b'1' { - score -= 1; - } - res = res.max(score); - } - res - } -} -``` - - - - - - - -### Solution 2 - - - -#### Python3 - -```python -class Solution: - def maxScore(self, s: str) -> int: - ans = t = (s[0] == '0') + s[1:].count('1') - for i in range(1, len(s) - 1): - t += 1 if s[i] == '0' else -1 - ans = max(ans, t) - return ans -``` - -#### Java - -```java -class Solution { - public int maxScore(String s) { - int t = 0; - if (s.charAt(0) == '0') { - t++; - } - for (int i = 1; i < s.length(); ++i) { - if (s.charAt(i) == '1') { - t++; - } - } - int ans = t; - for (int i = 1; i < s.length() - 1; ++i) { - t += s.charAt(i) == '0' ? 1 : -1; - ans = Math.max(ans, t); - } - return ans; - } -} -``` - -#### C++ - -```cpp -class Solution { -public: - int maxScore(string s) { - int t = 0; - if (s[0] == '0') ++t; - for (int i = 1; i < s.size(); ++i) t += s[i] == '1'; - int ans = t; - for (int i = 1; i < s.size() - 1; ++i) { - t += s[i] == '0' ? 1 : -1; - ans = max(ans, t); + let mut l = 0; + let mut r = s.bytes().filter(|&b| b == b'1').count() as i32; + let mut ans = 0; + let cs = s.as_bytes(); + for i in 0..s.len() - 1 { + l += ((cs[i] - b'0') ^ 1) as i32; + r -= (cs[i] - b'0') as i32; + ans = ans.max(l + r); } - return ans; + ans } -}; -``` - -#### Go - -```go -func maxScore(s string) int { - t := 0 - if s[0] == '0' { - t++ - } - n := len(s) - for i := 1; i < n; i++ { - if s[i] == '1' { - t++ - } - } - ans := t - for i := 1; i < n-1; i++ { - if s[i] == '0' { - t++ - } else { - t-- - } - ans = max(ans, t) - } - return ans } ``` diff --git a/solution/1400-1499/1422.Maximum Score After Splitting a String/Solution.cpp b/solution/1400-1499/1422.Maximum Score After Splitting a String/Solution.cpp index f78ec22439dcc..bf8dbbfefbf61 100644 --- a/solution/1400-1499/1422.Maximum Score After Splitting a String/Solution.cpp +++ b/solution/1400-1499/1422.Maximum Score After Splitting a String/Solution.cpp @@ -1,17 +1,13 @@ class Solution { public: int maxScore(string s) { + int l = 0, r = count(s.begin(), s.end(), '1'); int ans = 0; - for (int i = 1, n = s.size(); i < n; ++i) { - int t = 0; - for (int j = 0; j < i; ++j) { - t += s[j] == '0'; - } - for (int j = i; j < n; ++j) { - t += s[j] == '1'; - } - ans = max(ans, t); + for (int i = 0; i < s.size() - 1; ++i) { + l += (s[i] - '0') ^ 1; + r -= s[i] - '0'; + ans = max(ans, l + r); } return ans; } -}; \ No newline at end of file +}; diff --git a/solution/1400-1499/1422.Maximum Score After Splitting a String/Solution.go b/solution/1400-1499/1422.Maximum Score After Splitting a String/Solution.go index 901ebc0bb8520..8c30ed90ece93 100644 --- a/solution/1400-1499/1422.Maximum Score After Splitting a String/Solution.go +++ b/solution/1400-1499/1422.Maximum Score After Splitting a String/Solution.go @@ -1,18 +1,12 @@ -func maxScore(s string) int { - ans := 0 - for i, n := 1, len(s); i < n; i++ { - t := 0 - for j := 0; j < i; j++ { - if s[j] == '0' { - t++ - } +func maxScore(s string) (ans int) { + l, r := 0, strings.Count(s, "1") + for _, c := range s[:len(s)-1] { + if c == '0' { + l++ + } else { + r-- } - for j := i; j < n; j++ { - if s[j] == '1' { - t++ - } - } - ans = max(ans, t) + ans = max(ans, l+r) } - return ans -} \ No newline at end of file + return +} diff --git a/solution/1400-1499/1422.Maximum Score After Splitting a String/Solution.java b/solution/1400-1499/1422.Maximum Score After Splitting a String/Solution.java index e3dad9d463fe2..62f0ab1478582 100644 --- a/solution/1400-1499/1422.Maximum Score After Splitting a String/Solution.java +++ b/solution/1400-1499/1422.Maximum Score After Splitting a String/Solution.java @@ -1,20 +1,18 @@ class Solution { public int maxScore(String s) { - int ans = 0; - for (int i = 1; i < s.length(); ++i) { - int t = 0; - for (int j = 0; j < i; ++j) { - if (s.charAt(j) == '0') { - ++t; - } - } - for (int j = i; j < s.length(); ++j) { - if (s.charAt(j) == '1') { - ++t; - } + int l = 0, r = 0; + int n = s.length(); + for (int i = 0; i < n; ++i) { + if (s.charAt(i) == '1') { + ++r; } - ans = Math.max(ans, t); + } + int ans = 0; + for (int i = 0; i < n - 1; ++i) { + l += (s.charAt(i) - '0') ^ 1; + r -= s.charAt(i) - '0'; + ans = Math.max(ans, l + r); } return ans; } -} \ No newline at end of file +} diff --git a/solution/1400-1499/1422.Maximum Score After Splitting a String/Solution.py b/solution/1400-1499/1422.Maximum Score After Splitting a String/Solution.py index ab07d81eec3ef..57827a3472cf4 100644 --- a/solution/1400-1499/1422.Maximum Score After Splitting a String/Solution.py +++ b/solution/1400-1499/1422.Maximum Score After Splitting a String/Solution.py @@ -1,3 +1,9 @@ class Solution: def maxScore(self, s: str) -> int: - return max(s[:i].count('0') + s[i:].count('1') for i in range(1, len(s))) + l, r = 0, s.count("1") + ans = 0 + for x in s[:-1]: + l += int(x) ^ 1 + r -= int(x) + ans = max(ans, l + r) + return ans diff --git a/solution/1400-1499/1422.Maximum Score After Splitting a String/Solution.rs b/solution/1400-1499/1422.Maximum Score After Splitting a String/Solution.rs index 4f7142e3d7597..a88411fb0c0fe 100644 --- a/solution/1400-1499/1422.Maximum Score After Splitting a String/Solution.rs +++ b/solution/1400-1499/1422.Maximum Score After Splitting a String/Solution.rs @@ -1,26 +1,14 @@ impl Solution { pub fn max_score(s: String) -> i32 { - let n = s.len(); - let mut res = 0; - let mut score = 0; - let bs = s.as_bytes(); - if bs[0] == b'0' { - score += 1; + let mut l = 0; + let mut r = s.bytes().filter(|&b| b == b'1').count() as i32; + let mut ans = 0; + let cs = s.as_bytes(); + for i in 0..s.len() - 1 { + l += ((cs[i] - b'0') ^ 1) as i32; + r -= (cs[i] - b'0') as i32; + ans = ans.max(l + r); } - for i in 1..n { - if bs[i] == b'1' { - score += 1; - } - } - res = res.max(score); - for i in 1..n - 1 { - if bs[i] == b'0' { - score += 1; - } else if bs[i] == b'1' { - score -= 1; - } - res = res.max(score); - } - res + ans } } diff --git a/solution/1400-1499/1422.Maximum Score After Splitting a String/Solution.ts b/solution/1400-1499/1422.Maximum Score After Splitting a String/Solution.ts index f8253a8503772..398485704c0c2 100644 --- a/solution/1400-1499/1422.Maximum Score After Splitting a String/Solution.ts +++ b/solution/1400-1499/1422.Maximum Score After Splitting a String/Solution.ts @@ -1,23 +1,16 @@ function maxScore(s: string): number { - const n = s.length; - let res = 0; - let score = 0; - if (s[0] === '0') { - score++; + let [l, r] = [0, 0]; + for (const c of s) { + r += c === '1' ? 1 : 0; } - for (let i = 1; i < n; i++) { - if (s[i] === '1') { - score++; - } - } - res = Math.max(res, score); - for (let i = 1; i < n - 1; i++) { + let ans = 0; + for (let i = 0; i < s.length - 1; ++i) { if (s[i] === '0') { - score++; - } else if (s[i] === '1') { - score--; + ++l; + } else { + --r; } - res = Math.max(res, score); + ans = Math.max(ans, l + r); } - return res; + return ans; } diff --git a/solution/1400-1499/1422.Maximum Score After Splitting a String/Solution2.cpp b/solution/1400-1499/1422.Maximum Score After Splitting a String/Solution2.cpp deleted file mode 100644 index 3109efd6356e9..0000000000000 --- a/solution/1400-1499/1422.Maximum Score After Splitting a String/Solution2.cpp +++ /dev/null @@ -1,14 +0,0 @@ -class Solution { -public: - int maxScore(string s) { - int t = 0; - if (s[0] == '0') ++t; - for (int i = 1; i < s.size(); ++i) t += s[i] == '1'; - int ans = t; - for (int i = 1; i < s.size() - 1; ++i) { - t += s[i] == '0' ? 1 : -1; - ans = max(ans, t); - } - return ans; - } -}; \ No newline at end of file diff --git a/solution/1400-1499/1422.Maximum Score After Splitting a String/Solution2.go b/solution/1400-1499/1422.Maximum Score After Splitting a String/Solution2.go deleted file mode 100644 index 26aad8e48a855..0000000000000 --- a/solution/1400-1499/1422.Maximum Score After Splitting a String/Solution2.go +++ /dev/null @@ -1,22 +0,0 @@ -func maxScore(s string) int { - t := 0 - if s[0] == '0' { - t++ - } - n := len(s) - for i := 1; i < n; i++ { - if s[i] == '1' { - t++ - } - } - ans := t - for i := 1; i < n-1; i++ { - if s[i] == '0' { - t++ - } else { - t-- - } - ans = max(ans, t) - } - return ans -} \ No newline at end of file diff --git a/solution/1400-1499/1422.Maximum Score After Splitting a String/Solution2.java b/solution/1400-1499/1422.Maximum Score After Splitting a String/Solution2.java deleted file mode 100644 index 2af2f65f0d499..0000000000000 --- a/solution/1400-1499/1422.Maximum Score After Splitting a String/Solution2.java +++ /dev/null @@ -1,19 +0,0 @@ -class Solution { - public int maxScore(String s) { - int t = 0; - if (s.charAt(0) == '0') { - t++; - } - for (int i = 1; i < s.length(); ++i) { - if (s.charAt(i) == '1') { - t++; - } - } - int ans = t; - for (int i = 1; i < s.length() - 1; ++i) { - t += s.charAt(i) == '0' ? 1 : -1; - ans = Math.max(ans, t); - } - return ans; - } -} \ No newline at end of file diff --git a/solution/1400-1499/1422.Maximum Score After Splitting a String/Solution2.py b/solution/1400-1499/1422.Maximum Score After Splitting a String/Solution2.py deleted file mode 100644 index 04eb3724a077c..0000000000000 --- a/solution/1400-1499/1422.Maximum Score After Splitting a String/Solution2.py +++ /dev/null @@ -1,7 +0,0 @@ -class Solution: - def maxScore(self, s: str) -> int: - ans = t = (s[0] == '0') + s[1:].count('1') - for i in range(1, len(s) - 1): - t += 1 if s[i] == '0' else -1 - ans = max(ans, t) - return ans