青训营X豆包MarsCode 技术训练营第三课 | 豆包MarsCode AI 刷题

72 阅读4分钟

解析与图解

问题描述

在软件版本控制中,版本号通常由一个或多个修订号组成,修订号之间用点号 . 分隔。例如,2.5.330.1 都是有效的版本号。每个修订号可能包含多位数字,并且可能包含前导零。

给定两个版本号 version1version2,我们需要比较这两个版本号,判断哪个版本更新,或者它们是否相同。比较规则如下:

  1. 从左到右依次比较两个版本号的修订号。
  2. 忽略每个修订号的前导零,直接比较修订号对应的整数值。
  3. 如果其中一个版本没有足够的修订号,缺失的部分默认补为 0

根据比较结果,返回:

  • 如果 version1 > version2,返回 1
  • 如果 version1 < version2,返回 -1
  • 如果两个版本相等,返回 0

示例分析

让我们通过示例来理解问题:

  • 示例 1:

    • 输入: version1 = "0.1", version2 = "1.1"
    • 输出: -1
    • 解释: 比较第一个修订号 010 < 1,所以 version1 < version2
  • 示例 2:

    • 输入: version1 = "1.0.1", version2 = "1"
    • 输出: 1
    • 解释: 比较第一个修订号 11,相等。比较第二个修订号 0 和缺失的修订号(视为 0),0 = 0。比较第三个修订号 1 和缺失的修订号(视为 0),1 > 0,所以 version1 > version2
  • 示例 3:

    • 输入: version1 = "7.5.2.4", version2 = "7.5.3"
    • 输出: -1
    • 解释: 比较第一个修订号 77,相等。比较第二个修订号 55,相等。比较第三个修订号 232 < 3,所以 version1 < version2
  • 示例 4:

    • 输入: version1 = "1.0", version2 = "1.0.0"
    • 输出: 0
    • 解释: 比较第一个修订号 11,相等。比较第二个修订号 00,相等。version1 没有第三个修订号,视为 00 = 0,所以 version1 = version2

算法思路

为了比较两个版本号,我们可以按照以下步骤进行:

  1. 分割修订号:

    • 使用 split("\\.") 方法将版本号字符串按点号 . 分割成修订号数组。
  2. 确定比较长度:

    • 比较两个版本号的修订号数组长度,取较大的长度作为循环的次数。
    • 这样可以确保即使一个版本号比另一个版本号短,缺失的修订号也会被视为 0
  3. 逐个比较修订号:

    • 对于每个修订号对:
      • 如果当前修订号不存在,视为 0
      • 将修订号字符串转换为整数。
      • 比较两个修订号的大小:
        • 如果 revision1 > revision2,返回 1
        • 如果 revision1 < revision2,返回 -1
        • 如果相等,继续比较下一个修订号。
  4. 返回结果:

    • 如果所有修订号都相等,返回 0

图解

假设输入为 version1 = "1.0.1", version2 = "1"

  • 分割修订号:

    • revisions1 = ["1", "0", "1"]
    • revisions2 = ["1"]
  • 比较过程:

    1. 比较第一个修订号 11,相等。
    2. 比较第二个修订号 0 和缺失的修订号(视为 0),相等。
    3. 比较第三个修订号 1 和缺失的修订号(视为 0),1 > 0,所以 version1 > version2

代码详解

public class Main {
    public static void main(String[] args) {
        // 测试样例
        System.out.println(solution("0.1", "1.1") == -1); // 输出: true
        System.out.println(solution("1.0.1", "1") == 1);   // 输出: true
        System.out.println(solution("7.5.2.4", "7.5.3") == -1); // 输出: true
        System.out.println(solution("1.0", "1.0.0") == 0); // 输出: true
    }

    public static int solution(String version1, String version2) {
        // 将版本号按 '.' 分割成修订号数组
        String[] revisions1 = version1.split("\\.");
        String[] revisions2 = version2.split("\\.");

        // 找出较长的修订号数组长度
        int maxLength = Math.max(revisions1.length, revisions2.length);

        // 逐个比较修订号
        for (int i = 0; i < maxLength; i++) {
            // 如果当前下标超出了修订号数组长度,视为 0
            int revision1 = i < revisions1.length ? Integer.parseInt(revisions1[i]) : 0;
            int revision2 = i < revisions2.length ? Integer.parseInt(revisions2[i]) : 0;

            // 比较当前修订号
            if (revision1 > revision2) {
                return 1;
            } else if (revision1 < revision2) {
                return -1;
            }
        }

        // 如果所有修订号都相等,返回 0
        return 0;
    }
}
  • 分割修订号:

    • 使用 split("\\.") 方法将版本号字符串按点号 . 分割成修订号数组。
    • 正则表达式 \\. 用于匹配字面量的点号 .,因为在正则表达式中 . 是一个特殊字符。
  • 确定比较长度:

    • 使用 Math.max(revisions1.length, revisions2.length) 找出较长的修订号数组长度。
  • 逐个比较修订号:

    • 使用 Integer.parseInt(revisions[i]) 将修订号字符串转换为整数。
    • 如果当前修订号不存在,视为 0
    • 比较两个修订号的大小:
      • 如果 revision1 > revision2,返回 1
      • 如果 revision1 < revision2,返回 -1
      • 如果相等,继续比较下一个修订