刷题练习——118. 版本号比较

52 阅读3分钟

以下为题目描述

问题描述

在某个项目中,每个版本都用版本号标记,由一个或多个修订号组成,修订号之间由点号.分隔。每个修订号可能有多位数字,并且可能会包含前导零。你需要根据两个版本号 version1 和 version2,判断哪个版本更新,或者它们是否相同。

例如,2.5.33 和 0.1 都是有效的版本号。

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

你需要根据以下规则返回比较结果:

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

测试样例

样例1:

输入:version1 = "0.1" , version2 = "1.1"
输出:-1

样例2:

输入:version1 = "1.0.1" , version2 = "1"
输出:1

样例3:

输入:version1 = "7.5.2.4" , version2 = "7.5.3"
输出:-1

样例4:

输入:version1 = "1.0" , version2 = "1.0.0"
输出:0

解决方案

import java.math.BigInteger;

public class Main {
    public static void main(String[] args) {
        System.out.println(solution("0.1", "1.1") == -1);
        System.out.println(solution("1.0.1", "1") == 1);
        System.out.println(solution("7.5.2.4", "7.5.3") == -1);
        System.out.println(solution("1.0", "1.0.0") == 0);
    }

    public static int solution(String version1, String version2) {
        // Split the version strings into revision numbers
        String[] revisions1 = version1.split("\\.");
        String[] revisions2 = version2.split("\\.");

        // Determine the maximum length to iterate over
        int maxLength = Math.max(revisions1.length, revisions2.length);

        for (int i = 0; i < maxLength; i++) {
            // 获取第 i 个修订号,若超出数组长度,则补为 "0"
            String rev1 = i < revisions1.length ? revisions1[i] : "0";
            String rev2 = i < revisions2.length ? revisions2[i] : "0";

            // 去除前导零
            rev1 = rev1.replaceFirst("^0+", "");
            rev2 = rev2.replaceFirst("^0+", "");

            // 如果去除前导零后为空,则修订号为 "0"
            if (rev1.isEmpty()) rev1 = "0";
            if (rev2.isEmpty()) rev2 = "0";

            // 转换为 BigInteger
            BigInteger num1 = new BigInteger(rev1);
            BigInteger num2 = new BigInteger(rev2);

            // 比较两个修订号
            int comparison = num1.compareTo(num2);
            if (comparison > 0) {
                return 1; // version1 is greater
            } else if (comparison < 0) {
                return -1; // version2 is greater
            }
            // If equal, continue to next revision
        }
        // All revisions are equal
        return 0;
    }
}

代码解释

  1. 分割版本号字符串
String[] revisions1 = version1.split("\\.");
String[] revisions2 = version2.split("\\.");

首先先来分割版本号字符串,使用正则表达式来解决

• 使用正则表达式 "\." 将版本号字符串按点号分割,得到修订号数组

• 例如,"1.0.1" 分割后得到 ["1", "0", "1"]

2.确定比较的最大长度

int maxLength = Math.max(revisions1.length, revisions2.length);

• 为了比较所有修订号,取两个版本修订号数组的最大长度

  1. 逐个比较修订号
for (int i = 0; i < maxLength; i++) {
    // 获取第 i 个修订号,若超出数组长度,则补为 "0"
    String rev1 = i < revisions1.length ? revisions1[i] : "0";
    String rev2 = i < revisions2.length ? revisions2[i] : "0";

    // 去除前导零
    rev1 = rev1.replaceFirst("^0+", "");
    rev2 = rev2.replaceFirst("^0+", "");

    // 如果去除前导零后为空,则修订号为 "0"
    if (rev1.isEmpty()) rev1 = "0";
    if (rev2.isEmpty()) rev2 = "0";

    // 转换为 BigInteger
    BigInteger num1 = new BigInteger(rev1);
    BigInteger num2 = new BigInteger(rev2);

    // 比较两个修订号
    int comparison = num1.compareTo(num2);
    if (comparison > 0) {
        return 1; // version1 更大
    } else if (comparison < 0) {
        return -1; // version2 更大
    }
    // 若相等,继续下一轮比较
}

获取修订号:

使用条件运算符检查索引是否越界,若越界则补为 "0"。

去除前导零:

使用正则表达式 "^0+" 去除字符串开头的所有零,例如,"001" 去除前导零后得到 "1"。

如果去除后为空字符串,则说明修订号原本是 "0" 或者全是零,需要将其设为 "0"。

转换为 BigInteger

使用 BigInteger 而不是 Integer 或 Long,是为了防止修订号过大导致溢出。

比较修订号:

使用 compareTo 方法比较两个 BigInteger 对象。

如果 num1 大于 num2,返回 1。

如果 num1 小于 num2,返回 -1。

如果相等,继续比较下一个修订号