86 lines
3.5 KiB
Markdown
86 lines
3.5 KiB
Markdown
# [165] Compare Version Numbers
|
||
|
||
## 題目資訊
|
||
- **難度**: Medium
|
||
- **標籤**: Two Pointer, String
|
||
- **題目連結**: https://leetcode.com/problems/compare-version-numbers/
|
||
- **練習日期**: 2025-09-23
|
||
- **目標複雜度**: 時間 O(n)、空間 O(1)
|
||
|
||
## 題目描述
|
||
Given two **version strings**, `version1` and `version2`, compare them. A version string consists of **revisions** separated by dots `'.'`. The **value of the revision** is its **integer conversion** ignoring leading zeros.
|
||
|
||
To compare version strings, compare their revision values in **left-to-right order**. If one of the version strings has fewer revisions, treat the missing revision values as `0`.
|
||
|
||
Return the following:
|
||
|
||
If `version1 < version2`, return -1.
|
||
If `version1 > version2`, return 1.
|
||
Otherwise, return 0.
|
||
|
||
## 先備條件與限制
|
||
- 1 <= `version1.length, version2.length` <= 500
|
||
- version1 and version2 only contain digits and '.'
|
||
- version1 and version2 are valid version numbers.
|
||
- All the given revisions in `version1` and `version2` can be stored in a **32-bit integer**
|
||
|
||
## 解題思路
|
||
|
||
### 初步分析
|
||
- 類型:字串雙指標掃描
|
||
- 關鍵觀察:版本號可以逐段比較,缺段視為 0,且修訂號只包含數字
|
||
- 複雜度目標理由:只需線性掃過兩個字串一次即可完成比較
|
||
|
||
### 解法比較
|
||
1. 解法A(基準/暴力):
|
||
- 名稱:`MyCompareVersion`
|
||
- 思路:以 `Split('.')` 將版本字串拆成陣列,逐段轉成整數後比較;若另一側段數不足以 0 補齊
|
||
- 正確性:LeetCode 限制每段可裝進 32-bit 整數,直接使用 `int.TryParse` 安全可靠
|
||
- 複雜度:時間 O(n),空間 O(k)(k 為段數,需配置字串陣列與子字串)
|
||
2. 解法B(優化):
|
||
- 名稱:`CompareVersion`
|
||
- 思路:雙指標同步掃描兩個版本字串,藉由 `ReadOnlySpan<char>` 抓取下一段,去除前導 0 後用字元比較避免溢位與額外配置
|
||
- 正確性:段長先比較、再逐字比較,完全符合題意;缺段會回傳空 span 視為 0
|
||
- 複雜度:時間 O(n),空間 O(1)
|
||
|
||
## 實作細節
|
||
|
||
### 常見陷阱
|
||
- 前導 0:需在比較前移除,否則 `"01"` 與 `"1"` 會被視為不同
|
||
- 段數不一致:右側缺少的段要視為 0
|
||
- 空字串或末尾點:`""`、`"1."` 都可能出現,需要妥善處理
|
||
- 非數字字元:防守性處理(當前實作視為 0),但依題意實際資料不會出現
|
||
|
||
## 測試案例
|
||
|
||
### 範例輸入輸出
|
||
```
|
||
Input: version1 = "1.2", version2 = "1.10"
|
||
Output: -1
|
||
Explanation:
|
||
version1's second revision is "2" and version2's second revision is "10": 2 < 10, so version1 < version2.
|
||
```
|
||
|
||
### 邊界清單
|
||
- [x] 空字串 / 僅有 0
|
||
- [x] 單一段 / 全相同
|
||
- [x] 含 0 / 大數 / 前導 0
|
||
- [ ] 去重(與此題無關)
|
||
- [x] 大資料壓力(長度 200 的版本字串)
|
||
|
||
## 複雜度分析
|
||
- 最壞:時間 O(n)、空間 O(1)
|
||
- 備註:保留的 `MyCompareVersion` 雖然同為 O(n),但空間為 O(k)
|
||
|
||
## 相關題目 / Follow-up
|
||
- 179. Largest Number:同樣涉及字串排序與比較
|
||
- 415. Add Strings:字串逐位操作
|
||
|
||
## 學習筆記
|
||
- 今天學到:兩指標搭配 `ReadOnlySpan<char>` 可以在 C# 中避免額外配置
|
||
- 卡住與修正:原本 console app 移除 `Main` 造成 `dotnet test` 無法編譯,後來補回精簡入口
|
||
- 待優化:若要支援超長版本段,可考慮使用 `BigInteger` 或自訂比較邏輯(目前已以字元比較處理)
|
||
|
||
---
|
||
**總結**:核心在於逐段處理並正確處理前導 0 與缺段情況,適合練習字串雙指標與記憶體優化技巧。
|