Skip to content

feat: add solutions to lc problem: No.1005 #3842

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
Dec 6, 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
Original file line number Diff line number Diff line change
Expand Up @@ -76,13 +76,13 @@ tags:

我们观察发现,要使得数组的和尽可能大,就应该尽可能地将数组中的最小负数变成正数。

而题目中元素的范围为 $[-100,100]$,因此,我们可以先用哈希表 $cnt$ 统计数组 $nums$ 中每个元素出现的次数。接着从 $-100$ 开始遍历 $x$,如果哈希表中存在 $x$,那么我们取 $m = \min(cnt[x], k)$ 作为元素 $x$ 取反的个数,然后我们将 $cnt[x]$ 减去 $m$,将 $cnt[-x]$ 加上 $m$,并将 $k$ 减去 $m$。如果 $k$ 为 $0$,说明操作已经结束,直接退出循环即可。
而题目中元素的范围为 $[-100,100]$,因此,我们可以先用哈希表 $\textit{cnt}$ 统计数组 $\textit{nums}$ 中每个元素出现的次数。接着从 $-100$ 开始遍历 $x$,如果哈希表中存在 $x$,那么我们取 $m = \min(cnt[x], k)$ 作为元素 $x$ 取反的个数,然后我们将 $\textit{cnt}[x]$ 减去 $m$,将 $\textit{cnt}[-x]$ 加上 $m$,并将 $k$ 减去 $m$。如果 $k$ 为 $0$,说明操作已经结束,直接退出循环即可。

如果 $k$ 仍然为奇数,且 $cnt[0]=0$,那么我们还需要取 $cnt$ 中最小的一个正数 $x$,将 $cnt[x]$ 减去 $1$,将 $cnt[-x]$ 加上 $1$。
如果 $k$ 仍然为奇数,且 $\textit{cnt}[0]=0$,那么我们还需要取 $\textit{cnt}$ 中最小的一个正数 $x$,将 $\textit{cnt}[x]$ 减去 $1$,将 $\textit{cnt}[-x]$ 加上 $1$。

最后,我们遍历哈希表 $cnt$,将 $x$ 与 $cnt[x]$ 相乘的结果累加,即为答案。
最后,我们遍历哈希表 $\textit{cnt}$,将 $x$ 与 $\textit{cnt}[x]$ 相乘的结果累加,即为答案。

时间复杂度 $O(n + M)$,空间复杂度 $O(M)$。其中 $n$ 和 $M$ 分别为数组 $nums$ 的长度和 $nums$ 的数据范围大小。
时间复杂度 $O(n + M)$,空间复杂度 $O(M)$。其中 $n$ 和 $M$ 分别为数组 $\textit{nums}$ 的长度和 $\textit{nums}$ 的数据范围大小。

<!-- tabs:start -->

Expand Down Expand Up @@ -237,11 +237,7 @@ function largestSumAfterKNegations(nums: number[], k: number): number {
}
}
}
let ans = 0;
for (const [key, value] of cnt.entries()) {
ans += key * value;
}
return ans;
return Array.from(cnt.entries()).reduce((acc, [k, v]) => acc + k * v, 0);
}
```

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,17 @@ tags:

<!-- solution:start -->

### Solution 1
### Solution 1: Greedy + Counting

We observe that to maximize the sum of the array, we should try to turn the smallest negative numbers into positive numbers.

Given that the range of elements is $[-100, 100]$, we can use a hash table $\textit{cnt}$ to count the occurrences of each element in the array $\textit{nums}$. Then, starting from $-100$, we iterate through $x$. If $x$ exists in the hash table, we take $m = \min(\textit{cnt}[x], k)$ as the number of times to negate the element $x$. We then subtract $m$ from $\textit{cnt}[x]$, add $m$ to $\textit{cnt}[-x]$, and subtract $m$ from $k$. If $k$ becomes $0$, the operation is complete, and we exit the loop.

If $k$ is still odd and $\textit{cnt}[0] = 0$, we need to take the smallest positive number $x$ in $\textit{cnt}$, subtract $1$ from $\textit{cnt}[x]$, and add $1$ to $\textit{cnt}[-x]$.

Finally, we traverse the hash table $\textit{cnt}$ and sum the products of $x$ and $\textit{cnt}[x]$ to get the answer.

The time complexity is $O(n + M)$, and the space complexity is $O(M)$. Here, $n$ and $M$ are the length of the array $\textit{nums}$ and the size of the data range of $\textit{nums}$, respectively.

<!-- tabs:start -->

Expand Down Expand Up @@ -225,11 +235,7 @@ function largestSumAfterKNegations(nums: number[], k: number): number {
}
}
}
let ans = 0;
for (const [key, value] of cnt.entries()) {
ans += key * value;
}
return ans;
return Array.from(cnt.entries()).reduce((acc, [k, v]) => acc + k * v, 0);
}
```

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,5 @@ function largestSumAfterKNegations(nums: number[], k: number): number {
}
}
}
let ans = 0;
for (const [key, value] of cnt.entries()) {
ans += key * value;
}
return ans;
return Array.from(cnt.entries()).reduce((acc, [k, v]) => acc + k * v, 0);
}
Original file line number Diff line number Diff line change
Expand Up @@ -67,37 +67,39 @@ tags:

<!-- solution:start -->

### 方法一
### 方法一:DFS + 二分查找

我们设计一个函数 $\textit{dfs}(i, j)$,表示构造出从 $\textit{preorder}[i]$ 到 $\textit{preorder}[j]$ 这些节点构成的二叉搜索树。那么答案就是 $\textit{dfs}(0, n - 1)$。

在 $\textit{dfs}(i, j)$ 中,我们首先构造根节点,即 $\textit{preorder}[i]$。然后使用二分查找的方法找到第一个大于 $\textit{preorder}[i]$ 的节点的下标 $\textit{mid}$,将 $\textit{dfs}(i + 1, \textit{mid} - 1)$ 作为根节点的左子树,将 $\textit{dfs}(\textit{mid}, j)$ 作为根节点的右子树。

最后返回根节点即可。

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

<!-- tabs:start -->

#### Python3

```python
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def bstFromPreorder(self, preorder: List[int]) -> Optional[TreeNode]:
def dfs(preorder):
if not preorder:
def dfs(i: int, j: int) -> Optional[TreeNode]:
if i > j:
return None
root = TreeNode(preorder[0])
left, right = 1, len(preorder)
while left < right:
mid = (left + right) >> 1
if preorder[mid] > preorder[0]:
right = mid
root = TreeNode(preorder[i])
l, r = i + 1, j + 1
while l < r:
mid = (l + r) >> 1
if preorder[mid] > preorder[i]:
r = mid
else:
left = mid + 1
root.left = dfs(preorder[1:left])
root.right = dfs(preorder[left:])
l = mid + 1
root.left = dfs(i + 1, l - 1)
root.right = dfs(l, j)
return root

return dfs(preorder)
return dfs(0, len(preorder) - 1)
```

#### Java
Expand All @@ -119,27 +121,29 @@ class Solution:
* }
*/
class Solution {
private int[] preorder;

public TreeNode bstFromPreorder(int[] preorder) {
return dfs(preorder, 0, preorder.length - 1);
this.preorder = preorder;
return dfs(0, preorder.length - 1);
}

private TreeNode dfs(int[] preorder, int i, int j) {
if (i > j || i >= preorder.length) {
private TreeNode dfs(int i, int j) {
if (i > j) {
return null;
}
TreeNode root = new TreeNode(preorder[i]);
int left = i + 1, right = j + 1;
while (left < right) {
int mid = (left + right) >> 1;
int l = i + 1, r = j + 1;
while (l < r) {
int mid = (l + r) >> 1;
if (preorder[mid] > preorder[i]) {
right = mid;
r = mid;
} else {
left = mid + 1;
l = mid + 1;
}
}
root.left = dfs(preorder, i + 1, left - 1);
root.right = dfs(preorder, left, j);
root.left = dfs(i + 1, l - 1);
root.right = dfs(l, j);
return root;
}
}
Expand All @@ -162,23 +166,25 @@ class Solution {
class Solution {
public:
TreeNode* bstFromPreorder(vector<int>& preorder) {
return dfs(preorder, 0, preorder.size() - 1);
}

TreeNode* dfs(vector<int>& preorder, int i, int j) {
if (i > j || i >= preorder.size()) return nullptr;
TreeNode* root = new TreeNode(preorder[i]);
int left = i + 1, right = j + 1;
while (left < right) {
int mid = (left + right) >> 1;
if (preorder[mid] > preorder[i])
right = mid;
else
left = mid + 1;
}
root->left = dfs(preorder, i + 1, left - 1);
root->right = dfs(preorder, left, j);
return root;
auto dfs = [&](auto&& dfs, int i, int j) -> TreeNode* {
if (i > j) {
return nullptr;
}
TreeNode* root = new TreeNode(preorder[i]);
int l = i + 1, r = j + 1;
while (l < r) {
int mid = (l + r) >> 1;
if (preorder[mid] > preorder[i]) {
r = mid;
} else {
l = mid + 1;
}
}
root->left = dfs(dfs, i + 1, l - 1);
root->right = dfs(dfs, l, j);
return root;
};
return dfs(dfs, 0, preorder.size() - 1);
}
};
```
Expand All @@ -197,21 +203,21 @@ public:
func bstFromPreorder(preorder []int) *TreeNode {
var dfs func(i, j int) *TreeNode
dfs = func(i, j int) *TreeNode {
if i > j || i >= len(preorder) {
if i > j {
return nil
}
root := &TreeNode{Val: preorder[i]}
left, right := i+1, len(preorder)
for left < right {
mid := (left + right) >> 1
l, r := i+1, j+1
for l < r {
mid := (l + r) >> 1
if preorder[mid] > preorder[i] {
right = mid
r = mid
} else {
left = mid + 1
l = mid + 1
}
}
root.Left = dfs(i+1, left-1)
root.Right = dfs(left, j)
root.Left = dfs(i+1, l-1)
root.Right = dfs(l, j)
return root
}
return dfs(0, len(preorder)-1)
Expand All @@ -236,24 +242,25 @@ func bstFromPreorder(preorder []int) *TreeNode {
*/

function bstFromPreorder(preorder: number[]): TreeNode | null {
const n = preorder.length;
const next = new Array(n);
const stack = [];
for (let i = n - 1; i >= 0; i--) {
while (stack.length !== 0 && preorder[stack[stack.length - 1]] < preorder[i]) {
stack.pop();
}
next[i] = stack[stack.length - 1] ?? n;
stack.push(i);
}

const dfs = (left: number, right: number) => {
if (left >= right) {
const dfs = (i: number, j: number): TreeNode | null => {
if (i > j) {
return null;
}
return new TreeNode(preorder[left], dfs(left + 1, next[left]), dfs(next[left], right));
const root = new TreeNode(preorder[i]);
let [l, r] = [i + 1, j + 1];
while (l < r) {
const mid = (l + r) >> 1;
if (preorder[mid] > preorder[i]) {
r = mid;
} else {
l = mid + 1;
}
}
root.left = dfs(i + 1, l - 1);
root.right = dfs(l, j);
return root;
};
return dfs(0, n);
return dfs(0, preorder.length - 1);
}
```

Expand Down Expand Up @@ -281,36 +288,29 @@ function bstFromPreorder(preorder: number[]): TreeNode | null {
use std::cell::RefCell;
use std::rc::Rc;
impl Solution {
fn dfs(
preorder: &Vec<i32>,
next: &Vec<usize>,
left: usize,
right: usize,
) -> Option<Rc<RefCell<TreeNode>>> {
if left >= right {
return None;
}
Some(Rc::new(RefCell::new(TreeNode {
val: preorder[left],
left: Self::dfs(preorder, next, left + 1, next[left]),
right: Self::dfs(preorder, next, next[left], right),
})))
}

pub fn bst_from_preorder(preorder: Vec<i32>) -> Option<Rc<RefCell<TreeNode>>> {
let n = preorder.len();
let mut stack = Vec::new();
let mut next = vec![n; n];
for i in (0..n).rev() {
while !stack.is_empty() && preorder[*stack.last().unwrap()] < preorder[i] {
stack.pop();
fn dfs(preorder: &Vec<i32>, i: usize, j: usize) -> Option<Rc<RefCell<TreeNode>>> {
if i > j {
return None;
}
if !stack.is_empty() {
next[i] = *stack.last().unwrap();
let root = Rc::new(RefCell::new(TreeNode::new(preorder[i])));
let mut l = i + 1;
let mut r = j + 1;
while l < r {
let mid = (l + r) >> 1;
if preorder[mid] > preorder[i] {
r = mid;
} else {
l = mid + 1;
}
}
stack.push(i);
let mut root_ref = root.borrow_mut();
root_ref.left = dfs(preorder, i + 1, l - 1);
root_ref.right = dfs(preorder, l, j);
Some(root.clone())
}
Self::dfs(&preorder, &next, 0, n)

dfs(&preorder, 0, preorder.len() - 1)
}
}
```
Expand Down
Loading
Loading