diff --git a/solution/1000-1099/1017.Convert to Base -2/README.md b/solution/1000-1099/1017.Convert to Base -2/README.md index 80e7840923ebd..34edaa39a0857 100644 --- a/solution/1000-1099/1017.Convert to Base -2/README.md +++ b/solution/1000-1099/1017.Convert to Base -2/README.md @@ -171,6 +171,56 @@ function baseNeg2(n: number): string { } ``` +```rust +impl Solution { + pub fn base_neg2(n: i32) -> String { + if n == 0 { + return "0".to_string(); + } + let mut k = 1; + let mut ans = String::new(); + let mut num = n; + while num != 0 { + if num % 2 != 0 { + ans.push('1'); + num -= k; + } else { + ans.push('0'); + } + k *= -1; + num /= 2; + } + ans.chars().rev().collect::() + } +} +``` + +```cs +public class Solution { + public string BaseNeg2(int n) { + if (n == 0) { + return "0"; + } + int k = 1; + StringBuilder ans = new StringBuilder(); + int num = n; + while (num != 0) { + if (num % 2 != 0) { + ans.Append('1'); + num -= k; + } else { + ans.Append('0'); + } + k *= -1; + num /= 2; + } + char[] cs = ans.ToString().ToCharArray(); + Array.Reverse(cs); + return new string(cs); + } +} +``` + diff --git a/solution/1000-1099/1017.Convert to Base -2/README_EN.md b/solution/1000-1099/1017.Convert to Base -2/README_EN.md index f517b3942302b..fbea53f693e20 100644 --- a/solution/1000-1099/1017.Convert to Base -2/README_EN.md +++ b/solution/1000-1099/1017.Convert to Base -2/README_EN.md @@ -157,6 +157,56 @@ function baseNeg2(n: number): string { } ``` +```rust +impl Solution { + pub fn base_neg2(n: i32) -> String { + if n == 0 { + return "0".to_string(); + } + let mut k = 1; + let mut ans = String::new(); + let mut num = n; + while num != 0 { + if num % 2 != 0 { + ans.push('1'); + num -= k; + } else { + ans.push('0'); + } + k *= -1; + num /= 2; + } + ans.chars().rev().collect::() + } +} +``` + +```cs +public class Solution { + public string BaseNeg2(int n) { + if (n == 0) { + return "0"; + } + int k = 1; + StringBuilder ans = new StringBuilder(); + int num = n; + while (num != 0) { + if (num % 2 != 0) { + ans.Append('1'); + num -= k; + } else { + ans.Append('0'); + } + k *= -1; + num /= 2; + } + char[] cs = ans.ToString().ToCharArray(); + Array.Reverse(cs); + return new string(cs); + } +} +``` + diff --git a/solution/1000-1099/1017.Convert to Base -2/Solution.cs b/solution/1000-1099/1017.Convert to Base -2/Solution.cs new file mode 100644 index 0000000000000..dfa280dcf758a --- /dev/null +++ b/solution/1000-1099/1017.Convert to Base -2/Solution.cs @@ -0,0 +1,23 @@ +public class Solution { + public string BaseNeg2(int n) { + if (n == 0) { + return "0"; + } + int k = 1; + StringBuilder ans = new StringBuilder(); + int num = n; + while (num != 0) { + if (num % 2 != 0) { + ans.Append('1'); + num -= k; + } else { + ans.Append('0'); + } + k *= -1; + num /= 2; + } + char[] cs = ans.ToString().ToCharArray(); + Array.Reverse(cs); + return new string(cs); + } +} \ No newline at end of file diff --git a/solution/1000-1099/1017.Convert to Base -2/Solution.rs b/solution/1000-1099/1017.Convert to Base -2/Solution.rs new file mode 100644 index 0000000000000..5aaefcf811a0c --- /dev/null +++ b/solution/1000-1099/1017.Convert to Base -2/Solution.rs @@ -0,0 +1,21 @@ +impl Solution { + pub fn base_neg2(n: i32) -> String { + if n == 0 { + return "0".to_string(); + } + let mut k = 1; + let mut ans = String::new(); + let mut num = n; + while num != 0 { + if num % 2 != 0 { + ans.push('1'); + num -= k; + } else { + ans.push('0'); + } + k *= -1; + num /= 2; + } + ans.chars().rev().collect::() + } +} diff --git a/solution/1000-1099/1019.Next Greater Node In Linked List/README.md b/solution/1000-1099/1019.Next Greater Node In Linked List/README.md index bac4e882cde01..fba6766b0877c 100644 --- a/solution/1000-1099/1019.Next Greater Node In Linked List/README.md +++ b/solution/1000-1099/1019.Next Greater Node In Linked List/README.md @@ -203,12 +203,12 @@ function nextLargerNodes(head: ListNode | null): number[] { } const stk: number[] = []; const n = nums.length; - const ans: number[] = new Array(n).fill(0); + const ans: number[] = Array(n).fill(0); for (let i = n - 1; ~i; --i) { - while (stk.length && stk[stk.length - 1] <= nums[i]) { + while (stk.length && stk.at(-1)! <= nums[i]) { stk.pop(); } - ans[i] = stk.length ? stk[stk.length - 1] : 0; + ans[i] = stk.length ? stk.at(-1)! : 0; stk.push(nums[i]); } return ans; @@ -232,32 +232,29 @@ function nextLargerNodes(head: ListNode | null): number[] { // } // } // } -struct Item { - index: usize, - val: i32, -} - +use std::collections::VecDeque; impl Solution { pub fn next_larger_nodes(head: Option>) -> Vec { - let mut res = Vec::new(); - let mut stack: Vec = Vec::new(); - let mut cur = &head; - for i in 0..usize::MAX { - if cur.is_none() { - break; + let mut nums = Vec::new(); + let mut current = &head; + while let Some(node) = current { + nums.push(node.val); + current = &node.next; + } + + let mut stk = VecDeque::new(); + let n = nums.len(); + let mut ans = vec![0; n]; + for i in (0..n).rev() { + while !stk.is_empty() && stk.back().copied().unwrap() <= nums[i] { + stk.pop_back(); } - res.push(0); - let node = cur.as_ref().unwrap(); - while !stack.is_empty() && stack.last().unwrap().val < node.val { - res[stack.pop().unwrap().index] = node.val; + if let Some(&top) = stk.back() { + ans[i] = top; } - stack.push(Item { - index: i, - val: node.val, - }); - cur = &node.next; + stk.push_back(nums[i]); } - res + ans } } ``` @@ -296,48 +293,4 @@ var nextLargerNodes = function (head) { -### 方法二 - - - -```ts -/** - * Definition for singly-linked list. - * class ListNode { - * val: number - * next: ListNode | null - * constructor(val?: number, next?: ListNode | null) { - * this.val = (val===undefined ? 0 : val) - * this.next = (next===undefined ? null : next) - * } - * } - */ - -interface Item { - index: number; - val: number; -} - -function nextLargerNodes(head: ListNode | null): number[] { - const res: number[] = []; - const stack: Item[] = []; - let cur = head; - for (let i = 0; cur != null; i++) { - res.push(0); - const { val, next } = cur; - while (stack.length !== 0 && stack[stack.length - 1].val < val) { - res[stack.pop().index] = val; - } - stack.push({ - val, - index: i, - }); - cur = next; - } - return res; -} -``` - - - diff --git a/solution/1000-1099/1019.Next Greater Node In Linked List/README_EN.md b/solution/1000-1099/1019.Next Greater Node In Linked List/README_EN.md index 79e99e4ba06eb..355986b7060b9 100644 --- a/solution/1000-1099/1019.Next Greater Node In Linked List/README_EN.md +++ b/solution/1000-1099/1019.Next Greater Node In Linked List/README_EN.md @@ -38,7 +38,17 @@ ## Solutions -### Solution 1 +### Solution 1: Monotonic Stack + +The problem requires finding the next larger node for each node in the linked list, that is, finding the first node to the right of each node in the linked list that is larger than it. We first traverse the linked list and store the values in the linked list in an array $nums$. For each element in the array $nums$, we just need to find the first element to its right that is larger than it. The problem of finding the next larger element can be solved using a monotonic stack. + +We traverse the array $nums$ from back to front, maintaining a stack $stk$ that is monotonically decreasing from the bottom to the top. During the traversal, if the top element of the stack is less than or equal to the current element, we loop to pop the top element of the stack until the top element of the stack is larger than the current element or the stack is empty. + +If the stack is empty at this time, it means that the current element does not have a next larger element, otherwise, the next larger element of the current element is the top element of the stack, and we update the answer array $ans$. Then we push the current element into the stack and continue the traversal. + +After the traversal is over, we return the answer array $ans$. + +The time complexity is $O(n)$, and the space complexity is $O(n)$. Where $n$ is the length of the linked list. @@ -185,12 +195,12 @@ function nextLargerNodes(head: ListNode | null): number[] { } const stk: number[] = []; const n = nums.length; - const ans: number[] = new Array(n).fill(0); + const ans: number[] = Array(n).fill(0); for (let i = n - 1; ~i; --i) { - while (stk.length && stk[stk.length - 1] <= nums[i]) { + while (stk.length && stk.at(-1)! <= nums[i]) { stk.pop(); } - ans[i] = stk.length ? stk[stk.length - 1] : 0; + ans[i] = stk.length ? stk.at(-1)! : 0; stk.push(nums[i]); } return ans; @@ -214,32 +224,29 @@ function nextLargerNodes(head: ListNode | null): number[] { // } // } // } -struct Item { - index: usize, - val: i32, -} - +use std::collections::VecDeque; impl Solution { pub fn next_larger_nodes(head: Option>) -> Vec { - let mut res = Vec::new(); - let mut stack: Vec = Vec::new(); - let mut cur = &head; - for i in 0..usize::MAX { - if cur.is_none() { - break; + let mut nums = Vec::new(); + let mut current = &head; + while let Some(node) = current { + nums.push(node.val); + current = &node.next; + } + + let mut stk = VecDeque::new(); + let n = nums.len(); + let mut ans = vec![0; n]; + for i in (0..n).rev() { + while !stk.is_empty() && stk.back().copied().unwrap() <= nums[i] { + stk.pop_back(); } - res.push(0); - let node = cur.as_ref().unwrap(); - while !stack.is_empty() && stack.last().unwrap().val < node.val { - res[stack.pop().unwrap().index] = node.val; + if let Some(&top) = stk.back() { + ans[i] = top; } - stack.push(Item { - index: i, - val: node.val, - }); - cur = &node.next; + stk.push_back(nums[i]); } - res + ans } } ``` @@ -278,48 +285,4 @@ var nextLargerNodes = function (head) { -### Solution 2 - - - -```ts -/** - * Definition for singly-linked list. - * class ListNode { - * val: number - * next: ListNode | null - * constructor(val?: number, next?: ListNode | null) { - * this.val = (val===undefined ? 0 : val) - * this.next = (next===undefined ? null : next) - * } - * } - */ - -interface Item { - index: number; - val: number; -} - -function nextLargerNodes(head: ListNode | null): number[] { - const res: number[] = []; - const stack: Item[] = []; - let cur = head; - for (let i = 0; cur != null; i++) { - res.push(0); - const { val, next } = cur; - while (stack.length !== 0 && stack[stack.length - 1].val < val) { - res[stack.pop().index] = val; - } - stack.push({ - val, - index: i, - }); - cur = next; - } - return res; -} -``` - - - diff --git a/solution/1000-1099/1019.Next Greater Node In Linked List/Solution.rs b/solution/1000-1099/1019.Next Greater Node In Linked List/Solution.rs index 77e8687ae0396..0427d20dd18c4 100644 --- a/solution/1000-1099/1019.Next Greater Node In Linked List/Solution.rs +++ b/solution/1000-1099/1019.Next Greater Node In Linked List/Solution.rs @@ -14,31 +14,28 @@ // } // } // } -struct Item { - index: usize, - val: i32, -} - +use std::collections::VecDeque; impl Solution { pub fn next_larger_nodes(head: Option>) -> Vec { - let mut res = Vec::new(); - let mut stack: Vec = Vec::new(); - let mut cur = &head; - for i in 0..usize::MAX { - if cur.is_none() { - break; + let mut nums = Vec::new(); + let mut current = &head; + while let Some(node) = current { + nums.push(node.val); + current = &node.next; + } + + let mut stk = VecDeque::new(); + let n = nums.len(); + let mut ans = vec![0; n]; + for i in (0..n).rev() { + while !stk.is_empty() && stk.back().copied().unwrap() <= nums[i] { + stk.pop_back(); } - res.push(0); - let node = cur.as_ref().unwrap(); - while !stack.is_empty() && stack.last().unwrap().val < node.val { - res[stack.pop().unwrap().index] = node.val; + if let Some(&top) = stk.back() { + ans[i] = top; } - stack.push(Item { - index: i, - val: node.val, - }); - cur = &node.next; + stk.push_back(nums[i]); } - res + ans } } diff --git a/solution/1000-1099/1019.Next Greater Node In Linked List/Solution.ts b/solution/1000-1099/1019.Next Greater Node In Linked List/Solution.ts index e8ba26a08eae6..5f06c7fbe5912 100644 --- a/solution/1000-1099/1019.Next Greater Node In Linked List/Solution.ts +++ b/solution/1000-1099/1019.Next Greater Node In Linked List/Solution.ts @@ -18,12 +18,12 @@ function nextLargerNodes(head: ListNode | null): number[] { } const stk: number[] = []; const n = nums.length; - const ans: number[] = new Array(n).fill(0); + const ans: number[] = Array(n).fill(0); for (let i = n - 1; ~i; --i) { - while (stk.length && stk[stk.length - 1] <= nums[i]) { + while (stk.length && stk.at(-1)! <= nums[i]) { stk.pop(); } - ans[i] = stk.length ? stk[stk.length - 1] : 0; + ans[i] = stk.length ? stk.at(-1)! : 0; stk.push(nums[i]); } return ans; diff --git a/solution/1000-1099/1019.Next Greater Node In Linked List/Solution2.ts b/solution/1000-1099/1019.Next Greater Node In Linked List/Solution2.ts deleted file mode 100644 index 0cb92b03aa9f7..0000000000000 --- a/solution/1000-1099/1019.Next Greater Node In Linked List/Solution2.ts +++ /dev/null @@ -1,35 +0,0 @@ -/** - * Definition for singly-linked list. - * class ListNode { - * val: number - * next: ListNode | null - * constructor(val?: number, next?: ListNode | null) { - * this.val = (val===undefined ? 0 : val) - * this.next = (next===undefined ? null : next) - * } - * } - */ - -interface Item { - index: number; - val: number; -} - -function nextLargerNodes(head: ListNode | null): number[] { - const res: number[] = []; - const stack: Item[] = []; - let cur = head; - for (let i = 0; cur != null; i++) { - res.push(0); - const { val, next } = cur; - while (stack.length !== 0 && stack[stack.length - 1].val < val) { - res[stack.pop().index] = val; - } - stack.push({ - val, - index: i, - }); - cur = next; - } - return res; -} diff --git a/solution/1000-1099/1022.Sum of Root To Leaf Binary Numbers/README.md b/solution/1000-1099/1022.Sum of Root To Leaf Binary Numbers/README.md index 391d2564ba8e1..9b40d7a067249 100644 --- a/solution/1000-1099/1022.Sum of Root To Leaf Binary Numbers/README.md +++ b/solution/1000-1099/1022.Sum of Root To Leaf Binary Numbers/README.md @@ -48,7 +48,7 @@ ### 方法一:递归 -我们设计递归函数 `dfs(root, t)`,它接收两个参数:当前节点 `root` 和当前节点的父节点对应的二进制数 `t`。函数的返回值是从当前节点到叶子节点的路径所表示的二进制数之和。答案即为 `dfs(root, 0)`。 +我们设计一个递归函数 `dfs(root, t)`,它接收两个参数:当前节点 `root` 和当前节点的父节点对应的二进制数 `t`。函数的返回值是从当前节点到叶子节点的路径所表示的二进制数之和。答案即为 `dfs(root, 0)`。 递归函数的逻辑如下: diff --git a/solution/1000-1099/1022.Sum of Root To Leaf Binary Numbers/README_EN.md b/solution/1000-1099/1022.Sum of Root To Leaf Binary Numbers/README_EN.md index b99a23f77aa3e..2b3d4ad57c445 100644 --- a/solution/1000-1099/1022.Sum of Root To Leaf Binary Numbers/README_EN.md +++ b/solution/1000-1099/1022.Sum of Root To Leaf Binary Numbers/README_EN.md @@ -42,7 +42,16 @@ ## Solutions -### Solution 1 +### Solution 1: Recursion + +We design a recursive function `dfs(root, t)`, which takes two parameters: the current node `root` and the binary number corresponding to the parent node `t`. The return value of the function is the sum of the binary numbers represented by the path from the current node to the leaf node. The answer is `dfs(root, 0)`. + +The logic of the recursive function is as follows: + +- If the current node `root` is null, then return `0`. Otherwise, calculate the binary number `t` corresponding to the current node, i.e., `t = t << 1 | root.val`. +- If the current node is a leaf node, then return `t`. Otherwise, return the sum of `dfs(root.left, t)` and `dfs(root.right, t)`. + +The time complexity is $O(n)$, and the space complexity is $O(n)$. Where $n$ is the number of nodes in the binary tree. Each node is visited once; the recursion stack requires $O(n)$ space. diff --git a/solution/1000-1099/1024.Video Stitching/README_EN.md b/solution/1000-1099/1024.Video Stitching/README_EN.md index 4027af3ab9a90..00d9f17ee65ed 100644 --- a/solution/1000-1099/1024.Video Stitching/README_EN.md +++ b/solution/1000-1099/1024.Video Stitching/README_EN.md @@ -57,7 +57,27 @@ Now we have segments [0,2] + [2,8] + [8,10] which cover the sporting event [0, 1 ## Solutions -### Solution 1 +### Solution 1: Greedy + +Note that if there are multiple sub-intervals with the same starting point, it is optimal to choose the one with the largest right endpoint. + +Therefore, we can preprocess all sub-intervals. For each position $i$, calculate the largest right endpoint among all sub-intervals starting at $i$, and record it in the array $last[i]$. + +We define a variable `mx` to represent the farthest position that can currently be reached, a variable `ans` to represent the current minimum number of sub-intervals needed, and a variable `pre` to represent the right endpoint of the last used sub-interval. + +Next, we start enumerating all positions $i$ from $0$, using $last[i]$ to update `mx`. If after updating, $mx = i$, it means that the next position cannot be covered, so the task cannot be completed, return $-1$. + +At the same time, we record the right endpoint `pre` of the last used sub-interval. If $pre = i$, it means that a new sub-interval needs to be used, so we add $1$ to `ans` and update `pre` to `mx`. + +After the traversal is over, return `ans`. + +The time complexity is $O(n+m)$, and the space complexity is $O(m)$. Where $n$ and $m$ are the lengths of the `clips` array and the value of `time`, respectively. + +Similar problems: + +- [45. Jump Game II](https://github.com/doocs/leetcode/blob/main/solution/0000-0099/0045.Jump%20Game%20II/README_EN.md) +- [55. Jump Game](https://github.com/doocs/leetcode/blob/main/solution/0000-0099/0055.Jump%20Game/README_EN.md) +- [1326. Minimum Number of Taps to Open to Water a Garden](https://github.com/doocs/leetcode/blob/main/solution/1300-1399/1326.Minimum%20Number%20of%20Taps%20to%20Open%20to%20Water%20a%20Garden/README_EN.md) diff --git a/solution/1000-1099/1025.Divisor Game/README_EN.md b/solution/1000-1099/1025.Divisor Game/README_EN.md index 536977adb5fa1..0ea9d96ab1af3 100644 --- a/solution/1000-1099/1025.Divisor Game/README_EN.md +++ b/solution/1000-1099/1025.Divisor Game/README_EN.md @@ -45,7 +45,26 @@ ## Solutions -### Solution 1 +### Solution 1: Mathematical Induction + +- When $n=1$, the first player loses. +- When $n=2$, the first player takes $1$, leaving $1$, the second player loses, the first player wins. +- When $n=3$, the first player takes $1$, leaving $2$, the second player wins, the first player loses. +- When $n=4$, the first player takes $1$, leaving $3$, the second player loses, the first player wins. +- ... + +We conjecture that when $n$ is odd, the first player loses; when $n$ is even, the first player wins. + +Proof: + +1. If $n=1$ or $n=2$, the conclusion holds. +1. If $n \gt 2$, assume that the conclusion holds when $n \le k$, then when $n=k+1$: + - If $k+1$ is odd, since $x$ is a divisor of $k+1$, then $x$ can only be odd, so $k+1-x$ is even, the second player wins, the first player loses. + - If $k+1$ is even, now $x$ can be either odd $1$ or even. If $x$ is odd, then $k+1-x$ is odd, the second player loses, the first player wins. + +In conclusion, when $n$ is odd, the first player loses; when $n$ is even, the first player wins. The conclusion is correct. + +The time complexity is $O(1)$, and the space complexity is $O(1)$. diff --git a/solution/1000-1099/1027.Longest Arithmetic Subsequence/README_EN.md b/solution/1000-1099/1027.Longest Arithmetic Subsequence/README_EN.md index f2736bfa12a85..bb13e0acf8635 100644 --- a/solution/1000-1099/1027.Longest Arithmetic Subsequence/README_EN.md +++ b/solution/1000-1099/1027.Longest Arithmetic Subsequence/README_EN.md @@ -50,7 +50,19 @@ ## Solutions -### Solution 1 +### Solution 1: Dynamic Programming + +We define $f[i][j]$ as the maximum length of the arithmetic sequence ending with $nums[i]$ and having a common difference of $j$. Initially, $f[i][j]=1$, that is, each element itself is an arithmetic sequence of length $1$. + +> Since the common difference may be negative, and the maximum difference is $500$, we can uniformly add $500$ to the common difference, so the range of the common difference becomes $[0, 1000]$. + +Considering $f[i]$, we can enumerate the previous element $nums[k]$ of $nums[i]$, then the common difference $j=nums[i]-nums[k]+500$, at this time $f[i][j]=\max(f[i][j], f[k][j]+1)$, then we update the answer $ans=\max(ans, f[i][j])$. + +Finally, return the answer. + +> If initially $f[i][j]=0$, then we need to add $1$ to the answer when returning the answer. + +The time complexity is $O(n \times (d + n))$, and the space complexity is $O(n \times d)$. Where $n$ and $d$ are the length of the array $nums$ and the difference between the maximum and minimum values in the array $nums$, respectively.