145 lines
3.4 KiB
C#
145 lines
3.4 KiB
C#
// LeetCode 165: Compare Version Numbers
|
|
// 難度: Medium
|
|
// 日期: 2025-09-23
|
|
|
|
using System;
|
|
|
|
public class Solution
|
|
{
|
|
// Two-pointer parser that compares segments without allocating intermediate arrays.
|
|
public int CompareVersion(string version1, string version2)
|
|
{
|
|
var i = 0;
|
|
var j = 0;
|
|
|
|
while (i < version1.Length || j < version2.Length)
|
|
{
|
|
var segment1 = NextSegment(version1, ref i);
|
|
var segment2 = NextSegment(version2, ref j);
|
|
|
|
var comparison = CompareSegments(segment1, segment2);
|
|
if (comparison != 0)
|
|
{
|
|
return comparison;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
// Reads the next numeric segment (between dots) as a span and advances the current index.
|
|
private static ReadOnlySpan<char> NextSegment(string version, ref int index)
|
|
{
|
|
if (index >= version.Length)
|
|
{
|
|
return ReadOnlySpan<char>.Empty;
|
|
}
|
|
|
|
var start = index;
|
|
while (index < version.Length && version[index] != '.')
|
|
{
|
|
index++;
|
|
}
|
|
|
|
var segment = version.AsSpan(start, index - start);
|
|
|
|
if (index < version.Length && version[index] == '.')
|
|
{
|
|
index++;
|
|
}
|
|
|
|
return segment;
|
|
}
|
|
|
|
// Compares two trimmed segments lexicographically to avoid integer overflow.
|
|
private static int CompareSegments(ReadOnlySpan<char> left, ReadOnlySpan<char> right)
|
|
{
|
|
left = TrimLeadingZeros(left);
|
|
right = TrimLeadingZeros(right);
|
|
|
|
if (left.Length > right.Length)
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
if (left.Length < right.Length)
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
for (var i = 0; i < left.Length; i++)
|
|
{
|
|
if (left[i] > right[i])
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
if (left[i] < right[i])
|
|
{
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
private static ReadOnlySpan<char> TrimLeadingZeros(ReadOnlySpan<char> segment)
|
|
{
|
|
var index = 0;
|
|
while (index < segment.Length && segment[index] == '0')
|
|
{
|
|
index++;
|
|
}
|
|
|
|
return index == segment.Length ? ReadOnlySpan<char>.Empty : segment[index..];
|
|
}
|
|
|
|
public int MyCompareVersion(string version1, string version2)
|
|
{
|
|
var v1 = version1.Split('.');
|
|
var v2 = version2.Split('.');
|
|
|
|
if (v1.Length >= v2.Length)
|
|
{
|
|
return CompareString(v1, v2);
|
|
}
|
|
|
|
return CompareString(v2, v1) * -1;
|
|
}
|
|
|
|
private static int CompareString(string[] longer, string[] shorter)
|
|
{
|
|
for (var i = 0; i < longer.Length; i++)
|
|
{
|
|
_ = int.TryParse(longer[i], out var num1);
|
|
var num2 = i < shorter.Length && int.TryParse(shorter[i], out var parsed) ? parsed : 0;
|
|
|
|
if (num1 > num2)
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
if (num1 < num2)
|
|
{
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
public class Program
|
|
{
|
|
public static void Main(string[] args)
|
|
{
|
|
// optional: keep console app functional for manual verification
|
|
if (args.Length == 2)
|
|
{
|
|
var solution = new Solution();
|
|
var result = solution.CompareVersion(args[0], args[1]);
|
|
Console.WriteLine(result);
|
|
}
|
|
}
|
|
}
|