-
Notifications
You must be signed in to change notification settings - Fork 956
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
2c4cf20
commit 0033019
Showing
3 changed files
with
266 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
### 题目描述 | ||
|
||
这是 LeetCode 上的 **[2656. K 个元素的最大和](https://leetcode.cn/problems/maximum-sum-with-exactly-k-elements/solutions/2527384/gong-shui-san-xie-deng-chai-shu-lie-qiu-b2g88/)** ,难度为 **简单**。 | ||
|
||
Tag : 「数学」 | ||
|
||
|
||
|
||
给你一个下标从 `0` 开始的整数数组 `nums` 和一个整数 `k` 。 | ||
|
||
你需要执行以下操作恰好 `k` 次,最大化你的得分: | ||
|
||
1. 从 `nums` 中选择一个元素 `m` 。 | ||
2. 将选中的元素 `m` 从数组中删除。 | ||
3. 将新元素 `m + 1` 添加到数组中。 | ||
4. 你的得分增加 `m` 。 | ||
|
||
请你返回执行以上操作恰好 `k` 次后的最大得分。 | ||
|
||
示例 1: | ||
``` | ||
输入:nums = [1,2,3,4,5], k = 3 | ||
输出:18 | ||
解释:我们需要从 nums 中恰好选择 3 个元素并最大化得分。 | ||
第一次选择 5 。和为 5 ,nums = [1,2,3,4,6] 。 | ||
第二次选择 6 。和为 6 ,nums = [1,2,3,4,7] 。 | ||
第三次选择 7 。和为 5 + 6 + 7 = 18 ,nums = [1,2,3,4,8] 。 | ||
所以我们返回 18 。 | ||
18 是可以得到的最大答案。 | ||
``` | ||
示例 2: | ||
``` | ||
输入:nums = [5,5,5], k = 2 | ||
输出:11 | ||
解释:我们需要从 nums 中恰好选择 2 个元素并最大化得分。 | ||
第一次选择 5 。和为 5 ,nums = [5,5,6] 。 | ||
第二次选择 6 。和为 6 ,nums = [5,5,7] 。 | ||
所以我们返回 11 。 | ||
11 是可以得到的最大答案。 | ||
``` | ||
|
||
提示: | ||
* $1 <= nums.length <= 100$ | ||
* $1 <= nums[i] <= 100$ | ||
* $1 <= k <= 100$ | ||
|
||
--- | ||
|
||
### 数学 | ||
|
||
为了使得分最高,每次应从 `nums` 中选最大值,选完后重放仍为最大值。 | ||
|
||
假设原始 `nums` 中的最大值为 `max`,那么问题转换为「等差数列」求和:首项为 `max`,末项为 `max + k - 1`,项数为 $k$,公差为 $1$。 | ||
|
||
Java 代码: | ||
```Java | ||
class Solution { | ||
public int maximizeSum(int[] nums, int k) { | ||
int max = 0; | ||
for (int x : nums) max = Math.max(max, x); | ||
return k * (max + max + k - 1) / 2; | ||
} | ||
} | ||
``` | ||
C++ 代码: | ||
```C++ | ||
class Solution { | ||
public: | ||
int maximizeSum(vector<int>& nums, int k) { | ||
int maxv = 0; | ||
for (auto x : nums) maxv = max(maxv, x); | ||
return k * (maxv + maxv + k - 1) / 2; | ||
} | ||
}; | ||
``` | ||
Python 代码: | ||
```Python | ||
class Solution: | ||
def maximizeSum(self, nums: List[int], k: int) -> int: | ||
return k * (2 * max(nums) + k - 1) // 2 | ||
``` | ||
TypeScript 代码: | ||
```TypeScript | ||
function maximizeSum(nums: number[], k: number): number { | ||
let max = 0; | ||
for (const x of nums) max = Math.max(max, x); | ||
return k * (max + max + k - 1) / 2; | ||
}; | ||
``` | ||
* 时间复杂度:$O(n)$ | ||
* 空间复杂度:$O(1)$ | ||
|
||
--- | ||
|
||
### 最后 | ||
|
||
这是我们「刷穿 LeetCode」系列文章的第 `No.2656` 篇,系列开始于 2021/01/01,截止于起始日 LeetCode 上共有 1916 道题目,部分是有锁题,我们将先把所有不带锁的题目刷完。 | ||
|
||
在这个系列文章里面,除了讲解解题思路以外,还会尽可能给出最为简洁的代码。如果涉及通解还会相应的代码模板。 | ||
|
||
为了方便各位同学能够电脑上进行调试和提交代码,我建立了相关的仓库:https://github.com/SharingSource/LogicStack-LeetCode 。 | ||
|
||
在仓库地址里,你可以看到系列文章的题解链接、系列文章的相应代码、LeetCode 原题链接和其他优选题解。 | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,157 @@ | ||
### 题目描述 | ||
|
||
这是 LeetCode 上的 **[2698. 求一个整数的惩罚数]()** ,难度为 **简单**。 | ||
|
||
Tag : 「双指针」 | ||
|
||
|
||
|
||
给你一个下标从 $0$ 开始的整数数组 `nums` 和一个整数 `threshold`。 | ||
|
||
请你从 `nums` 的子数组中找出以下标 `l` 开头、下标 `r` 结尾 ($0 <= l <= r < nums.length$) 且满足以下条件的 最长子数组 : | ||
|
||
* `nums[l] % 2 == 0` | ||
* 对于范围 $[l, r - 1]$ 内的所有下标 `i`,`nums[i] % 2 != nums[i + 1] % 2` | ||
* 对于范围 $[l, r]$ 内的所有下标 `i`,`nums[i] <= threshold` | ||
|
||
以整数形式返回满足题目要求的最长子数组的长度。 | ||
|
||
注意:子数组 是数组中的一个连续非空元素序列。 | ||
|
||
示例 1: | ||
``` | ||
输入:nums = [3,2,5,4], threshold = 5 | ||
输出:3 | ||
解释:在这个示例中,我们选择从 l = 1 开始、到 r = 3 结束的子数组 => [2,5,4] ,满足上述条件。 | ||
因此,答案就是这个子数组的长度 3 。可以证明 3 是满足题目要求的最大长度。 | ||
``` | ||
示例 2: | ||
``` | ||
输入:nums = [1,2], threshold = 2 | ||
输出:1 | ||
解释: | ||
在这个示例中,我们选择从 l = 1 开始、到 r = 1 结束的子数组 => [2] 。 | ||
该子数组满足上述全部条件。可以证明 1 是满足题目要求的最大长度。 | ||
``` | ||
示例 3: | ||
``` | ||
输入:nums = [2,3,4,5], threshold = 4 | ||
输出:3 | ||
解释: | ||
在这个示例中,我们选择从 l = 0 开始、到 r = 2 结束的子数组 => [2,3,4] 。 | ||
该子数组满足上述全部条件。 | ||
因此,答案就是这个子数组的长度 3 。可以证明 3 是满足题目要求的最大长度。 | ||
``` | ||
|
||
提示: | ||
* $1 <= nums.length <= 100$ | ||
* $1 <= nums[i] <= 100$ | ||
* $1 <= threshold <= 100$ | ||
|
||
--- | ||
|
||
### 双指针 | ||
|
||
整体题意:求 `nums` 中的最长的子数组 $[l, r]$,对于任意 $nums[i]$ 不超过 `threshold`,且从 $nums[l]$ 开始按照「先偶后奇」顺序交替。 | ||
|
||
容易想到「双指针」做法: | ||
|
||
* 变量 `i` 作为当前子数组左端点,从前往后扫描 `nums`,首先确保 `i` 的合法性(跳过不满足 `nums[i] % 2 = 0` 和 `nums[i] <= threshold` 的位置);随后在固定左端点 `i` 前提下,找最远的右端点 `j`(值不超过 `threshold`,且奇偶性与前值交替) | ||
* 得到当前连续段长度,更新 `ans`,从当前结束位置开始,重复上述过程,直到处理完 `nums` | ||
|
||
Java 代码 | ||
|
||
```Java | ||
class Solution { | ||
public int longestAlternatingSubarray(int[] nums, int threshold) { | ||
int n = nums.length, ans = 0, i = 0; | ||
while (i < n) { | ||
if ((nums[i] % 2 != 0 || nums[i] > threshold) && ++i >= 0) continue; | ||
int j = i + 1, cur = nums[i] % 2; | ||
while (j < n) { | ||
if (nums[j] > threshold || nums[j] % 2 == cur) break; | ||
cur = nums[j] % 2; j++; | ||
} | ||
ans = Math.max(ans, j - i); | ||
i = j; | ||
} | ||
return ans; | ||
} | ||
} | ||
``` | ||
C++ 代码 | ||
```C++ | ||
class Solution { | ||
public: | ||
int longestAlternatingSubarray(vector<int>& nums, int threshold) { | ||
int n = nums.size(), ans = 0, i = 0; | ||
while (i < n) { | ||
if ((nums[i] % 2 != 0 || nums[i] > threshold) && ++i >= 0) continue; | ||
int j = i + 1, cur = nums[i] % 2; | ||
while (j < n) { | ||
if (nums[j] > threshold || nums[j] % 2 == cur) break; | ||
cur = nums[j] % 2; j++; | ||
} | ||
ans = max(ans, j - i); | ||
i = j; | ||
} | ||
return ans; | ||
} | ||
}; | ||
|
||
``` | ||
Python 代码 | ||
```Python | ||
class Solution: | ||
def longestAlternatingSubarray(self, nums: List[int], threshold: int) -> int: | ||
n, ans, i = len(nums), 0, 0 | ||
while i < n: | ||
if nums[i] % 2 != 0 or nums[i] > threshold: | ||
i += 1 | ||
continue | ||
j, cur = i + 1, nums[i] % 2 | ||
while j < n: | ||
if nums[j] > threshold or nums[j] % 2 == cur: break | ||
cur, j = nums[j] % 2, j + 1 | ||
ans = max(ans, j - i) | ||
i = j | ||
return ans | ||
``` | ||
TypeScript 代码 | ||
```TypeScript | ||
function longestAlternatingSubarray(nums: number[], threshold: number): number { | ||
let n = nums.length, ans = 0, i = 0 | ||
while (i < n) { | ||
if ((nums[i] % 2 != 0 || nums[i] > threshold) && ++i >= 0) continue; | ||
let j = i + 1, cur = nums[i] % 2; | ||
while (j < n) { | ||
if (nums[j] > threshold || nums[j] % 2 == cur) break; | ||
cur = nums[j] % 2; j++; | ||
} | ||
ans = Math.max(ans, j - i); | ||
i = j; | ||
} | ||
return ans; | ||
}; | ||
``` | ||
* 时间复杂度:$O(n)$ | ||
* 空间复杂度:$O(1)$ | ||
|
||
--- | ||
|
||
### 最后 | ||
|
||
这是我们「刷穿 LeetCode」系列文章的第 `No.2760` 篇,系列开始于 2021/01/01,截止于起始日 LeetCode 上共有 1916 道题目,部分是有锁题,我们将先把所有不带锁的题目刷完。 | ||
|
||
在这个系列文章里面,除了讲解解题思路以外,还会尽可能给出最为简洁的代码。如果涉及通解还会相应的代码模板。 | ||
|
||
为了方便各位同学能够电脑上进行调试和提交代码,我建立了相关的仓库:https://github.com/SharingSource/LogicStack-LeetCode 。 | ||
|
||
在仓库地址里,你可以看到系列文章的题解链接、系列文章的相应代码、LeetCode 原题链接和其他优选题解。 | ||
|