|
| 1 | +--- |
| 2 | +title: 2210.统计数组中峰和谷的数量:一次遍历(记录上一个不同的数) |
| 3 | +date: 2025-07-28 22:28:53 |
| 4 | +tags: [题解, LeetCode, 简单, 数组, 遍历, 模拟] |
| 5 | +categories: [题解, LeetCode] |
| 6 | +--- |
| 7 | + |
| 8 | +# 【LetMeFly】2210.统计数组中峰和谷的数量:一次遍历(记录上一个不同的数) |
| 9 | + |
| 10 | +力扣题目链接:[https://leetcode.cn/problems/count-hills-and-valleys-in-an-array/](https://leetcode.cn/problems/count-hills-and-valleys-in-an-array/) |
| 11 | + |
| 12 | +<p>给你一个下标从 <strong>0</strong> 开始的整数数组 <code>nums</code> 。如果两侧距 <code>i</code> 最近的不相等邻居的值均小于 <code>nums[i]</code> ,则下标 <code>i</code> 是 <code>nums</code> 中,某个峰的一部分。类似地,如果两侧距 <code>i</code> 最近的不相等邻居的值均大于 <code>nums[i]</code> ,则下标 <code>i</code> 是 <code>nums</code> 中某个谷的一部分。对于相邻下标 <code>i</code> 和 <code>j</code> ,如果 <code>nums[i] == nums[j]</code> , 则认为这两下标属于 <strong>同一个</strong> 峰或谷。</p> |
| 13 | + |
| 14 | +<p>注意,要使某个下标所在峰或谷的一部分,那么它左右两侧必须 <strong>都</strong> 存在不相等邻居。</p> |
| 15 | + |
| 16 | +<p>返回 <code>nums</code> 中峰和谷的数量。</p> |
| 17 | + |
| 18 | +<p> </p> |
| 19 | + |
| 20 | +<p><strong>示例 1:</strong></p> |
| 21 | + |
| 22 | +<pre> |
| 23 | +<strong>输入:</strong>nums = [2,4,1,1,6,5] |
| 24 | +<strong>输出:</strong>3 |
| 25 | +<strong>解释:</strong> |
| 26 | +在下标 0 :由于 2 的左侧不存在不相等邻居,所以下标 0 既不是峰也不是谷。 |
| 27 | +在下标 1 :4 的最近不相等邻居是 2 和 1 。由于 4 > 2 且 4 > 1 ,下标 1 是一个峰。 |
| 28 | +在下标 2 :1 的最近不相等邻居是 4 和 6 。由于 1 < 4 且 1 < 6 ,下标 2 是一个谷。 |
| 29 | +在下标 3 :1 的最近不相等邻居是 4 和 6 。由于 1 < 4 且 1 < 6 ,下标 3 符合谷的定义,但需要注意它和下标 2 是同一个谷的一部分。 |
| 30 | +在下标 4 :6 的最近不相等邻居是 1 和 5 。由于 6 > 1 且 6 > 5 ,下标 4 是一个峰。 |
| 31 | +在下标 5 :由于 5 的右侧不存在不相等邻居,所以下标 5 既不是峰也不是谷。 |
| 32 | +共有 3 个峰和谷,所以返回 3 。</pre> |
| 33 | + |
| 34 | +<p><strong>示例 2:</strong></p> |
| 35 | + |
| 36 | +<pre> |
| 37 | +<strong>输入:</strong>nums = [6,6,5,5,4,1] |
| 38 | +<strong>输出:</strong>0 |
| 39 | +<strong>解释:</strong> |
| 40 | +在下标 0 :由于 6 的左侧不存在不相等邻居,所以下标 0 既不是峰也不是谷。 |
| 41 | +在下标 1 :由于 6 的左侧不存在不相等邻居,所以下标 1 既不是峰也不是谷。 |
| 42 | +在下标 2 :5 的最近不相等邻居是 6 和 4 。由于 5 < 6 且 5 > 4 ,下标 2 既不是峰也不是谷。 |
| 43 | +在下标 3 :5 的最近不相等邻居是 6 和 4 。由于 5 < 6 且 5 > 4 ,下标 3 既不是峰也不是谷。 |
| 44 | +在下标 4 :4 的最近不相等邻居是 5 和 1 。由于 4 < 5 且 4 > 1 ,下标 4 既不是峰也不是谷。 |
| 45 | +在下标 5 :由于 1 的右侧不存在不相等邻居,所以下标 5 既不是峰也不是谷。 |
| 46 | +共有 0 个峰和谷,所以返回 0 。 |
| 47 | +</pre> |
| 48 | + |
| 49 | +<p> </p> |
| 50 | + |
| 51 | +<p><strong>提示:</strong></p> |
| 52 | + |
| 53 | +<ul> |
| 54 | + <li><code>3 <= nums.length <= 100</code></li> |
| 55 | + <li><code>1 <= nums[i] <= 100</code></li> |
| 56 | +</ul> |
| 57 | + |
| 58 | + |
| 59 | + |
| 60 | +## 解题方法:一次遍历 |
| 61 | + |
| 62 | +使用last记录上一个和当前元素不相同的元素,从第一个元素到倒数第二个元素遍历nums数组,如果当前元素比last和下一个元素都大或都小,则答案数量加一。如果当前元素和下一个元素不相同,则更新last为当前元素。 |
| 63 | + |
| 64 | +特别的,我们可以将last的初始值设置为nums[0],这样当nums[1]和nums[0]相等时,last的值其实和含义“上一个不同元素”不匹配,但并不影响结果的判断。 |
| 65 | + |
| 66 | ++ 时间复杂度$O(len(nums))$ |
| 67 | ++ 空间复杂度$O(1)$ |
| 68 | + |
| 69 | +### AC代码 |
| 70 | + |
| 71 | +#### C++ |
| 72 | + |
| 73 | +```cpp |
| 74 | +/* |
| 75 | + * @Author: LetMeFly |
| 76 | + * @Date: 2025-07-28 21:39:52 |
| 77 | + * @LastEditors: LetMeFly.xyz |
| 78 | + * @LastEditTime: 2025-07-28 21:45:22 |
| 79 | + */ |
| 80 | +#if defined(_WIN32) || defined(__APPLE__) |
| 81 | +#include "_[1,2]toVector.h" |
| 82 | +#endif |
| 83 | + |
| 84 | +class Solution { |
| 85 | +public: |
| 86 | + int countHillValley(vector<int>& nums) { |
| 87 | + int ans = 0; |
| 88 | + int last = nums[0]; |
| 89 | + for (int i = 1; i < nums.size() - 1; i++) { |
| 90 | + if (nums[i] > last && nums[i] > nums[i + 1]) { |
| 91 | + ans++; |
| 92 | + } else if (nums[i] < last && nums[i] < nums[i + 1]) { |
| 93 | + ans++; |
| 94 | + } |
| 95 | + if (nums[i] != nums[i + 1]) { |
| 96 | + last = nums[i]; |
| 97 | + } |
| 98 | + } |
| 99 | + return ans; |
| 100 | + } |
| 101 | +}; |
| 102 | +``` |
| 103 | +
|
| 104 | +贴一个[来自扣友](https://leetcode.cn/problems/count-hills-and-valleys-in-an-array/solutions/1374467/tong-ji-shu-zu-zhong-feng-he-gu-de-shu-l-ca7e/comments/3085283/)的C++20高级写法: |
| 105 | +
|
| 106 | +```cpp |
| 107 | +#include <ranges> |
| 108 | +class Solution { |
| 109 | +public: |
| 110 | + int countHillValley(vector<int>& nums) { |
| 111 | + return ranges::count(nums |
| 112 | + | views::chunk_by(equal_to{}) |
| 113 | + | views::transform(ranges::begin) |
| 114 | + | views::adjacent_transform<3>([](auto a, auto b, auto c) { return (*a <=> *b) == (*c <=> *b); }) |
| 115 | + , true); |
| 116 | + } |
| 117 | +}; |
| 118 | +``` |
| 119 | + |
| 120 | +#### Python |
| 121 | + |
| 122 | +```python |
| 123 | +''' |
| 124 | +Author: LetMeFly |
| 125 | +Date: 2025-07-28 21:39:52 |
| 126 | +LastEditors: LetMeFly.xyz |
| 127 | +LastEditTime: 2025-07-28 22:23:33 |
| 128 | +''' |
| 129 | +from typing import List |
| 130 | + |
| 131 | +class Solution: |
| 132 | + def countHillValley(self, nums: List[int]) -> int: |
| 133 | + last = nums[0] |
| 134 | + ans = 0 |
| 135 | + # for i, t in enumerate(nums[1:-1]): # 不可!这样i=0时t=nums[1] |
| 136 | + for i in range(1, len(nums) - 1): |
| 137 | + ans += nums[i] > last and nums[i] > nums[i + 1] or nums[i] < last and nums[i] < nums[i + 1] |
| 138 | + if nums[i] != nums[i + 1]: |
| 139 | + last = nums[i] |
| 140 | + return ans |
| 141 | +``` |
| 142 | + |
| 143 | +#### Java |
| 144 | + |
| 145 | +```java |
| 146 | +/* |
| 147 | + * @Author: LetMeFly |
| 148 | + * @Date: 2025-07-28 21:39:52 |
| 149 | + * @LastEditors: LetMeFly.xyz |
| 150 | + * @LastEditTime: 2025-07-28 22:25:46 |
| 151 | + */ |
| 152 | +class Solution { |
| 153 | + public int countHillValley(int[] nums) { |
| 154 | + int last = nums[0]; |
| 155 | + int ans = 0; |
| 156 | + for (int i = 1; i < nums.length - 1; i++) { |
| 157 | + if (nums[i] > last && nums[i] > nums[i + 1] || nums[i] < last && nums[i] < nums[i + 1]) { |
| 158 | + ans++; |
| 159 | + } |
| 160 | + if (nums[i] != nums[i + 1]) { |
| 161 | + last = nums[i]; |
| 162 | + } |
| 163 | + } |
| 164 | + return ans; |
| 165 | + } |
| 166 | +} |
| 167 | +``` |
| 168 | + |
| 169 | +#### Go |
| 170 | + |
| 171 | +```go |
| 172 | +/* |
| 173 | + * @Author: LetMeFly |
| 174 | + * @Date: 2025-07-28 21:39:52 |
| 175 | + * @LastEditors: LetMeFly.xyz |
| 176 | + * @LastEditTime: 2025-07-28 22:27:50 |
| 177 | + */ |
| 178 | +package main |
| 179 | + |
| 180 | +func countHillValley(nums []int) (ans int) { |
| 181 | + last := nums[0] |
| 182 | + for i := 1; i < len(nums) - 1; i++ { |
| 183 | + if nums[i] > last && nums[i] > nums[i + 1] || nums[i] < last && nums[i] < nums[i + 1] { |
| 184 | + ans++ |
| 185 | + } |
| 186 | + if nums[i] != nums[i + 1] { |
| 187 | + last = nums[i] |
| 188 | + } |
| 189 | + } |
| 190 | + return |
| 191 | +} |
| 192 | +``` |
| 193 | + |
| 194 | +> 同步发文于[CSDN](https://letmefly.blog.csdn.net/article/details/149727208)和我的[个人博客](https://blog.letmefly.xyz/),原创不易,转载经作者同意后请附上[原文链接](https://blog.letmefly.xyz/2025/07/28/LeetCode%202210.%E7%BB%9F%E8%AE%A1%E6%95%B0%E7%BB%84%E4%B8%AD%E5%B3%B0%E5%92%8C%E8%B0%B7%E7%9A%84%E6%95%B0%E9%87%8F/)哦~ |
| 195 | +> |
| 196 | +> 千篇源码题解[已开源](https://github.com/LetMeFly666/LeetCode) |
0 commit comments