Medium

题目描述

给定两个整数 num1num2,表示一个闭区间 [num1, num2]

数字的波动性定义为其峰值和谷值的总数:

  • 如果一个数字严格大于其两个相邻数字,则该数字是峰值。
  • 如果一个数字严格小于其两个相邻数字,则该数字是谷值。
  • 数字的第一位和最后一位不能是峰值或谷值。
  • 任何少于 3 位数的数字波动性为 0。

返回区间 [num1, num2] 内所有数字的波动性总和。

示例 1:

输入:num1 = 120, num2 = 130
输出:3
解释:
在区间 [120, 130] 中:
- 120:中间数字 2 是峰值,波动性 = 1。
- 121:中间数字 2 是峰值,波动性 = 1。
- 130:中间数字 3 是峰值,波动性 = 1。
- 其他所有数字的波动性都为 0。
因此,总波动性为 1 + 1 + 1 = 3。

示例 2:

输入:num1 = 198, num2 = 202
输出:3
解释:
在区间 [198, 202] 中:
- 198:中间数字 9 是峰值,波动性 = 1。
- 201:中间数字 0 是谷值,波动性 = 1。
- 202:中间数字 0 是谷值,波动性 = 1。
- 其他所有数字的波动性都为 0。
因此,总波动性为 1 + 1 + 1 = 3。

示例 3:

输入:num1 = 4848, num2 = 4848
输出:2
解释:
数字 4848:第二位数字 8 是峰值,第三位数字 4 是谷值,波动性为 2。

约束:

  • 1 <= num1 <= num2 <= 10^5

提示:

  • 使用暴力解法

解题思路

解题思路

这是一道需要计算数字波动性的题目。根据题意,我们需要:

  1. 理解波动性定义:对于一个数字,如果某一位严格大于左右相邻位,则为峰值;严格小于左右相邻位,则为谷值。首尾位不参与计算。

  2. 暴力枚举:由于数据范围不大(最多10^5),我们可以对区间内每个数字都计算其波动性,然后累加。

  3. 单个数字波动性计算

    • 将数字转换为字符串,便于处理每一位
    • 遍历中间的每一位(除首尾位)
    • 检查当前位是否为峰值或谷值
    • 累加峰值和谷值数量
  4. 边界条件处理

    • 少于3位的数字波动性为0
    • 只有中间位才能成为峰值或谷值

算法步骤:

  • 遍历区间[num1, num2]内的每个数字
  • 对每个数字计算波动性
  • 累加所有数字的波动性

时间复杂度主要取决于数字的位数和区间大小,由于约束条件限制,这种暴力解法完全可行。

代码实现

class Solution {
public:
    int totalWaviness(int num1, int num2) {
        int totalWaviness = 0;
        
        for (int num = num1; num <= num2; num++) {
            totalWaviness += calculateWaviness(num);
        }
        
        return totalWaviness;
    }
    
private:
    int calculateWaviness(int num) {
        string s = to_string(num);
        int n = s.length();
        
        if (n < 3) return 0;
        
        int waviness = 0;
        for (int i = 1; i < n - 1; i++) {
            char left = s[i - 1];
            char mid = s[i];
            char right = s[i + 1];
            
            // Check if it's a peak
            if (mid > left && mid > right) {
                waviness++;
            }
            // Check if it's a valley
            else if (mid < left && mid < right) {
                waviness++;
            }
        }
        
        return waviness;
    }
};
class Solution:
    def totalWaviness(self, num1: int, num2: int) -> int:
        total_waviness = 0
        
        for num in range(num1, num2 + 1):
            total_waviness += self.calculate_waviness(num)
        
        return total_waviness
    
    def calculate_waviness(self, num: int) -> int:
        s = str(num)
        n = len(s)
        
        if n < 3:
            return 0
        
        waviness = 0
        for i in range(1, n - 1):
            left = s[i - 1]
            mid = s[i]
            right = s[i + 1]
            
            # Check if it's a peak
            if mid > left and mid > right:
                waviness += 1
            # Check if it's a valley
            elif mid < left and mid < right:
                waviness += 1
        
        return waviness
public class Solution {
    public int TotalWaviness(int num1, int num2) {
        int totalWaviness = 0;
        
        for (int num = num1; num <= num2; num++) {
            totalWaviness += CalculateWaviness(num);
        }
        
        return totalWaviness;
    }
    
    private int CalculateWaviness(int num) {
        string s = num.ToString();
        int n = s.Length;
        
        if (n < 3) return 0;
        
        int waviness = 0;
        for (int i = 1; i < n - 1; i++) {
            char left = s[i - 1];
            char mid = s[i];
            char right = s[i + 1];
            
            // Check if it's a peak
            if (mid > left && mid > right) {
                waviness++;
            }
            // Check if it's a valley
            else if (mid < left && mid < right) {
                waviness++;
            }
        }
        
        return waviness;
    }
}
var totalWaviness = function(num1, num2) {
    let totalWaviness = 0;
    
    for (let num = num1; num <= num2; num++) {
        totalWaviness += calculateWaviness(num);
    }
    
    return totalWaviness;
};

function calculateWaviness(num) {
    const s = num.toString();
    const n = s.length;
    
    if (n < 3) return 0;
    
    let waviness = 0;
    for (let i = 1; i < n - 1; i++) {
        const left = s[i - 1];
        const mid = s[i];
        const right = s[i + 1];
        
        // Check if it's a peak
        if (mid > left && mid > right) {
            waviness++;
        }
        // Check if it's a valley
        else if (mid < left && mid < right) {
            waviness++;
        }
    }
    
    return waviness;
}

复杂度分析

复杂度类型复杂度说明
时间复杂度O((num2 - num1 + 1) × log₁₀(num2))需要遍历区间内每个数字,每个数字需要O(log₁₀(num))时间计算波动性
空间复杂度O(log₁₀(num2))字符串转换需要的额外空间,与最大数字的位数成正比