Compare commits

...

69 Commits

Author SHA1 Message Date
8146e2176d [#0166] feat(leetcode): add README, unit test and C# solution 2025-09-24 11:18:08 +08:00
5189c524ef [#0166] feat(leetcode): init project 2025-09-24 09:35:00 +08:00
959f8a6861 remove: legacy solutions 2025-09-24 09:34:13 +08:00
5f8bf18795 docs(monthly): update monthly report 2025-09-23 11:02:46 +08:00
72aa011de9 [#0165]feat(leetcode): Init project, add C# solution, unit test and README 2025-09-23 10:59:18 +08:00
c4e23d5be3 docs(monthly): update monthly report 2025-09-22 13:51:44 +08:00
c7453b45e6 [#3005] feat(leetcode): init project, add C# solution 2025-09-22 13:48:38 +08:00
7c86a4a99a feat(makefile): makefile for automatic setup 2025-09-22 09:58:24 +08:00
c396a84294 docs(logs): update monthly log 2025-09-12 13:37:31 +08:00
2d6209a043 [#3227] docs(leetcode): update README 2025-09-12 13:34:05 +08:00
1e562065e8 [#3227] feat(leetcode): add c# and golang solution 2025-09-12 13:13:22 +08:00
8dfafaaf43 docs(utils,readme): add helper help and refresh docs 2025-09-12 10:37:45 +08:00
6d9993cd9f feat(utils): add global test runner and helper help 2025-09-12 10:19:47 +08:00
9ff736e11c feat(utils,templates,docs): file-based .tmpl templates; remove I/O fixtures 2025-09-12 09:56:37 +08:00
d724a5fb65 feat(utils, templates, docs): file-based templates + stronger README 2025-09-12 09:44:30 +08:00
002e9e6c32 docs(README): edit monthly README 2025-09-11 11:09:43 +08:00
75f3d9e320 feat(SortVowels): add C# solution 2025-09-11 11:05:11 +08:00
f4a7029b7e docs(README): monthly README 2025-09-08 14:34:32 +08:00
31d68d2f04 [#1317] docs(GetNoZeroIntegers): add README 2025-09-08 14:28:10 +08:00
4b2df683a4 [#1317] feat(GetNoZeroIntegers): add C# solution 2025-09-08 14:27:53 +08:00
cf3a952d1d Merge pull request '2025-09/2749-minimum-operations-to-make-the-integer-zero' (#9) from 2025-09/2749-minimum-operations-to-make-the-integer-zero into main
Reviewed-on: #9
2025-09-05 09:02:59 +00:00
63880d4717 feat(makeTheIntegerZeio): add C# solution 2025-09-05 16:54:03 +08:00
c3955ad390 docs(makeTheIntegerZero): add README 2025-09-05 16:52:45 +08:00
08c96f8636 Merge pull request '2025-09/3516-find-closest-person' (#8) from 2025-09/3516-find-closest-person into main
Reviewed-on: #8
2025-09-04 02:17:29 +00:00
MH Hung
ec12425cb9 [#3516] feat(note): add monthly README 2025-09-04 10:14:05 +08:00
MH Hung
17eaaa52c2 [#3516] feat(go): add golang solution 2025-09-04 10:10:53 +08:00
MH Hung
58acd6e8d8 [#3516] feat(C#): add C# solution 2025-09-04 10:10:26 +08:00
MH Hung
b81da2e59e [#3516] feat(note): add description 2025-09-04 10:09:45 +08:00
bd46985abc note(README): add monthly README 2025-09-03 11:09:14 +08:00
26696bf229 Merge pull request '2025-09/3027-find-the-number-of-ways-to-place-people-ii' (#7) from 2025-09/3027-find-the-number-of-ways-to-place-people-ii into main
Reviewed-on: #7
2025-09-03 03:06:42 +00:00
d120af6661 [#3027] testI(numberOfPairs): add C# unit test cases 2025-09-03 11:04:35 +08:00
614434de14 [#3027] note(numberOfPairs): add README of Description 2025-09-03 11:03:55 +08:00
bcbea676c2 [#3027] feat(numberOfPairs): add C# solution 2025-09-03 10:55:26 +08:00
b9965b192c Merge pull request '2025-09/3025-find-the-number-of-ways-to-place-people-i' (#6) from 2025-09/3025-find-the-number-of-ways-to-place-people-i into main
Reviewed-on: #6
2025-09-02 06:09:17 +00:00
8a49217c3d [#3025] note(numbersOfPairs): add monthly note 2025-09-02 14:08:30 +08:00
0c278fa275 [#3025] test(numberOfPairs): add golang unit test 2025-09-02 14:05:40 +08:00
c760afc0f7 [#3025] feat(numberOfPairs): add golang solution 2025-09-02 13:31:22 +08:00
b99708dc36 [#3025] note(numberOfPairs): add monthly note 2025-09-02 12:35:26 +08:00
38f948f691 [#3025] test(numberOfPairs): write C# unit test 2025-09-02 12:28:52 +08:00
5018b4ab9f [#3025] feat(numberOfPairs): add C# solution, add notes 2025-09-02 11:11:15 +08:00
262a934d89 [#3025] note(numberOfPairs): add Description and init C# project 2025-09-02 09:57:41 +08:00
492b5ecd60 fix(bash): fix unit test bash run error 2025-09-01 17:22:53 +08:00
ac6bc1010e [#1782] note(MaxAverageRatio): add complexity describe 2025-09-01 14:53:36 +08:00
a37a374c24 [#1782] fix(README): fix readme 2025-09-01 14:44:16 +08:00
b07f0c2957 Merge pull request '2025-09/1792-maximum-avergae-pass-ratio' (#5) from 2025-09/1792-maximum-avergae-pass-ratio into main
Reviewed-on: #5
2025-09-01 06:41:36 +00:00
e3edc716ef [#1782] test(MaxAverageRatio): Add run test bash and cases describe 2025-09-01 14:38:58 +08:00
2c72e5236f [#1782] feat(MaxAverageRatio): Add priority queue method 2025-09-01 13:45:31 +08:00
70f64e1ef7 [#1782] note(MaxAverageRatio): Add solution README 2025-09-01 13:44:57 +08:00
24828dfbf0 [#1782] test(MaxAverageRatio): Add test cases for C# solution 2025-09-01 13:38:07 +08:00
7c9e454777 [#1792]feat(MaxAverageRatio) : add C# brute force solution 2025-09-01 12:08:15 +08:00
30f9a73a17 fix(template): solved redundant filess 2025-09-01 10:03:54 +08:00
ed0d2f344d feat(template): add readme templates and leetcode helper 2025-09-01 09:48:11 +08:00
11e62e4eac feat(template): add problem template markdown 2025-09-01 09:17:10 +08:00
9fec047d3f refactor: refactor project structure 2025-09-01 09:13:32 +08:00
524784a3c5 Merge pull request '[#3446] feat(SortMatrix): add C# solution' (#4) from 2508/3446 into main
Reviewed-on: #4
2025-08-29 01:17:28 +00:00
6960f1136f [#3446] feat(SortMatrix): add C# solution 2025-08-28 12:25:01 +08:00
2a90279797 Merge pull request '2508/3000' (#3) from 2508/3000 into main
Reviewed-on: #3
2025-08-26 06:24:02 +00:00
4b92457f40 [#3000] feat(AreaOfMaxDiagonal): add golang solution 2025-08-26 14:22:31 +08:00
174dd451da [#3000] feat(AreaOfMaxDiagonal): add C# solution 2025-08-26 14:12:02 +08:00
f61f982669 Merge pull request '2508/FindDiagonalOrder' (#2) from 2508/FindDiagonalOrder into main
Reviewed-on: #2
2025-08-25 03:58:49 +00:00
f25337364b [#498] feat(FindDiagonalOrder): add golang solution 2025-08-25 11:57:30 +08:00
b8a053eff1 [#498] feat(FindDiagonalOrder): add C# solution 2025-08-25 11:04:55 +08:00
385787dbdc [#498] docs(FindDiagonalOrder) : add solution note 2025-08-25 11:04:08 +08:00
541227b060 [#498] feat(FindDiagonalOrder): Init issue 2025-08-25 10:18:32 +08:00
0aa92458aa feat(common): edit README 2025-08-25 09:49:26 +08:00
87f14206fe Merge pull request '2508/3195' (#1) from 2508/3195 into main
Reviewed-on: #1
2025-08-25 01:48:20 +00:00
dedeabb44b [#3195] feat(MinimumArea): add golang solution 2025-08-25 09:42:27 +08:00
41c0f6d3db [#3195] feat(MinimumArea): add C# solution 2025-08-25 09:42:10 +08:00
6464507fd9 test 2025-08-24 14:28:26 +08:00
108 changed files with 5393 additions and 594 deletions

0
.gitignore vendored Normal file → Executable file
View File

View File

@@ -1,24 +0,0 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.5.2.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "largestGoodInteger", "largestGoodInteger.csproj", "{DF73131C-3A52-FFDC-7C0C-19190AA3E331}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{DF73131C-3A52-FFDC-7C0C-19190AA3E331}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{DF73131C-3A52-FFDC-7C0C-19190AA3E331}.Debug|Any CPU.Build.0 = Debug|Any CPU
{DF73131C-3A52-FFDC-7C0C-19190AA3E331}.Release|Any CPU.ActiveCfg = Release|Any CPU
{DF73131C-3A52-FFDC-7C0C-19190AA3E331}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {E9F3A871-90C4-4B8E-81E2-B0AF873694BF}
EndGlobalSection
EndGlobal

View File

@@ -1,63 +0,0 @@
public class Solution {
public string LargestGoodInteger(string num)
{
// var count = 0;
// char lastNum = 'a';
// var numList = new List<int>();
// for (var i = 0; i < num.Length; i++)
// {
// if (num[i] == lastNum)
// {
// count++;
// if (count == 3)
// {
// numList.Add(int.Parse(num[i].ToString()));
// }
// }
// else
// {
// count = 1;
// }
// lastNum = num[i];
// }
// if (numList.Count == 0)
// {
// return "";
// }
// else
// {
// var a = numList.Max().ToString();
// return $"{a}{a}{a}";
// }
string max = "";
for (int i = 0; i < num.Length - 2; i++)
{
if (num[i] == num[i + 1] && num[i] == num[i + 2])
{
string current = $"{num[i]}{num[i]}{num[i]}";
if (max == "") max = current;
else
{
if (int.Parse(current) > int.Parse(max))
max = current;
}
}
}
return max;
}
}
class program
{
static void Main()
{
var solution = new Solution();
Console.WriteLine(solution.LargestGoodInteger("6777133339"));
}
}

View File

@@ -1,23 +0,0 @@
package main
import "fmt"
func LargestGoodInteger(num string) string {
max := ""
for i := 0; i < len(num)-2; i++ {
if num[i] == num[i+1] && num[i] == num[i+2] {
current := string([]byte{num[i], num[i], num[i]})
if current > max {
max = current
}
}
}
return max
}
func main() {
fmt.Println(LargestGoodInteger("7636669283"))
}

View File

@@ -1,24 +0,0 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.5.2.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ProductQueries", "C#\ProductQueries.csproj", "{412F89C4-B1BF-D819-298B-9C873A098742}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{412F89C4-B1BF-D819-298B-9C873A098742}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{412F89C4-B1BF-D819-298B-9C873A098742}.Debug|Any CPU.Build.0 = Debug|Any CPU
{412F89C4-B1BF-D819-298B-9C873A098742}.Release|Any CPU.ActiveCfg = Release|Any CPU
{412F89C4-B1BF-D819-298B-9C873A098742}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {BDF3A5A3-29B8-4169-8A46-A13A7DE900D8}
EndGlobalSection
EndGlobal

View File

@@ -1,69 +0,0 @@
using System;
public class Solution
{
public int[] ProductQueries(int n, int[][] queries)
{
// 1. n => calculate in powers of 2
// 2. get number array without 0
var powers = CalPower(n);
return CalQueries(powers, queries);
}
private int[] CalPower(int n)
{
var result = new List<int>();
while (n > 0)
{
var num = n % 2;
result.Add(num);
n /= 2;
}
var newResult = new List<int>();
for (var i = 0; i < result.Count; i++)
{
if (result[i] != 0)
{
var ans = (int)Math.Pow(2, i);
newResult.Add(ans);
}
}
return newResult.ToArray();
}
private int[] CalQueries(int[] powers, int[][] queries)
{
const int MOD = 1000000007;
var result = new List<int>();
foreach (var query in queries)
{
long count = 1;
for (var i = query[0]; i <= query[1]; i++)
{
count = (count * powers[i]) % MOD;
}
result.Add(count);
}
return result.ToArray();
}
}
class Program
{
static void Main()
{
var Solution = new Solution();
var ans = Solution.ProductQueries(15, [[0, 1], [2, 2], [0, 3]]);
Console.WriteLine(string.Join(", ", ans));
ans = Solution.ProductQueries(919, [[5,5],[4,4],[0,1],[1,5],[4,6],[6,6],[5,6],[0,3],[5,5],[5,6],[1,2],[3,5],[3,6],[5,5],[4,4],[1,1],[2,4],[4,5],[4,4],[5,6],[0,4],[3,3],[0,4],[0,5],[4,4],[5,5],[4,6],[4,5],[0,4],[6,6],[6,6],[6,6],[2,2],[0,5],[1,4],[0,3],[2,4],[5,5],[6,6],[2,2],[2,3],[5,5],[0,6],[3,3],[6,6],[4,4],[0,0],[0,2],[6,6],[6,6],[3,6],[0,4],[6,6],[2,2],[4,6]]);
Console.WriteLine(string.Join(", ", ans));
}
}

View File

@@ -1,5 +0,0 @@
Given a positive integer n, there exists a 0-indexed array called powers, composed of the minimum number of powers of 2 that sum to n. The array is sorted in non-decreasing order, and there is only one way to form the array.
You are also given a 0-indexed 2D integer array queries, where queries[i] = [lefti, righti]. Each queries[i] represents a query where you have to find the product of all powers[j] with lefti <= j <= righti.
Return an array answers, equal in length to queries, where answers[i] is the answer to the ith query. Since the answer to the ith query may be too large, each answers[i] should be returned modulo 109 + 7.

View File

@@ -1,24 +0,0 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.5.2.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "numberOfWays", "numberOfWays.csproj", "{1E81E272-AF2C-9CB4-F90B-0AAC263D10DC}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{1E81E272-AF2C-9CB4-F90B-0AAC263D10DC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1E81E272-AF2C-9CB4-F90B-0AAC263D10DC}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1E81E272-AF2C-9CB4-F90B-0AAC263D10DC}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1E81E272-AF2C-9CB4-F90B-0AAC263D10DC}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {AD18FC84-E2FB-4382-96DF-8AE7E50C1401}
EndGlobalSection
EndGlobal

View File

@@ -1,48 +0,0 @@
// knapsack problem
public class Solution
{
public int NumberOfWays(int n, int x)
{
const int MOD = 1_000_000_007;
// list all the powers which smaller than n
var powers = new List<int>();
var num = 1;
while (true)
{
int pow = (int)Math.Pow(num, x);
if (pow > n)
break;
powers.Add(pow);
num++;
}
// dynamic programming
var dp = new int[n + 1];
dp[0] = 1;
foreach (var power in powers)
{
for (var i = n; i >= power; i--)
{
dp[i] = (dp[i] + dp[i - power]) % MOD;
}
}
return dp[n];
}
}
class Program
{
static void Main()
{
var solution = new Solution();
Console.WriteLine(solution.NumberOfWays(4, 1));
Console.WriteLine(solution.NumberOfWays(100, 3));
}
}

View File

@@ -1,21 +0,0 @@
public class Solution {
public bool IsPowerOfThree(int n) {
if(n <= 0)
return false;
if(n == 1)
return true;
if(n % 3 != 0)
return false;
return IsPowerOfThree(n/3);
}
}
class program{
static void Main(){
var Solution = new Solution();
Console.WriteLine(Solution.IsPowerOfThree(9));
Console.WriteLine(Solution.IsPowerOfThree(0));
Console.WriteLine(Solution.IsPowerOfThree(-1));
}
}

View File

@@ -1,22 +0,0 @@
Given an integer n, return true if it is a power of three. Otherwise, return false.
An integer n is a power of three, if there exists an integer x such that n == 3x.
Example 1:
Input: n = 27
Output: true
Explanation: 27 = 33
Example 2:
Input: n = 0
Output: false
Explanation: There is no x where 3x = 0.
Example 3:
Input: n = -1
Output: false
Explanation: There is no x where 3x = (-1).

View File

@@ -1,26 +0,0 @@
package main
import "fmt"
type Solution struct{}
func (s Solution) IsPowerOfThree(n int) bool{
if n <= 0{
return false
}
if n == 1{
return true
}
if n % 3 != 0{
return false
}
return s.IsPowerOfThree(n/3)
}
func main(){
solution := Solution{}
fmt.Println(solution.IsPowerOfThree(27))
fmt.Println(solution.IsPowerOfThree(0))
fmt.Println(solution.IsPowerOfThree(-1))
}

View File

@@ -1,24 +0,0 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.5.2.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MaxCollectedFruits", "MaxCollectedFruits.csproj", "{AA67CF61-67B3-7229-E3F9-D471B0EF4EDE}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{AA67CF61-67B3-7229-E3F9-D471B0EF4EDE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{AA67CF61-67B3-7229-E3F9-D471B0EF4EDE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{AA67CF61-67B3-7229-E3F9-D471B0EF4EDE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{AA67CF61-67B3-7229-E3F9-D471B0EF4EDE}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {B9D47F51-61C3-4A24-890A-01C9AC85EC93}
EndGlobalSection
EndGlobal

View File

@@ -1,67 +0,0 @@
public class Solution
{
public int MaxCollectedFruits(int[][] fruits)
{
int n = fruits.Length;
int ans = 0;
for (int i = 0; i < n; ++i) ans += fruits[i][i];
int dp()
{
int[] prev = Enumerable.Repeat(int.MinValue, n).ToArray();
int[] curr = new int[n];
prev[n - 1] = fruits[0][n - 1];
for (int i = 1; i < n - 1; ++i)
{
Array.Fill(curr, int.MinValue);
for (int j = Math.Max(n - 1 - i, i + 1); j < n; ++j)
{
int best = prev[j];
if (j - 1 >= 0)
{
best = Math.Max(best, prev[j - 1]);
}
if (j + 1 < n)
{
best = Math.Max(best, prev[j + 1]);
}
curr[j] = best + fruits[i][j];
}
var temp = prev;
prev = curr;
curr = temp;
}
return prev[n - 1];
}
ans += dp();
for (int i = 0; i < n; ++i)
{
for (int j = 0; j < i; ++j)
{
var temp = fruits[j][i];
fruits[j][i] = fruits[i][j];
fruits[i][j] = temp;
}
}
ans += dp();
return ans;
}
}
class Program
{
static void Main()
{
var Solution = new Solution();
var fruits = new int[][] { [1,2,3,4],[5,6,8,7],[9,10,11,12],[13,14,15,16]};
Console.WriteLine(Solution.MaxCollectedFruits(fruits));
}
}

View File

@@ -1,24 +0,0 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.5.2.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "soupServings", "soupServings.csproj", "{6D960F00-6A53-6E19-86A1-4BF3D1CD764F}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{6D960F00-6A53-6E19-86A1-4BF3D1CD764F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6D960F00-6A53-6E19-86A1-4BF3D1CD764F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6D960F00-6A53-6E19-86A1-4BF3D1CD764F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6D960F00-6A53-6E19-86A1-4BF3D1CD764F}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {11CC27B7-C17E-4820-8A68-ADD32A2B37F8}
EndGlobalSection
EndGlobal

View File

@@ -1,56 +0,0 @@
using System;
public class Solution
{
private Dictionary<(int, int), double> dp = new Dictionary<(int, int), double>();
public double SoupServings(int n)
{
if (n > 5000)
return 1.0;
n = (n + 24) / 25;
// use dynamic programming
return Helper(n, n);
}
private double Helper(int a, int b)
{
if (a <= 0 && b <= 0)
{
return 0.5;
}
if (a <= 0)
{
return 1.0;
}
if (b <= 0)
{
return 0.0;
}
if (dp.ContainsKey((a, b)))
{
return dp[(a, b)];
}
double probability = 0.25 * (
Helper(a - 4, b) +
Helper(a - 3, b - 1) +
Helper(a - 2, b - 2) +
Helper(a - 1, b - 3)
);
dp[(a, b)] = probability;
return probability;
}
}
class Program
{
static void Main()
{
var Solution = new Solution();
var ans = Solution.SoupServings(800);
Console.WriteLine(ans);
}
}

View File

@@ -1,52 +0,0 @@
package main
import ("fmt")
type Solution struct{
dp map[[2]int]float64
}
func NewSolution() *Solution{
return &Solution{dp: make(map[[2]int]float64)}
}
func (s *Solution) SoupServings(n int)float64{
if n > 5000{
return 1.0
}
n = (n+24) /25
return s.helper(n, n)
}
func (s * Solution) helper(a, b int) float64 {
if a <= 0 && b <= 0{
return 0.5
}
if a <= 0{
return 1.0
}
if b <= 0{
return 0
}
if val, exist := s.dp[[2]int{a, b}]; exist{
return val
}
probability := 0.25 * (
s.helper(a-4, b) +
s.helper(a-3, b-1) +
s.helper(a-2, b-2) +
s.helper(a-1, b-3))
s.dp[[2]int {a, b}] = probability
return probability
}
func main(){
Solution := NewSolution()
ans := Solution.SoupServings(100)
fmt.Println(ans)
}

View File

@@ -1,14 +0,0 @@
You have two soups, A and B, each starting with n mL. On every turn, one of the following four serving operations is chosen at random, each with probability 0.25 independent of all previous turns:
pour 100 mL from type A and 0 mL from type B
pour 75 mL from type A and 25 mL from type B
pour 50 mL from type A and 50 mL from type B
pour 25 mL from type A and 75 mL from type B
Note:
There is no operation that pours 0 mL from A and 100 mL from B.
The amounts from A and B are poured simultaneously during the turn.
If an operation asks you to pour more than you have left of a soup, pour all that remains of that soup.
The process stops immediately after any turn in which one of the soups is used up.
Return the probability that A is used up before B, plus half the probability that both soups are used up in the same turn. Answers within 10-5 of the actual answer will be accepted.

0
LICENSE Normal file → Executable file
View File

View File

@@ -1,4 +0,0 @@
# Dynamic programming 動態規劃
## 2D
https://hackmd.io/@bangyewu/By3RWr0ZT

292
README.md Normal file → Executable file
View File

@@ -1,5 +1,289 @@
# coding-practice
# LeetCode 練習專案
Practice from Daily Leetcode
ACC : iak64825@jioso.com
Password : ww5&Hy73dgh
這是一個用來紀錄與管理 LeetCode 練習的專案,整合 C# 與 Go 的題解、基本測試模板、月度學習日誌,以及一支小工具腳本,協助快速建立新題目與維持一致的結構與習慣。
## 專案架構
```
.
├── problems/ # 每題一個資料夾 (NNNN-kebab-case)
│ └── 3516-find-closest-person/
│ ├── README.md # 題目說明與解題筆記
│ ├── csharp/ # C# 解法 (dotnet)
│ ├── go/ # Go 解法 (go module)
│ └── test/ # C#/Go 測試模板與測試檔
├── utils/
│ ├── leetcode_helper.sh # 建題、更新 README、建立月誌
│ └── run_tests.sh # 全域測試執行器(選擇 C#/Go 或全部)
├── logs/ # 月度練習紀錄 (YYYY-MM.md)
├── templates/ # 檔案模板 (.tmpl)
│ ├── problem/ # 建題用模板README、C#/Go、test
│ ├── problem-template.md.tmpl # 題解寫作指引模板(參考用)
│ └── logs-template.md.tmpl # 月誌模板
├── legacy/ # 舊題或舊結構的紀錄
├── LICENSE
└── README.md
```
命名慣例問題資料夾以「4 位數題號 + 題目英文 kebab-case」命名例如 `3025-find-the-number-of-ways-to-place-people-i`
## 需求與環境
- C#: 安裝 `.NET SDK 8+`,常用指令 `dotnet build / run / test`
- Go: 安裝 `Go 1.21+`,常用指令 `go build / run / test`
- Bash: 可執行 `utils/leetcode_helper.sh``utils/run_tests.sh`
初次使用請先授權腳本:
```
chmod +x utils/leetcode_helper.sh utils/run_tests.sh
```
## 常用操作
- 新增題目自動建立資料夾、README、C#/Go 程式與測試模板)
```
./utils/leetcode_helper.sh problem <題號> <題目名稱-kebab> <難度>
# 範例
./utils/leetcode_helper.sh problem 1 two-sum Easy
./utils/leetcode_helper.sh problem 3000 maximum-area-rectangle Medium
# 顯示說明:
./utils/leetcode_helper.sh --help
```
建立完成後的結構(示意):
```
problems/NNNN-name/
├── README.md
├── csharp/
│ ├── Program.cs
│ └── csharp.csproj
├── go/
│ ├── main.go
│ └── go.mod
└── test/
├── SolutionTests.cs # xUnit 測試
├── TestProject.csproj
├── main_test.go # Go testing
└── edge_cases.md
```
- 建立月度日誌(依模板生成 `logs/YYYY-MM.md`
```
./utils/leetcode_helper.sh log 2025-09
```
- 更新主 README目前顯示題目統計後續可擴充自動彙整
```
./utils/leetcode_helper.sh readme
```
## 執行與測試
- 執行 C# 解法:
```
cd problems/NNNN-name/csharp
dotnet run
```
- 執行 Go 解法:
```
cd problems/NNNN-name/go
go run main.go
```
- 執行該題的測試(同時跑 C# 與 Go
```
./utils/run_tests.sh NNNN-name [all|csharp|go]
# 也可只給題號:
./utils/run_tests.sh 3025
# 僅跑 C# 或 Go
./utils/run_tests.sh 3025 csharp
./utils/run_tests.sh 3025 go
# 顯示說明:
./utils/run_tests.sh --help
# 列出目前可用題目:
./utils/run_tests.sh --list
```
或分別執行:
```
cd problems/NNNN-name/test
dotnet test
go test -v
```
## utils 的用途
`utils/leetcode_helper.sh` 提供三個主要功能,將繁瑣步驟自動化、保持專案一致性;`utils/run_tests.sh` 則統一執行測試。
- problem根據輸入的題號、名稱與難度建立一個完整題目骨架
- 產生題目 `README.md`(含題目資訊、思路、測試與筆記段落)
- 建立 `csharp/``go/` 目錄及基本程式碼
- 建立 `test/` 目錄,內含 xUnit、Go 測試模板(統一用 `utils/run_tests.sh` 執行)
- 初始化 Go module`go.mod`
- readme掃描 `problems/` 題目數量,輸出簡單統計到終端(可再擴充寫回本檔)
- log`templates/logs-template.md.tmpl` 生成月誌雛形,方便每日記錄與月度回顧
`utils/run_tests.sh` 全域測試執行:
- 用法:`./utils/run_tests.sh <problem> [all|csharp|go]`
- <problem> 可為題號(如 `3025`)、資料夾名(如 `3025-find-...`)、或完整路徑(如 `problems/3025-...`
- 其他:`--help` 顯示說明、`--list` 列出可用題目
- 範例:
- `./utils/run_tests.sh 3025`(同時跑 C# 與 Go
- `./utils/run_tests.sh 3025 csharp`(只跑 C#
- `./utils/run_tests.sh --list`
小提醒:腳本內建的模板語言為繁中,可依需求修改 `templates/` 與腳本內容。
## 模板與筆記
- 題目模板:`templates/problem-template.md.tmpl`
- 月誌模板:`templates/logs-template.md.tmpl`
建議每題完成後:
- 更新該題 `README.md` 的「解題思路」「測試案例」「學習筆記」段落
-`logs/YYYY-MM.md` 紀錄當日題目、時間、心得與統計
## Templates 強化(重點)
- **Problem 模板新增**
- 先備條件與限制(輸入範圍、是否需要 in-place/排序)
- 解法比較A/B/C、正確性要點、優缺點
- 乾跑Dry Run步驟示例
- API 設計C#/Go 方法簽名)與常見陷阱清單
- 對拍/隨機測試建議;更完整的邊界清單
- **Logs 模板新增**
- 本月設定(主題/目標/挑戰)與主題覆蓋追蹤
- 連續天數Streak與錯誤類型統計
- 困難案例復盤與下月計畫欄位
## Problem 模板範例節錄3516
```
# [3516] Find Closest Person
## 題目資訊
- 難度: Easy
- 標籤: Math
- 題目連結: https://leetcode.com/problems/find-closest-person/
- 練習日期: 2025-09-04
- 目標複雜度: 時間 O(1), 空間 O(1)
## 先備條件與限制
- 輸入: x, y, z 為整數;值域小;需比較兩者距離
- 回傳: 1/2/0 表示誰先到或同時到
## 解法比較
1. 解法A直接比距離
- 思路: 計算 |x-z| 與 |y-z|,比較大小
- 正確性: 距離等速 → 距離小者先到
- 複雜度: O(1) / O(1)
2. 解法B
## 乾跑
- x=2, y=7, z=4 → |2-4|=2, |7-4|=3 → 回傳 1
## 實作細節與 API 設計
- C#
public int FindClosest(int x, int y, int z) { ... }
- Go
func findClosest(x, y, z int) int { ... }
## 測試案例
- 邊界: 等距回傳0、同點、極小/極大值
```
完整寫法可參考:`problems/3516-find-closest-person/README.md`
## 測試範例(可直接複製改題名)
- xUnitC#
```csharp
using Xunit;
public class SolutionTests {
[Theory]
[InlineData(2, 7, 4, 1)]
[InlineData(2, 5, 6, 2)]
[InlineData(1, 5, 3, 0)]
public void FindClosest_Works(int x, int y, int z, int expected) {
var s = new Solution();
Assert.Equal(expected, s.FindClosest(x, y, z));
}
}
```
- Go testing
```go
package main
import "testing"
func TestFindClosest(t *testing.T) {
tests := []struct{ x, y, z, want int }{
{2, 7, 4, 1},
{2, 5, 6, 2},
{1, 5, 3, 0},
}
for _, tt := range tests {
if got := findClosest(tt.x, tt.y, tt.z); got != tt.want {
t.Fatalf("x=%d y=%d z=%d want=%d got=%d", tt.x, tt.y, tt.z, tt.want, got)
}
}
}
```
## 自訂模板
- 直接編輯:`templates/problem-template.md.tmpl``templates/logs-template.md.tmpl`
- 工具腳本已改為讀取 `templates/` 目錄的檔案生成骨架:
- 問題頁:`templates/problem/README.md.tmpl`
- C#`templates/problem/csharp/*`
- Go`templates/problem/go/*`
- 測試:`templates/problem/test/*`
- 月誌:`templates/logs-template.md.tmpl`
不需修改腳本本身即可客製化模板。
## 工具清單
- `utils/leetcode_helper.sh`: 管理題目與月誌
- 功能:
- `problem <題號> <題目名稱-kebab> <難度>`:建立新題目(產生 `README.md``csharp/``go/``test/` 骨架)
- `log [YYYY-MM]`:建立月度學習日誌(預設本月)
- `readme`:顯示題目數量統計
- `-h|--help`:顯示說明
- 範例:
- `./utils/leetcode_helper.sh problem 3025 find-the-number-of-ways-to-place-people-i Medium`
- `./utils/leetcode_helper.sh log 2025-09`
- `./utils/leetcode_helper.sh --help`
- `utils/run_tests.sh`: 執行指定題目的測試
- 語法:`./utils/run_tests.sh <problem> [all|csharp|go]`
- <problem> 可為:題號(如 `3025`/ 目錄名(如 `3025-find-…`/ 完整路徑(如 `problems/3025-…`
- 參數:`--help` 顯示說明、`--list` 列出現有題目
- 範例:
- `./utils/run_tests.sh 3025`(同時跑 C# 與 Go
- `./utils/run_tests.sh 3025 csharp`(只跑 C#
- `./utils/run_tests.sh --list`
## 未來可擴充方向
- 主 README 自動彙整各題狀態(難度、語言、連結、完成度)
- 加入 CI如 GitHub Actions自動跑各題測試
- 更完整的模板與範例(含 I/O、邊界測資
---
歡迎依個人習慣調整腳本與模板,持續穩定地練習最重要!

78
logs/2025-09.md Normal file
View File

@@ -0,0 +1,78 @@
# 2025-09 學習記錄
## 📅 每日練習記錄
### Week 1
| 日期 | 題目 | 難度 | 語言 | 耗時 | 狀態 | 心得 |
|------|------|------|------|------|------|------|
| 09/01 | Maximum Average Pass Ratio | Medium | C# | 1hr | Done | 第一次用到Priority Queue |
| 09/02 | Find The Number of Ways to Place People I | Medium | C#, go | 0.7hr | Done | 二維點位判斷 |
| 09/03 | Find The Number of Ways to Place People II | Hard | C# | 0.2hr | Done | Same as [#3025] |
| 09/04 | Find Closest Person | Easy | C#, go | 0.1hr | Done | 數學判斷 |
| 09/05 | Minimum Operations to Make the Integer Zero | Medium | C# | 1.5hr | Done | |
### Week 2
| 日期 | 題目 | 難度 | 語言 | 耗時 | 狀態 | 心得 |
|------|------|------|------|------|------|------|
| 09/08 | Convert Integer To The Sum Of Two No Zero Integers | Easy | C# | 0.2hr | Done | |
| 09/11 | Sort Vowels In A String | Medium | C# | 0.2hr | Done | |
| 09/11 | [3227]Vowels Game In A String | Medium | C#, go | 0.1hr | Done | like easy |
### Week 3
| 日期 | 題目 | 難度 | 語言 | 耗時 | 狀態 | 心得 |
|------|------|------|------|------|------|------|
| | | | | | | |
### Week 4
| 日期 | 題目 | 難度 | 語言 | 耗時 | 狀態 | 心得 |
|------|------|------|------|------|------|------|
| 09/22 | [3005]Count Elements With Maximum Frequency | Easy | C# | 0.3hr | Done | Dictionary Mapping |
| 09/23| [0165]Compare Version Numbers | Medium | C# | 0.4hr | Done | String, Two Pointers |
## 📈 本月統計
### 完成情況
- **總練習天數**: 9 天
- **完成題數**: 9題
- **語言分布**: C# 9(題), Go 2(題)
- **難度分布**: Easy 3(題), Medium 5(題), Hard 1(題)
### 時間投入
- **總時間**: 4.5小時
- **平均每題**: 分鐘
- **每日平均**: 分鐘
## 🎯 本月重點學習
### 新掌握的技巧
1. 貪心策略
2. string轉char, char轉string
### 常犯錯誤分析
1.
### 語言學習心得
- **C#**:
- **Go**:
## 🔄 遇到的困難與解決
### 困難1:
- **問題**:
- **解決**:
- **學習**:
## 📝 改進計畫
### 下月目標
1.
### 學習方法調整
1.
## 💡 本月金句
>
---
**總結**:

184
logs/2025-10.md Normal file
View File

@@ -0,0 +1,184 @@
# 2025年8月 學習記錄
## 📅 每日練習記錄
### Week 1 (2025-08-01 ~ 2025-08-07)
| 日期 | 題目 | 難度 | 語言 | 耗時 | 狀態 | 心得 |
|------|------|------|------|------|------|------|
| 08-01 | [1] Two Sum | Easy | C# | 30min | ✅ | 第一題,熟悉環境 |
| 08-02 | [1] Two Sum | Easy | Go | 45min | ✅ | Go語法不熟多花時間 |
| 08-03 | [15] 3Sum | Medium | C# | 90min | ⚠️ | TLE需要最佳化 |
| 08-04 | [15] 3Sum | Medium | C# | 60min | ✅ | 學會雙指針,重要突破! |
| 08-05 | 休息 | - | - | - | - | 週末休息 |
| 08-06 | [11] Container Water | Medium | C# | 45min | ✅ | 雙指針再次應用 |
| 08-07 | 複習筆記 | - | - | 60min | - | 整理本週學習 |
### Week 2 (2025-08-08 ~ 2025-08-14)
| 日期 | 題目 | 難度 | 語言 | 耗時 | 狀態 | 心得 |
|------|------|------|------|------|------|------|
| 08-08 | [3] Longest Substring | Medium | C# | 120min | 🔄 | 滑動窗口概念很重要 |
| 08-09 | [3] Longest Substring | Medium | Go | 90min | ✅ | Go實作更簡潔 |
| ... | ... | ... | ... | ... | ... | ... |
## 📈 本月統計
### 完成情況
- **總練習天數**: 20天
- **完成題數**: 8題
- **語言分布**: C# (8題), Go (5題)
- **難度分布**: Easy (5題), Medium (3題), Hard (0題)
### 時間投入
- **總時間**: 18小時
- **平均每題**: 135分鐘
- **每日平均**: 54分鐘
### 正確率
- **一次通過**: 3題 (37.5%)
- **二次通過**: 4題 (50%)
- **多次調整**: 1題 (12.5%)
## 🎯 本月重點學習
### 新掌握的技巧
1. **雙指針技巧** - 在 3Sum 和 Container Water 中應用
2. **Hash Table 應用** - Two Sum 的經典解法
3. **滑動窗口初步** - Longest Substring 問題
### 常犯錯誤分析
1. **邊界條件** - 忘記檢查空陣列 (犯錯 3次)
2. **索引越界** - 雙指針移動時的邊界 (犯錯 2次)
3. **時間複雜度** - 第一次嘗試常用暴力解法
### 語言學習心得
- **C#**: 語法熟悉LINQ很好用但要注意效能
- **Go**: 簡潔但型別嚴格slice操作需多練習
## 🔄 遇到的困難與解決
### 困難1: 思路卡住
- **問題**: 3Sum 一開始完全沒思路
- **解決**: 先研究 Two Sum再擴展到三個數字
- **學習**: 從簡單問題推廣到複雜問題
### 困難2: Go語法不熟
- **問題**: Go的slice、map語法經常出錯
- **解決**: 整理了Go語法筆記多做練習
- **學習**: 不要急著解題,先把工具準備好
## 📝 改進計畫
### 9月目標
1. **提升難度**: 嘗試3-5題Hard題目
2. **新主題**: 開始學習動態規劃
3. **效率提升**: 目標平均解題時間降到90分鐘
4. **語言平衡**: Go語言題數追上C#
### 學習方法調整
1. **題目分析時間**: 每題先花15分鐘分析再開始寫程式
2. **複習機制**: 每週末複習本週所有題目
3. **筆記改善**: 加強解題思路的記錄
## 💡 本月金句
> "演算法不是背出來的,是理解出來的" - 在第15題3Sum卡住兩天後的感悟
---
**總結**: 八月是很好的開始,從完全新手到能獨立解決中等題目。九月要持續挑戰自己!
# YYYY年M月 學習記錄
## 本月設定(目標與主題)
- **主題**:例如 雙指針 / 滑動視窗 / DP / 圖論
- **目標題數**X 題Easy Y / Medium Z / Hard W
- **投入時間**:每日 ≥ N 分鐘;每週 ≥ M 小時
- **挑戰**:至少完成 Hard ≥ H 題;每週寫 1 篇總結
## 📅 每日練習記錄
### Week 1 (YYYY-MM-DD ~ YYYY-MM-DD)
| 日期 | 題目 | 難度 | 語言 | 耗時 | 狀態 | 心得 |
|------|------|------|------|------|------|------|
| | | | | | | |
### Week 2 (YYYY-MM-DD ~ YYYY-MM-DD)
| 日期 | 題目 | 難度 | 語言 | 耗時 | 狀態 | 心得 |
|------|------|------|------|------|------|------|
| | | | | | | |
### Week 3 (YYYY-MM-DD ~ YYYY-MM-DD)
| 日期 | 題目 | 難度 | 語言 | 耗時 | 狀態 | 心得 |
|------|------|------|------|------|------|------|
| | | | | | | |
### Week 4 (YYYY-MM-DD ~ YYYY-MM-DD)
| 日期 | 題目 | 難度 | 語言 | 耗時 | 狀態 | 心得 |
|------|------|------|------|------|------|------|
| | | | | | | |
## 🧭 主題覆蓋追蹤(勾選)
- [ ] 陣列/字串Two Pointers / Sliding Window
- [ ] 資料結構Stack/Queue/Heap/Set/Map
- [ ] 排序與搜尋Sorting / Binary Search
- [ ] 數學與位運算Math / Bit
- [ ] 動態規劃DP
- [ ] 圖論BFS/DFS/最短路/拓撲)
- [ ]BST/遍歷/序列化)
## 📈 本月統計
### 完成情況
- **練習天數**: 天
- **完成題數**: 題Easy / Medium / Hard
- **語言分布**: C# (題), Go (題)
- **連續天數Streak**: 天;本月斷點:第 天
### 時間投入
- **總時間**: 小時
- **平均每題**: 分鐘
- **每日平均**: 分鐘
### 正確率 / 嘗試次數
- **一次通過**: 題
- **二次通過**: 題
- **多次調整**: 題(記錄主因:邊界/複雜度/實作)
## 🎯 本月重點學習
### 新掌握的技巧(至少 3 條)
1.
2.
3.
### 常見錯誤與對策
1. 錯誤:;對策:
2. 錯誤:;對策:
3. 錯誤:;對策:
### 語言心得(實作層面)
- **C#**LINQ/Span/效能注意點/測試習慣
- **Go**slice/map/指標/錯誤處理/benchmark 習慣
## 🔄 困難案例復盤
### 案例1題號/主題
- 問題:
- 嘗試:
- 解決:
- 學習:
### 案例2題號/主題
- 問題:
- 嘗試:
- 解決:
- 學習:
## 📝 下月計畫
- **目標題數**
- **重點主題**
- **練習節奏**
- **要避免的坑**
## 💡 本月金句
>
---
**總結**:本月最大收穫是 ______,接下來專注 ______

99
logs/2025-11.md Normal file
View File

@@ -0,0 +1,99 @@
# YYYY年M月 學習記錄
## 本月設定(目標與主題)
- 主題:雙指針 / 滑動視窗 / DP / 圖論(自訂)
- 目標題數X 題Easy Y / Medium Z / Hard W
- 投入時間:每日 ≥ N 分鐘;每週 ≥ M 小時
- 挑戰:至少完成 Hard ≥ H 題;每週寫 1 篇總結
## 📅 每日練習記錄
### Week 1 (YYYY-MM-DD ~ YYYY-MM-DD)
| 日期 | 題目 | 難度 | 語言 | 耗時 | 狀態 | 心得 |
|------|------|------|------|------|------|------|
| | | | | | | |
### Week 2 (YYYY-MM-DD ~ YYYY-MM-DD)
| 日期 | 題目 | 難度 | 語言 | 耗時 | 狀態 | 心得 |
|------|------|------|------|------|------|------|
| | | | | | | |
### Week 3 (YYYY-MM-DD ~ YYYY-MM-DD)
| 日期 | 題目 | 難度 | 語言 | 耗時 | 狀態 | 心得 |
|------|------|------|------|------|------|------|
| | | | | | | |
### Week 4 (YYYY-MM-DD ~ YYYY-MM-DD)
| 日期 | 題目 | 難度 | 語言 | 耗時 | 狀態 | 心得 |
|------|------|------|------|------|------|------|
| | | | | | | |
## 🧭 主題覆蓋追蹤(勾選)
- [ ] 陣列/字串Two Pointers / Sliding Window
- [ ] 資料結構Stack/Queue/Heap/Set/Map
- [ ] 排序與搜尋Sorting / Binary Search
- [ ] 數學與位運算Math / Bit
- [ ] 動態規劃DP
- [ ] 圖論BFS/DFS/最短路/拓撲)
- [ ]BST/遍歷/序列化)
## 📈 本月統計
### 完成情況
- 練習天數:天
- 完成題數Easy / Medium / Hard
- 語言分布C# (題), Go (題)
- 連續天數Streak本月斷點第 天
### 時間投入
- 總時間:小時
- 平均每題:分鐘
- 每日平均:分鐘
### 正確率 / 嘗試次數
- 一次通過:題
- 二次通過:題
- 多次調整:題(主因:邊界/複雜度/實作)
## 🎯 本月重點學習
### 新掌握的技巧(至少 3 條)
1.
2.
3.
### 常見錯誤與對策
1. 錯誤:;對策:
2. 錯誤:;對策:
3. 錯誤:;對策:
### 語言心得(實作層面)
- C#LINQ/Span/效能注意點/測試習慣
- Goslice/map/指標/錯誤處理/benchmark 習慣
## 🔄 困難案例復盤
### 案例1題號/主題
- 問題:
- 嘗試:
- 解決:
- 學習:
### 案例2題號/主題
- 問題:
- 嘗試:
- 解決:
- 學習:
## 📝 下月計畫
- 目標題數:
- 重點主題:
- 練習節奏:
- 要避免的坑:
## 💡 本月金句
>
---
**總結**:本月最大收穫是 ______,接下來專注 ______

99
logs/2025-12.md Normal file
View File

@@ -0,0 +1,99 @@
# YYYY年M月 學習記錄
## 本月設定(目標與主題)
- 主題:雙指針 / 滑動視窗 / DP / 圖論(自訂)
- 目標題數X 題Easy Y / Medium Z / Hard W
- 投入時間:每日 ≥ N 分鐘;每週 ≥ M 小時
- 挑戰:至少完成 Hard ≥ H 題;每週寫 1 篇總結
## 📅 每日練習記錄
### Week 1 (YYYY-MM-DD ~ YYYY-MM-DD)
| 日期 | 題目 | 難度 | 語言 | 耗時 | 狀態 | 心得 |
|------|------|------|------|------|------|------|
| | | | | | | |
### Week 2 (YYYY-MM-DD ~ YYYY-MM-DD)
| 日期 | 題目 | 難度 | 語言 | 耗時 | 狀態 | 心得 |
|------|------|------|------|------|------|------|
| | | | | | | |
### Week 3 (YYYY-MM-DD ~ YYYY-MM-DD)
| 日期 | 題目 | 難度 | 語言 | 耗時 | 狀態 | 心得 |
|------|------|------|------|------|------|------|
| | | | | | | |
### Week 4 (YYYY-MM-DD ~ YYYY-MM-DD)
| 日期 | 題目 | 難度 | 語言 | 耗時 | 狀態 | 心得 |
|------|------|------|------|------|------|------|
| | | | | | | |
## 🧭 主題覆蓋追蹤(勾選)
- [ ] 陣列/字串Two Pointers / Sliding Window
- [ ] 資料結構Stack/Queue/Heap/Set/Map
- [ ] 排序與搜尋Sorting / Binary Search
- [ ] 數學與位運算Math / Bit
- [ ] 動態規劃DP
- [ ] 圖論BFS/DFS/最短路/拓撲)
- [ ]BST/遍歷/序列化)
## 📈 本月統計
### 完成情況
- 練習天數:天
- 完成題數Easy / Medium / Hard
- 語言分布C# (題), Go (題)
- 連續天數Streak本月斷點第 天
### 時間投入
- 總時間:小時
- 平均每題:分鐘
- 每日平均:分鐘
### 正確率 / 嘗試次數
- 一次通過:題
- 二次通過:題
- 多次調整:題(主因:邊界/複雜度/實作)
## 🎯 本月重點學習
### 新掌握的技巧(至少 3 條)
1.
2.
3.
### 常見錯誤與對策
1. 錯誤:;對策:
2. 錯誤:;對策:
3. 錯誤:;對策:
### 語言心得(實作層面)
- C#LINQ/Span/效能注意點/測試習慣
- Goslice/map/指標/錯誤處理/benchmark 習慣
## 🔄 困難案例復盤
### 案例1題號/主題
- 問題:
- 嘗試:
- 解決:
- 學習:
### 案例2題號/主題
- 問題:
- 嘗試:
- 解決:
- 學習:
## 📝 下月計畫
- 目標題數:
- 重點主題:
- 練習節奏:
- 要避免的坑:
## 💡 本月金句
>
---
**總結**:本月最大收穫是 ______,接下來專注 ______

22
makefile Normal file
View File

@@ -0,0 +1,22 @@
# Makefile - 安裝環境工具
.PHONY: all update upgrade install setup check
all: setup
update:
sudo apt update
upgrade:
sudo apt upgrade -y
install:
sudo apt install -y dotnet-sdk-8.0 golang-go
setup: update upgrade install check
@echo "✅ 開發環境安裝完成!"
check:
@echo "=== 檢查安裝結果 ==="
@dotnet --version || echo "⚠️ dotnet 未安裝成功"
@go version || echo "⚠️ go 未安裝成功"

View File

@@ -0,0 +1,85 @@
# [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 與缺段情況,適合練習字串雙指標與記憶體優化技巧。

View File

@@ -0,0 +1,144 @@
// 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);
}
}
}

View File

@@ -0,0 +1,9 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
</Project>

View File

@@ -0,0 +1,56 @@
// LeetCode 165: Compare Version Numbers 單元測試xUnit
using System.Linq;
using Xunit;
public class SolutionTests {
private readonly Solution _s = new Solution();
[Theory]
[InlineData("1.01", "1.001", 0)]
[InlineData("1.0", "1.0.0", 0)]
[InlineData("1.0.0.0", "1", 0)]
[InlineData("0.1", "1.1", -1)]
[InlineData("1.0.1", "1", 1)]
[InlineData("7.5.2.4", "7.5.3", -1)]
public void CompareVersion_ReturnsExpectedResult(string version1, string version2, int expected) {
var actual = _s.CompareVersion(version1, version2);
Assert.Equal(expected, actual);
}
[Theory]
[InlineData("1.0.1", "1")]
[InlineData("3.0.0", "2.9.9.9")]
[InlineData("10.4", "10.3.9")]
public void CompareVersion_IsAntiSymmetric(string left, string right) {
var forward = _s.CompareVersion(left, right);
var backward = _s.CompareVersion(right, left);
Assert.Equal(1, forward);
Assert.Equal(-1, backward);
}
[Theory]
[InlineData("", "", 0)]
[InlineData("", "0", 0)]
[InlineData("0.0.0", "", 0)]
[InlineData("000", "0", 0)]
[InlineData("2147483647", "2147483646", 1)]
[InlineData("2147483646", "2147483647", -1)]
public void CompareVersion_HandlesBoundaryInputs(string version1, string version2, int expected) {
var actual = _s.CompareVersion(version1, version2);
Assert.Equal(expected, actual);
}
[Fact]
public void CompareVersion_LongSequencesDifferAtEnd() {
var left = string.Join('.', Enumerable.Repeat("0", 199).Append("1"));
var right = string.Join('.', Enumerable.Repeat("0", 200));
var result = _s.CompareVersion(left, right);
Assert.Equal(1, result);
}
}

View File

@@ -0,0 +1,19 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
<IsPackable>false</IsPackable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.1.0" />
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="../csharp/csharp.csproj" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,29 @@
# 邊界情況清單165 Compare Version Numbers
## 需要測試的邊界
- [x] 空輸入 / 單一元素:`""``"0"`
- [x] 重複元素 / 全相同:`"1.0.0"` vs `"1"`
- [x] 極值(最小/最大):`"2147483647"` vs `"2147483646"`
- [x] 含負數 / 0 / 大數:題目無負數,已覆蓋多零與大修訂號
- [x] 大資料量接近上限200 段版本字串
## 額外案例
### 案例 1
- 輸入:`version1 = "", version2 = "0"`
- 預期:`0`
- 說明:空字串缺少所有段,視為全 0
### 案例 2
- 輸入:`version1 = "2147483647", version2 = "2147483646"`
- 預期:`1`
- 說明:驗證最大 32-bit 整數段處理
### 案例 3
- 輸入:`version1 = "0.0.0", version2 = "0"`
- 預期:`0`
- 說明:多段全 0 與單段 0 視為相同
### 案例 4
- 輸入:`version1 = string.Join(".", Enumerable.Repeat("0", 199)) + ".1"`, `version2 = string.Join(".", Enumerable.Repeat("0", 200))`
- 預期:`1`
- 說明:長度 200 的版本字串,在最後一段差異才分勝負

View File

@@ -0,0 +1,30 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.5.2.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "csharp", "csharp\csharp.csproj", "{CF022C7B-CAF3-706D-67E1-FB93518229B7}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestProject", "test\TestProject.csproj", "{C670389A-9CE7-B456-51E5-A79D56E199CF}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{CF022C7B-CAF3-706D-67E1-FB93518229B7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{CF022C7B-CAF3-706D-67E1-FB93518229B7}.Debug|Any CPU.Build.0 = Debug|Any CPU
{CF022C7B-CAF3-706D-67E1-FB93518229B7}.Release|Any CPU.ActiveCfg = Release|Any CPU
{CF022C7B-CAF3-706D-67E1-FB93518229B7}.Release|Any CPU.Build.0 = Release|Any CPU
{C670389A-9CE7-B456-51E5-A79D56E199CF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C670389A-9CE7-B456-51E5-A79D56E199CF}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C670389A-9CE7-B456-51E5-A79D56E199CF}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C670389A-9CE7-B456-51E5-A79D56E199CF}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {C5790EDA-C36F-4FC3-877D-C7E20837E160}
EndGlobalSection
EndGlobal

View File

@@ -0,0 +1,80 @@
# [166] Fraction To Recurring Decimal
## 題目資訊
- **難度**: Medium
- **標籤**: Hash Table, Math, Simulation
- **題目連結**: https://leetcode.com/problems/fraction-to-recurring-decimal/
- **練習日期**: 2025-09-24
- **目標複雜度**: 時間 O(L)、空間 O(L)L 為輸出字串長度,最多 10^4
## 題目描述
Given two integers representing the `numerator` and `denominator` of a fraction, return *the fraction* in string format.
If the fractional part is repeating, enclose the repeating part in parentheses.
If multiple answers are possible, return **any of them**.
It is **guaranteed** that the length of the answer string is less than `10^4` for all the given inputs.
## 先備條件與限制
- 輸入限制:`-2^31 <= numerator, denominator <= 2^31 - 1`,且 denominator ≠ 0
- 回傳/輸出格式:回傳十進位字串;有限小數直接輸出,小數有循環時用括號標記循環段
- 其他:允許使用 64-bit 以避免在取絕對值時溢位
## 解題思路
### 初步分析
- 類型:數學 / 模擬 / 哈希
- 關鍵觀察:整數除法僅靠餘數決定下一個小數位;相同餘數必定導致循環,位置可透過哈希表還原
- 複雜度目標理由:每個餘數最多處理一次,因此時間與空間成正比於輸出長度 L
### 解法比較
1. 解法A餘數位置哈希
- 思路:先處理正負號並計算整數部分;對小數部分反覆以 10 乘上餘數取商,並在 map 中紀錄餘數首次出現的索引,一旦重複即可插入括號
- 正確性:每個可能的餘數介於 0 與 |denominator|-1重複時即代表循環節開始未重複則最後餘數為 0有限小數
- 複雜度:時間 O(L) / 空間 O(L)
## 實作細節
- 先處理 `numerator == 0` 直接回傳 "0"
- 判斷結果正負號,使用 `long`/`long long` 取絕對值避免 `INT_MIN` 無法轉正的問題
- `integer_part = abs_num / abs_den` 直接加入結果,小數部分以餘數 `remainder = abs_num % abs_den` 開始
- 使用字典 `remainder -> index` 紀錄餘數在結果字串中的位置;迴圈內:餘數乘 10取下一位商並更新餘數
- 若餘數為 0表示小數結束不需括號若餘數再度出現在對應索引插入 `(`,在結尾加 `)`
## 常見陷阱
- 處理負數:符號只出現一次,判斷後用 64-bit 絕對值繼續運算避免 `--6...` 之類錯誤
- `INT_MIN / -1` 可能溢位:需先轉成 64-bit 再做除法與取餘數
- 餘數 map 要記錄的是「餘數出現時的輸出索引」,找到重複時要在該位置插入 `(`
- 每回合先檢查餘數是否重複再乘 10避免多插一位或落掉循環起點
- `numerator` 為 0 時無小數部分,直接回傳 "0"
## 測試案例
### 範例輸入輸出
```
Input: numerator = 4, denominator = 333
Output: "0.(012)"
```
### 邊界清單
- `numerator = 1, denominator = 2``"0.5"`(有限小數)
- `numerator = 1, denominator = 6``"0.1(6)"`(循環節不從第一位開始)
- `numerator = -50, denominator = 8``"-6.25"`(負數與有限小數)
- `numerator = 0, denominator = 5``"0"`(整數結果)
- `numerator = 1, denominator = 7``"0.(142857)"`(較長的循環節)
## 複雜度分析
- 最壞:時間 O(L)、空間 O(L)
- L 為輸出字串長度,等同於需要處理的餘數數量上限(題目保證 < 10^4
## 相關題目 / Follow-up
- 與任一進位制的循環小數檢測 base conversion類似可類比餘數循環檢測技巧
## 學習筆記
- 今天學到餘數 索引的哈希表能精準標記循環段搭配 `StringBuilder.Insert` 可快速加括號
- 卡住與修正`int.MinValue` 轉正時會拋例外改用 `long` 做完整流程含乘 10 與取餘就穩定
- 另外注意符號在輸出開頭先處理整數和小數部分都用正數運算可避免重複符號
- 待優化可以先行預估非循環長度以減少插入成本但對此題影響不大
---
**總結**這題的核心在於以餘數哈希判斷循環節適合練習小數表示與溢位處理

View File

@@ -0,0 +1,68 @@
// LeetCode 166: Fraction To Recurring Decimal
// 難度: Medium
// 日期: 2025-09-24
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
public class Solution
{
public string FractionToDecimal(int numerator, int denominator)
{
if (numerator == 0) return "0";
long num = numerator;
long den = denominator;
StringBuilder result = new StringBuilder();
bool isNegative = (num < 0) ^ (den < 0);
if (isNegative) result.Append('-');
num = Math.Abs(num);
den = Math.Abs(den);
long integerPart = num / den;
result.Append(integerPart);
long remainder = num % den;
if (remainder == 0) return result.ToString();
result.Append('.');
result.Append(CalculateDecimalPart(remainder, den));
return result.ToString();
}
private string CalculateDecimalPart(long remainder, long denominator)
{
StringBuilder decimalBuilder = new StringBuilder();
Dictionary<long, int> remainderMap = new Dictionary<long, int>();
while (remainder != 0)
{
if (remainderMap.TryGetValue(remainder, out int repeatIndex))
{
decimalBuilder.Insert(repeatIndex, '(');
decimalBuilder.Append(')');
break;
}
remainderMap[remainder] = decimalBuilder.Length;
remainder *= 10;
long digit = remainder / denominator;
decimalBuilder.Append(digit);
remainder %= denominator;
}
return decimalBuilder.ToString();
}
}
public class Program {
public static void Main() {
var s = new Solution();
}
}

View File

@@ -0,0 +1,9 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
</Project>

View File

@@ -0,0 +1,3 @@
module leetcode-166
go 1.18

View File

@@ -0,0 +1,18 @@
// LeetCode 166: Fraction To Recurring Decimal
// 難度: Medium
// 日期: 2025-09-24
package main
import "fmt"
// TODO: 根據題意調整簽名
func solve(nums []int) int {
return 0
}
func main() {
fmt.Printf("Hello LeetCode 166!\n")
// TODO: 可加入簡單測試
}

View File

@@ -0,0 +1,27 @@
// LeetCode 166 單元測試xUnit
using Xunit;
public class SolutionTests {
private readonly Solution _s = new Solution();
[Theory]
[InlineData(4, 333, "0.(012)")]
[InlineData(1, 2, "0.5")]
[InlineData(1, 6, "0.1(6)")]
[InlineData(-50, 8, "-6.25")]
[InlineData(0, 5, "0")]
[InlineData(1, 7, "0.(142857)")]
public void FractionToDecimal_BasicAndRepeatingScenarios(int numerator, int denominator, string expected) {
var actual = _s.FractionToDecimal(numerator, denominator);
Assert.Equal(expected, actual);
}
[Fact]
public void FractionToDecimal_DenominatorOne_ReturnsIntegerString() {
var actual = _s.FractionToDecimal(2, 1);
Assert.Equal("2", actual);
}
}

View File

@@ -0,0 +1,19 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
<IsPackable>false</IsPackable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.1.0" />
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="../csharp/csharp.csproj" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,20 @@
# 邊界情況清單166 Fraction To Recurring Decimal
## 需要測試的邊界
- [ ] 空輸入 / 單一元素
- [ ] 重複元素 / 全相同
- [ ] 極值(最小/最大)
- [ ] 含負數 / 0 / 大數
- [ ] 大資料量(接近上限)
## 額外案例
### 案例 1
- 輸入:
- 預期:
- 說明:
### 案例 2
- 輸入:
- 預期:
- 說明:

View File

@@ -0,0 +1,12 @@
// LeetCode 166 單元測試Go testing
package main
import "testing"
func TestExample(t *testing.T) {
// TODO: input := []int{}
// got := solve(input)
// want := 0
// if got != want { t.Fatalf("want %v got %v", want, got) }
}

View File

@@ -0,0 +1,65 @@
# [1317] Convert Integer To The Sum Of Two No Zero Integers
## 題目資訊
- **難度**: Easy
- **標籤**: Math
- **題目連結**: [LeetCode](https://leetcode.com/problems/convert-integer-to-the-sum-of-two-no-zero-integers/)
- **練習日期**: 2025-09-08
## 題目描述
No-Zero integer is a positive integer that does not contain any `0` in its decimal representation.
Given an integer `n`, return a list of two integers `[a, b]` where:
- `a` and `b` are No-Zero integers.
- `a + b = n`
The test cases are generated so that there is at least one valid solution. If there are many valid solutions, you can return any of them.
## 解題思路
### 初步分析
- 這題主要考察什麼概念?
迴圈遍歷 + 數字位數檢查
- 有什麼關鍵限制條件?
1. 兩個數都必須是正整數
2. 兩個數的十進制表示都不能包含數字 0
3. 兩個數相加必須等於 n
- 預期時間/空間複雜度?
### 解法概述
**解法**:
- 思路:
1. 從 i = 1 開始遍歷到 n-1
2. 對每個 i檢查 i 和 (n-i) 是否都不包含數字 0
3. 找到第一個滿足條件的組合就返回
- 時間複雜度O(n)
- 空間複雜度O(1)
## 測試案例
### 範例輸入輸出
```
Input: n = 2
Output: [1,1]
Explanation: Let a = 1 and b = 1.
Both a and b are no-zero integers, and a + b = 2 = n.
```
### 邊界情況
2 <= n <= 10^4
## 學習筆記
### 今天學到什麼?
-
### 遇到的困難
-
### 改善方向
-
### 相關題目
---
**總結**: 這題的核心概念是...,適合練習...技巧。

View File

@@ -0,0 +1,52 @@
// LeetCode 1317: Convert Integer To The Sum Of Two No Zero Integers
// 難度: Easy
// 日期: 2025-09-08
using System;
using System.Collections.Generic;
using System.Linq;
public class Solution
{
public int[] GetNoZeroIntegers(int n)
{
for (var i = 1; i < n; i++)
{
if (CheckIntegersWithNoZero(i) && CheckIntegersWithNoZero(n - i))
{
return new int[]{i, n - i};
}
}
return new int[]{};
}
private bool CheckIntegersWithNoZero(int n)
{
while (n > 0)
{
if (n % 10 == 0)
{
return false;
}
n /= 10;
}
return true;
}
}
public class Program {
public static void Main() {
var Solution = new Solution();
TestCase1(Solution);
// TestCase2();
}
static void TestCase1(Solution Solution) {
// Input:
var input = 1010;
// Expected: [11, 999]
int[] result = Solution.GetNoZeroIntegers(input);
// Actual:
Console.WriteLine($"Test 1: {result[0]}, {result[1]}");
}
}

View File

@@ -0,0 +1,75 @@
# [1792] Maximum Average Pass Ratio
## 題目資訊
- **難度**: Medium
- **標籤**: Array, Greedy, Heap(Priority Queue)
- **題目連結**: [LeetCode](https://leetcode.com/problems/maximum-average-pass-ratio/)
- **練習日期**: 2025-09-01
## 題目描述
There is a school that has classes of students and each class will be having a final exam. You are given a 2D integer array `classes`, where `classes[i] = [passi, totali]`. You know beforehand that in the `ith` class, there are `totali` total students, but only `passi` number of students will pass the exam.
You are also given an integer `extraStudents`. There are another `extraStudents` brilliant students that are **guaranteed** to pass the exam of any class they are assigned to. You want to assign each of the `extraStudents` students to a class in a way that **maximizes** the **average** pass ratio across **all** the classes.
The **pass ratio** of a class is equal to the number of students of the class that will pass the exam divided by the total number of students of the class. The **average pass ratio** is the sum of pass ratios of all the classes divided by the number of the classes.
Return the *maximum* possible average pass ratio after assigning the `extraStudents` students. Answers within `10^-5` of the actual answer will be accepted.
## 解題思路
### 初步分析
- 這題主要考察什麼概念?
- 貪心算法,找出每次分配學生,通過率可以提升至最高
- Pass Ratio = pass / total
- Average Pass Ratio = sum of pass ration / number of class
### 解法概述
1. **暴力解法**:
- 思路:
- 每次分配一個學生看哪個班級提升率會最高
- leetcode 這邊會 time limit exceeded
- 時間複雜度O(N^2)
- 空間複雜度O(N)
2. **最佳解法**:
- 思路:
- Priority Queue(Max Heap) 直接找gain最大的
- 時間複雜度O(log N)
- 空間複雜度O(N)
## 測試案例
### 範例輸入輸出
```
Input: classes = [[1,2],[3,5],[2,2]], extraStudents = 2
Output: 0.78333
Explanation: You can assign the two extra students to the first class. The average pass ratio will be equal to (3/4 + 3/5 + 2/2) / 3 = 0.78333.
```
### 邊界情況
- 1 <= classes.length <= 10^5
- classes[i].length == 2
- 1 <= passi <= totali <= 10^5
- 1 <= extraStudents <= 10^5
## 學習筆記
### 今天學到什麼?
- 第一次使用 Priority Queue
- 第一次使用 Unit Test
### 遇到的困難
- 可能要再了解 Priority Queue 更多實際用途
### 改善方向
-
### 相關題目
- [#1627](https://leetcode.com/problems/graph-connectivity-with-threshold/description/) Graph Connectivity With Threshold
- [#1728](https://leetcode.com/problems/cat-and-mouse-ii/description/) Cat and Mouse II
- [#3440](https://leetcode.com/problems/reschedule-meetings-for-maximum-free-time-ii/description/) Reschedule Meetings for Maximum Free Time II
---
**總結**:
1. 貪心策略,每次都選擇當下收益最大解
2. 練習使用Priority Queue 快速找到最大收益

View File

@@ -0,0 +1,187 @@
// LeetCode 1792: Maximum Average Pass Ratio
// 難度: Medium
// 日期: 2025-09-01
using System;
using System.Collections.Generic;
using System.Linq;
public class Solution
{
public double MaxAverageRatio(int[][] classes, int extraStudents)
{
// use priority queue
var pq = new PriorityQueue<ClassInfo, double>();
// 初始化:將所有班級加入優先佇列
for (int i = 0; i < classes.Length; i++)
{
int pass = classes[i][0];
int total = classes[i][1];
double gain = CalculateGain(pass, total);
pq.Enqueue(new ClassInfo(pass, total), -gain);
}
for (int i = 0; i < extraStudents; i++)
{
var classInfo = pq.Dequeue();
classInfo.Pass++;
classInfo.Total++;
double newGain = CalculateGain(classInfo.Pass, classInfo.Total);
pq.Enqueue(classInfo, -newGain);
}
double totalRatio = 0;
while (pq.Count > 0)
{
var classInfo = pq.Dequeue();
totalRatio += (double)classInfo.Pass / classInfo.Total;
}
return totalRatio / classes.Length;
}
public double MaxAverageRatioByBruteForce(int[][] classes, int extraStudents)
{
var n = classes.Length;
var pass = new int[n];
var total = new int[n];
for (var i = 0; i < n; i++)
{
pass[i] = classes[i][0];
total[i] = classes[i][1];
}
for (int student = 0; student < extraStudents; student++)
{
int bestClass = -1;
double maxInprovement = 0;
for (int i = 0; i < n; i++)
{
double currentAvg = CalculateAvergaeRatio(pass, total);
pass[i]++;
total[i]++;
double newAvg = CalculateAvergaeRatio(pass, total);
double improvement = newAvg - currentAvg;
pass[i]--;
total[i]--;
if (improvement > maxInprovement)
{
maxInprovement = improvement;
bestClass = i;
}
}
if (bestClass != -1)
{
pass[bestClass]++;
total[bestClass]++;
}
}
return CalculateAvergaeRatio(pass, total);
}
private double CalculateGain(int pass, int total)
{
// 計算提升率
return (double)(pass + 1) / (total + 1) - (double)pass / total;
}
private double CalculateAvergaeRatio(int[] pass, int[] total)
{
double sum = 0;
for (var i = 0; i < pass.Length; i++)
{
sum += (double)pass[i] / total[i];
}
return sum / pass.Length;
}
}
public class ClassInfo
{
public int Pass { get; set; }
public int Total { get; set; }
public ClassInfo(int pass, int total)
{
Pass = pass;
Total = total;
}
}
// 測試程式
public class Program
{
public static void Main()
{
Solution solution = new Solution();
// TestCase
TestCase1(solution);
TestCase2(solution);
}
static void TestCase1(Solution solution)
{
// Input:
int[][] classes = new int[][]
{
new int[] {1, 2},
new int[] {3, 5},
new int[] {2, 2}
};
int extraStudents = 2;
Console.WriteLine("Test 1: ");
Console.WriteLine($"classes: [{string.Join("], [", classes.Select(c => string.Join(", ", c)))}]");
Console.WriteLine($"extraStudents: {extraStudents}");
// Expected:
Console.WriteLine("Expect: ");
Console.WriteLine($"output: 0.78333");
// Actual:
Console.WriteLine("Actual: ");
Console.WriteLine($"Brute Force: {solution.MaxAverageRatioByBruteForce(classes, extraStudents):F6}");
Console.WriteLine($"Priority Queue: {solution.MaxAverageRatio(classes, extraStudents):F6}");
}
static void TestCase2(Solution solution)
{
// Input:
int[][] classes = new int[][]
{
new int[] {2, 4},
new int[] {3, 9},
new int[] {4, 5},
new int[] {2, 10}
};
int extraStudents = 4;
Console.WriteLine("Test 2: ");
Console.WriteLine($"classes: [{string.Join("], [", classes.Select(c => string.Join(", ", c)))}]");
Console.WriteLine($"extraStudents: {extraStudents}");
// Expected:
Console.WriteLine("Expect: ");
Console.WriteLine($"output: 0.53485");
// Actual:
Console.WriteLine("Actual: ");
Console.WriteLine($"Brute Force: {solution.MaxAverageRatioByBruteForce(classes, extraStudents):F6}");
Console.WriteLine($"Priority Queue: {solution.MaxAverageRatio(classes, extraStudents):F6}");
}
}

View File

@@ -0,0 +1,176 @@
// LeetCode 1792 單元測試
// 使用 xUnit 框架
using Xunit;
using System;
using System.Collections.Generic;
public class SolutionTests
{
private readonly Solution _solution;
private const double TOLERANCE = 0.00001;
public SolutionTests()
{
_solution = new Solution();
}
#region Basic Test
[Fact]
public void TestCase1()
{
// Arrange
int[][] classes = new int[][]
{
new int[] {1, 2},
new int[] {3, 5},
new int[] {2, 2}
};
int extraStudents = 2;
double expected = 0.78333;
// Act
var result = _solution.MaxAverageRatio(classes, extraStudents);
// Assert
Assert.True(Math.Abs(result - expected) < TOLERANCE,
$"Expected: {expected}, Actual: {result}");
}
[Fact]
public void TestCase2()
{
// Arrange
int[][] classes = new int[][]
{
new int[] {2, 4}, // 通過率: 2/4 = 0.5
new int[] {3, 9}, // 通過率: 3/9 = 0.333...
new int[] {4, 5}, // 通過率: 4/5 = 0.8
new int[] {2, 10} // 通過率: 2/10 = 0.2
};
int extraStudents = 4;
double expected = 0.53485;
// Act
var result = _solution.MaxAverageRatio(classes, extraStudents);
// Assert
Assert.True(Math.Abs(result - expected) < TOLERANCE,
$"Expected: {expected}, Actual: {result}");
}
[Fact]
public void TestBruteForceVsPriorityQueue()
{
// Arrange
int[][] classes = new int[][]
{
new int[] {1, 3},
new int[] {2, 4},
new int[] {1, 5}
};
int extraStudents = 3;
// Act
var resultBruteForce = _solution.MaxAverageRatioByBruteForce(classes, extraStudents);
var resultPriorityQueue = _solution.MaxAverageRatio(classes, extraStudents);
// Assert
Assert.True(Math.Abs(resultBruteForce - resultPriorityQueue) < TOLERANCE,
$"Brute Force: {resultBruteForce}, Priority Queue: {resultPriorityQueue}");
}
#endregion
#region Edge Test
[Fact]
public void TestEdgeCases_MinClassesLength_OneClass()
{
// Arrange
int[][] classes = new int[][]
{
new int[] {50, 100}
};
int extraStudents = 10;
double expected = 60.0 / 110.0;
// Act
var result = _solution.MaxAverageRatio(classes, extraStudents);
// Assert
Assert.True(result >= 0 && result <= 1,
$"Result should be between 0 and 1, got: {result}");
Assert.True(Math.Abs(result - expected) < TOLERANCE,
$"Expected: {expected}, Actual: {result}");
}
[Fact]
public void TestEdgeCases_LargeClassesLength()
{
// Arrange
const int numClasses = 1000;
var classes = new int[numClasses][];
var random = new Random(42);
for (int i = 0; i < numClasses; i++)
{
int total = random.Next(10, 100); // total 在 10-100 之間
int pass = random.Next(1, total + 1); // pass 在 1-total 之間
classes[i] = new int[] { pass, total };
}
int extraStudents = 100;
// Act
var result = _solution.MaxAverageRatio(classes, extraStudents);
// Assert
Assert.True(result >= 0 && result <= 1,
$"Result should be between 0 and 1, got: {result}");
}
[Fact]
public void TestEdgeCases_MinExtraStudents_One()
{
// Arrange
int[][] classes = new int[][]
{
new int[] {1, 3},
new int[] {2, 4}
};
int extraStudents = 1;
// Act
var result = _solution.MaxAverageRatio(classes, extraStudents);
// Assert
double originalAvg = (1.0 / 3 + 2.0 / 4) / 2;
Assert.True(result > originalAvg,
$"Result {result} should be greater than original average {originalAvg}");
}
[Fact]
public void TestEdgeCases_LargeExtraStudents()
{
// Arrange - 大量額外學生
int[][] classes = new int[][]
{
new int[] {10, 100}, // 10% 通過率
new int[] {20, 100}, // 20% 通過率
new int[] {30, 100} // 30% 通過率
};
int extraStudents = 10000;
// Act
var result = _solution.MaxAverageRatio(classes, extraStudents);
// Assert
Assert.True(result >= 0 && result <= 1,
$"Result should be between 0 and 1, got: {result}");
// 大量學生加入後,通過率應該顯著提升
double originalAvg = (0.1 + 0.2 + 0.3) / 3; // = 0.2
Assert.True(result > originalAvg + 0.1,
$"Result {result} should be significantly higher than original average {originalAvg}");
}
#endregion
}

View File

@@ -0,0 +1,22 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
<IsPackable>false</IsPackable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.1.0" />
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="../csharp/csharp.csproj" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,7 @@
# 邊界情況清單
## 需要測試的邊界情況
- [x] one element in classes
- [x] classes Length >= 1000
- [x] extraStudent = 1
- [x] extraStudent = 10000

View File

@@ -0,0 +1,101 @@
# [2749] Minimum Operations To Make The Integer Zero
## 題目資訊
- **難度**: Medium
- **標籤**: Bit Manipulation, Brainteaser, Enumeration
- **題目連結**: [LeetCode](https://leetcode.com/problems/minimum-operations-to-make-the-integer-zero/)
- **練習日期**: 2025-09-05
## 題目描述
You are given two integers `num1` and `num2`.
In one operation, you can choose integer i in the range `[0, 60]` and subtract `2^i + num2` from `num1`.
Return the integer denoting the *minimum* number of operations needed to make `num1` equal to `0`.
If it is impossible to make `num1` equal to `0`, return `-1`.
## 解題思路
### 初步分析
- 這題主要考察什麼概念?
1. 位元操作 (Bit Manipulation):需要理解二進制表示和位元運算
2. 數學建模:將實際問題轉換為數學等式
3. 枚舉 (Enumeration):嘗試不同的操作次數 k
4. 約束條件判斷:理解多個限制條件的邏輯關係
- 有什麼關鍵限制條件?
1. target ≥ 0
2. bitCount(target) ≤ k
3. k ≤ target
- 預期時間/空間複雜度?
- 時間複雜度O(60 × log(target)) ≈ O(1)
- 空間複雜度O(1)
### 解法概述
1. **解法**:
- 思路:
- 目標:讓 num1 變成 0
- 每次操作num1 = num1 - (2^i + num2)
- k 次操作後num1 - k*num2 - (2^i1 + 2^i2 + ... + 2^ik) = 0
- 重新整理target = num1 - k*num2 = 2^i1 + 2^i2 + ... + 2^ik
- 時間複雜度O(1)
- 空間複雜度O(1)
## 測試案例
### 範例輸入輸出
```
Input: num1 = 3, num2 = -2
Output: 3
Explanation:
We can make 3 equal to 0 with the following operations:
- We choose i = 2 and subtract 22 + (-2) from 3, 3 - (4 + (-2)) = 1.
- We choose i = 2 and subtract 22 + (-2) from 1, 1 - (4 + (-2)) = -1.
- We choose i = 0 and subtract 20 + (-2) from -1, (-1) - (1 + (-2)) = 0.
It can be proven, that 3 is the minimum number of operations that we need to perform.
```
### 邊界情況
- `1 <= num1 <= 10^9`
- `-10^9 <= num2 <= 10^9`
## 學習筆記
### 今天學到什麼?
- 二位元的操作寫法
### 遇到的困難
- 二位元的操作
1. 方法一: 逐位檢查法
- 程式碼:
``` C#
count += (int)(n & 1);
n >>= 1;
```
- 運作原理:
1. n & 1檢查最右邊的位元是否為 1
2. count += (int)(n & 1):如果是 1 就加到計數器
3. n >>= 1把 n 右移一位(去掉已檢查的位元)
4. 重複直到 n 變成 0
2. 方法二: 移除最右邊 1
- 程式碼:
``` C#
count++;
n &= n - 1;
```
- 運作原理:
1. n - 1讓最右邊的 1 變成 0其右邊的 0 都變成 1
2. n & (n - 1):神奇地移除了最右邊的 1
3. count++:每移除一個 1計數器就加 1
4. 重複直到 n 變成 0
### 改善方向
-
### 相關題目
- [#991](https://leetcode.com/problems/broken-calculator) Broken Calculator
- [#1658](https://leetcode.com/problems/minimum-operations-to-reduce-x-to-zero/) Minimum Operations to Reduce X to Zero
---
**總結**:
1. 學習二位元的使用技巧

View File

@@ -0,0 +1,84 @@
// LeetCode 2749: Minimum Operations To Make The Integer Zero
// 難度: Medium
// 日期: 2025-09-05
using System;
using System.Collections.Generic;
using System.Linq;
public class Solution
{
public int MakeTheIntegerZero(int num1, int num2)
{
for (int k = 1; k <= 60; k++)
{
long target = (long)num1 - (long)k * num2;
if (target < 0) continue;
int bitCount = CountSetBits(target);
if (bitCount <= k && k <= target)
{
return k;
}
}
return -1;
}
private int CountSetBits(long n)
{
int count = 0;
while (n > 0)
{
// 方法一
// count += (int)(n & 1);
// n >>= 1;
// 方法二
count++;
n &= n - 1;
}
return count;
}
}
public class Program
{
public static void Main()
{
Solution solution = new Solution();
TestCase1(solution);
TestCase2(solution);
}
static void TestCase1(Solution solution)
{
int num1 = 3, num2 = -2;
int expected = 3;
int actual = solution.MakeTheIntegerZero(num1, num2);
Console.WriteLine("Test 1:");
Console.WriteLine($"Input: num1 = {num1}, num2 = {num2}");
Console.WriteLine($"Expected: {expected}");
Console.WriteLine($"Actual: {actual}");
Console.WriteLine($"Result: {(actual == expected ? "PASS" : "FAIL")}");
Console.WriteLine();
}
static void TestCase2(Solution solution)
{
int num1 = 5, num2 = 7;
int expected = -1;
int actual = solution.MakeTheIntegerZero(num1, num2);
Console.WriteLine("Test 2:");
Console.WriteLine($"Input: num1 = {num1}, num2 = {num2}");
Console.WriteLine($"Expected: {expected}");
Console.WriteLine($"Actual: {actual}");
Console.WriteLine($"Result: {(actual == expected ? "PASS" : "FAIL")}");
Console.WriteLine();
}
}

View File

@@ -0,0 +1,70 @@
# [2785] Sort Vowels In A String
## 題目資訊
- **難度**: Medium
- **標籤**: String, Sorting
- **題目連結**: [LeetCode](https://leetcode.com/problems/sort-vowels-in-a-string/)
- **練習日期**: 2025-09-11
## 題目描述
給定一個 0-indexed 的字串 s重新排列 s 以獲得新字串 t使得
所有子音保持在原來的位置
母音必須按照 ASCII 值的非遞減順序排序
更正式地說:
如果存在索引 i其中 0 <= i < s.length s[i] 是子音那麼 t[i] = s[i]
對於索引對 i, j其中 0 <= i < j < s.length s[i] s[j] 都是母音那麼 t[i] ASCII 值不能高於 t[j]
母音定義: 'a', 'e', 'i', 'o', 'u' 以及它們的大寫形式
## 解題思路
### 初步分析
- 這題主要考察什麼概念
這題主要考察字串處理和排序概念
- 有什麼關鍵限制條件
- 預期時間/空間複雜度
O(n log k) / O(k)其中 n 為字串長度k 為母音數量
### 解法概述
1. **解法**:
- 思路
1. 遍歷字串收集所有母音及其位置
2. 對母音字符進行排序
3. 將排序後的母音按原位置重新放回字串
- 時間複雜度O(n + k log k) 其中 n 是字串長度k 是母音數量
- 空間複雜度O(k) 存儲母音字符和位置
## 測試案例
### 範例輸入輸出
```
Input: s = "lEetcOde"
Output: "lEOtcede"
Explanation:
母音 'E', 'e', 'O', 'e' 排序後變成 'E', 'O', 'e', 'e'
```
### 邊界情況
- `1 <= s.length <= 10^5`
- `s` consists only of letters of the English alphabet in uppercase and lowercase.
## 學習筆記
### 今天學到什麼?
-
### 遇到的困難
-
### 改善方向
-
### 相關題目
- [題目編號] 題目名稱 - 相似概念
- [題目編號] 題目名稱 - 進階版本
---
**總結**: 這題的核心概念是...適合練習...技巧

View File

@@ -0,0 +1,108 @@
// LeetCode 2785: Sort Vowels In A String
// 難度: Medium
// 日期: 2025-09-11
using System;
using System.Collections.Generic;
using System.Linq;
public class Solution {
public string SortVowels(string s) {
// to char[]
char[] sArray = s.ToCharArray();
// get all vowels
string vowels = "aeiouAEIOU";
List<int> vowelPositions = new List<int>();
List<char> vowelChars = new List<char>();
for(int i = 0; i < sArray.Length; i++){
if(vowels.Contains(sArray[i])){
vowelPositions.Add(i);
vowelChars.Add(sArray[i]);
}
}
// sort all vowels
vowelChars.Sort();
// insert vowels
for(var i = 0; i < vowelPositions.Count; i++){
sArray[vowelPositions[i]] = vowelChars[i];
}
return new string(sArray);
}
}
// 測試程式
public class Program {
public static void Main() {
Solution sol = new Solution();
// TODO: 加入測試案例
TestCase1(sol);
TestCase2(sol);
TestCase3(sol);
TestCase4(sol);
TestCase5(sol);
TestCase6(sol);
TestCase7(sol);
}
// 基本範例 - LeetCode官方例子
static void TestCase1(Solution sol) {
var s = "lEetcOde";
var result = sol.SortVowels(s);
var expected = "lEOtcede";
Console.WriteLine($"Test 1: Input: \"{s}\", Result: \"{result}\", Expected: \"{expected}\", Pass: {result == expected}");
}
// 只有子音 - 沒有母音的情況
static void TestCase2(Solution sol) {
var s = "lYmpH";
var result = sol.SortVowels(s);
var expected = "lYmpH";
Console.WriteLine($"Test 2: Input: \"{s}\", Result: \"{result}\", Expected: \"{expected}\", Pass: {result == expected}");
}
// 只有母音 - 測試排序功能
static void TestCase3(Solution sol) {
var s = "aEiOu";
var result = sol.SortVowels(s);
var expected = "EOaiu";
Console.WriteLine($"Test 3: Input: \"{s}\", Result: \"{result}\", Expected: \"{expected}\", Pass: {result == expected}");
}
// 混合大小寫母音
static void TestCase4(Solution sol) {
var s = "TestcasE";
var result = sol.SortVowels(s);
var expected = "TEstcase";
Console.WriteLine($"Test 4: Input: \"{s}\", Result: \"{result}\", Expected: \"{expected}\", Pass: {result == expected}");
}
// 單一字元 - 邊界情況
static void TestCase5(Solution sol) {
var s = "a";
var result = sol.SortVowels(s);
var expected = "a";
Console.WriteLine($"Test 5: Input: \"{s}\", Result: \"{result}\", Expected: \"{expected}\", Pass: {result == expected}");
}
// 重複母音
static void TestCase6(Solution sol) {
var s = "Aa";
var result = sol.SortVowels(s);
var expected = "Aa";
Console.WriteLine($"Test 6: Input: \"{s}\", Result: \"{result}\", Expected: \"{expected}\", Pass: {result == expected}");
}
// 較長的字串測試
static void TestCase7(Solution sol) {
var s = "RaInBoW";
var result = sol.SortVowels(s);
var expected = "RIanBoW";
Console.WriteLine($"Test 7: Input: \"{s}\", Result: \"{result}\", Expected: \"{expected}\", Pass: {result == expected}");
}
}

View File

@@ -0,0 +1,30 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.5.2.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "csharp", "csharp\csharp.csproj", "{CF022C7B-CAF3-706D-67E1-FB93518229B7}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestProject", "test\TestProject.csproj", "{C670389A-9CE7-B456-51E5-A79D56E199CF}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{CF022C7B-CAF3-706D-67E1-FB93518229B7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{CF022C7B-CAF3-706D-67E1-FB93518229B7}.Debug|Any CPU.Build.0 = Debug|Any CPU
{CF022C7B-CAF3-706D-67E1-FB93518229B7}.Release|Any CPU.ActiveCfg = Release|Any CPU
{CF022C7B-CAF3-706D-67E1-FB93518229B7}.Release|Any CPU.Build.0 = Release|Any CPU
{C670389A-9CE7-B456-51E5-A79D56E199CF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C670389A-9CE7-B456-51E5-A79D56E199CF}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C670389A-9CE7-B456-51E5-A79D56E199CF}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C670389A-9CE7-B456-51E5-A79D56E199CF}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {50409315-93FE-4BEF-BAEC-4B70A05B634A}
EndGlobalSection
EndGlobal

View File

@@ -0,0 +1,91 @@
# [3005] Count_elements_with_maximum_frequency
## 題目資訊
- **難度**: Easy
- **標籤**:
- **題目連結**: https://leetcode.com/problems/count_elements_with_maximum_frequency/
- **練習日期**: 2025-09-22
- **目標複雜度**: 時間 O(?)、空間 O(?)
## 題目描述
> 在這裡貼上題目的完整描述(或重點)
## 先備條件與限制
- 輸入限制n ∈ [?, ?]、值域 ∈ [?, ?]
- 回傳/輸出格式:...
- 其他:是否允許排序/就地修改
## 解題思路
### 初步分析
- 類型:雙指針 / 滑動視窗 / 排序 / DP / 貪心 / 圖論 ...
- 關鍵觀察:
- 複雜度目標理由:
### 解法比較
1. 解法A基準/暴力):
- 思路:
- 正確性:
- 複雜度O(?) / O(?)
2. 解法B優化
- 思路:
- 正確性:
- 複雜度O(?) / O(?)
### 乾跑Dry Run
- 範例:...
## 實作細節與 API 設計
### C# 方法簽名(示意)
```csharp
public class Solution {
// TODO: 根據題意調整簽名
public int Solve(int[] nums) {
return 0;
}
}
```
### Go 方法簽名(示意)
```go
func solve(nums []int) int {
return 0
}
```
### 常見陷阱
- 邊界:空/單一/極值/全相等
- 去重:排序後跳重複、集合
- 溢位:使用 64-bit
## 測試案例
### 範例輸入輸出
```
Input: ...
Output: ...
Explanation: ...
```
### 邊界清單
- [ ] 空陣列/空字串
- [ ] 單一元素 / 全相同
- [ ] 含負數/0/大數
- [ ] 去重
- [ ] 大資料壓力
## 複雜度分析
- 最壞:時間 O(?)、空間 O(?)
## 相關題目 / Follow-up
-
## 學習筆記
- 今天學到:
- 卡住與修正:
- 待優化:
---
**總結**:這題的核心在於 ______,適合練習 ______

View File

@@ -0,0 +1,52 @@
// LeetCode 3005: Count_elements_with_maximum_frequency
// 難度: Easy
// 日期: 2025-09-22
using System;
using System.Collections.Generic;
using System.Linq;
public class Solution {
public int MaxFrequencyElements(int[] nums)
{
Dictionary<int, int> frequencyMap = new Dictionary<int, int>();
// put nums into dictionary map
foreach (var num in nums)
{
if (!frequencyMap.ContainsKey(num))
{
frequencyMap.Add(num, 0);
}
frequencyMap[num]++;
}
// find most frequency nums
int maxFrequency = 0;
if (frequencyMap.Count != 0)
{
maxFrequency = frequencyMap.Values.Max();
}
// count if have same max frequency nus
int count = 0;
foreach (var dic in frequencyMap)
{
if (dic.Value == maxFrequency)
{
count += maxFrequency;
}
}
return count;
}
}
public class Program {
public static void Main() {
var s = new Solution();
// TODO: 可加入簡單輸入/輸出測試
Console.WriteLine("Hello LeetCode 3005!");
}
}

View File

@@ -0,0 +1,9 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
</Project>

View File

@@ -0,0 +1,18 @@
// LeetCode 3005: Count_elements_with_maximum_frequency
// 難度: Easy
// 日期: 2025-09-22
package main
import "fmt"
// TODO: 根據題意調整簽名
func solve(nums []int) int {
return 0
}
func main() {
fmt.Printf("Hello LeetCode 3005!\n")
// TODO: 可加入簡單測試
}

View File

@@ -0,0 +1,24 @@
// LeetCode 3005 單元測試xUnit
using Xunit;
public class SolutionTests {
private readonly Solution _s = new Solution();
[Fact]
public void Example1() {
// TODO: Arrange
// var input = new int[] { };
// var expected = 0;
// Act
// var got = _s.Solve(input);
// Assert.Equal(expected, got);
Assert.True(true);
}
[Fact]
public void EdgeCases() {
Assert.True(true);
}
}

View File

@@ -0,0 +1,19 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
<IsPackable>false</IsPackable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.1.0" />
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="../csharp/csharp.csproj" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,12 @@
// LeetCode 3005 單元測試Go testing
package main
import "testing"
func TestExample(t *testing.T) {
// TODO: input := []int{}
// got := solve(input)
// want := 0
// if got != want { t.Fatalf("want %v got %v", want, got) }
}

View File

@@ -0,0 +1,69 @@
# [3025] Find The Number Of Ways To Place People I
## 題目資訊
- **難度**: Medium
- **標籤**: Array, Math, Geometry, Sorting, Enumeration
- **題目連結**: [LeetCode](https://leetcode.com/problems/find-the-number-of-ways-to-place-people-i/)
- **練習日期**: 2025-09-02
## 題目描述
You are given a 2D array `points` of size `n x 2` representing integer coordinates of some points on a 2D plane, where `points[i] = [xi, yi]`.
Count the number of pairs of points `(A, B)`, where
- `A` is on **the upper** left side of `B`, and
- there are no other points in the rectangle (or line) they make (**including the border**).
Return the count.
## 解題思路
### 初步分析
- 核心概念
幾何關係判斷 + 區域內點的檢測
- 關鍵限制條件
1. A必須在B的左上方, A.x <= B.x, A.y >= B.y
2. 矩形區域內(包含邊界)不能有其他點
- 預期時間/空間複雜度?
### 解法概述
**解法**:
- 思路:
- 遍歷所有點對 (A, B)
- 檢查每個pair形成的矩形, 裡面跟邊界會不會包含其他點
- 時間複雜度O(N^3)
- 空間複雜度O(1)
## 測試案例
### 範例輸入輸出
```
Input: points = [[6,2],[4,4],[2,6]]
Output: 2
Explanation:
- The left one is the pair (points[1], points[0]), where points[1] is on the upper left side of points[0] and the rectangle is empty.
- The left one is the pair (points[1], points[0]), where points[1] is on the upper left side of points[0] and the rectangle is empty.
- The right one is the pair (points[2], points[0]), where points[2] is on the upper left side of points[0], but points[1] is inside the rectangle so it's not a valid pair.
```
### 邊界情況
- `2 <= n <= 50`
- `points[i].length == 2`
- `0 <= points[i][0], points[i][1] <= 50`
- All `points[i]` are distinct.
## 學習筆記
### 今天學到什麼?
- 二維空間判斷點大小
### 遇到的困難
-
### 改善方向
-
### 相關題目
- [#223](https://leetcode.com/problems/rectangle-area/) Rectangle Area
---
**總結**: 這題的核心概念是...,適合練習...技巧。

View File

@@ -0,0 +1,86 @@
// LeetCode 3025: Find The Number Of Ways To Place People I
// 難度: Medium
// 日期: 2025-09-02
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
public class Solution
{
public int NumberOfPairs(int[][] points)
{
// 遍歷所有點對 (A, B)
// 檢查每個pair形成的矩形, 裡面跟邊界會不會包含其他點
// points[0].Length == 2
int n = points.Length;
int count = 0;
for (var i = 0; i < n; i++)
{
for (var j = 0; j < n; j++)
{
if (i == j) continue;
int[] pointA = points[i];
int[] pointB = points[j];
// check if A.x <= B.x && A.y >= B.y
// if yes, check if any points in rectangle
if (pointA[0] <= pointB[0] && pointA[1] >= pointB[1])
{
// difinition of border
bool hasOtherPoint = false;
int minX = pointA[0];
int maxX = pointB[0];
int minY = pointB[1];
int maxY = pointA[1];
// check other point if its in border
for (var k = 0; k < n; k++)
{
if (k == i || k == j) continue;
var pointC = points[k];
if (minX <= pointC[0] && pointC[0] <= maxX
&& minY <= pointC[1] && pointC[1] <= maxY)
{
hasOtherPoint = true;
break;
}
}
if (!hasOtherPoint) count++;
}
}
}
return count;
}
}
public class Program {
public static void Main() {
Solution solution = new Solution();
// 測試案例
TestCase(solution);
}
static void TestCase(Solution solution) {
// Input:
int[][] points = new int[][] {
new int[] {6, 2},
new int[] {4, 4},
new int[] {2, 6}
};
// Expected:
Console.WriteLine($"Test Case: [[6,2],[4,4],[2,6]]");
Console.WriteLine($"Expected: 2");
// Actual:
int result1 = solution.NumberOfPairs(points);
Console.WriteLine($"Result: {result1}");
}
}

View File

@@ -0,0 +1,3 @@
module leetcode-3025
go 1.18

View File

@@ -0,0 +1,70 @@
// LeetCode 3025: Find The Number Of Ways To Place People I
// 難度: Medium
// 日期: 2025-09-02
package main
import "fmt"
// TODO: 實作解法
func numberOfPairs(points [][]int) int {
n := len(points)
count := 0;
for i:= 0; i < n; i++{
for j := 0; j < n; j++{
if i == j {
continue
}
pointA := points[i]
pointB := points[j]
if pointA[0] <= pointB[0] && pointA[1] >= pointB[1] {
hasOtherPoint := false;
minX := pointA[0]
maxX := pointB[0]
minY := pointB[1]
maxY := pointA[1]
for k := 0; k < n; k++{
if i == k || j == k{
continue
}
pointC := points[k]
if minX <= pointC[0] && pointC[0] <= maxX && minY <= pointC[1] && pointC[1] <= maxY{
hasOtherPoint = true
break
}
}
if !hasOtherPoint{
count++
}
}
}
}
return count;
}
func main() {
testCase()
}
// 測試案例模板
func testCase() {
// Input:
points := [][]int{
{6, 2},
{4, 4},
{2, 6},
}
// Expected:
fmt.Printf("Test Case: [[6,2],[4,4],[2,6]]\n")
fmt.Printf("Expected: 2\n")
// Actual:
result := numberOfPairs(points)
fmt.Printf("Result: %d\n", result)
}

View File

@@ -0,0 +1,239 @@
// LeetCode 3025 Go 單元測試
package main
import (
"math/rand"
"testing"
"fmt"
)
func TestCase1_ExampleFromProblem(t *testing.T) {
// Arrange
points := [][]int{
{6, 2},
{4, 4},
{2, 6},
}
expected := 2
// Act
result := numberOfPairs(points)
// Assert
if result != expected {
t.Errorf("TestCase1 failed. Expected: %v, Got: %v", expected, result)
}
}
func TestCase2_TwoPoints(t *testing.T) {
// Arrange
points := [][]int{
{1, 3},
{2, 1},
}
expected := 1
// Act
result := numberOfPairs(points)
// Assert
if result != expected {
t.Errorf("TestCase2 failed. Expected: %v, Got: %v", expected, result)
}
}
func TestCase3_NoValidPairs(t *testing.T) {
// Arrange - 沒有有效點對的情況
points := [][]int{
{1, 1},
{2, 2},
{3, 3},
}
expected := 0
// Act
result := numberOfPairs(points)
// Assert
if result != expected {
t.Errorf("TestCase3 failed. Expected: %v, Got: %v", expected, result)
}
}
func TestCase4_SameXCoordinate(t *testing.T) {
// Arrange - x 座標相同的情況
points := [][]int{
{3, 5}, // A
{3, 2}, // B
{3, 1}, // C
}
// 詳細分析:
// (A, B): (3,5) -> (3,2) ✓ 矩形是線段,無其他點
// (A, C): (3,5) -> (3,1) ✗ 點B在矩形內
// (B, C): (3,2) -> (3,1) ✓ 矩形是線段,無其他點
expected := 2
// Act
result := numberOfPairs(points)
// Assert
if result != expected {
t.Errorf("TestCase4 failed. Expected: %v, Got: %v", expected, result)
}
}
func TestCase5_SameYCoordinate(t *testing.T) {
// Arrange - y 座標相同的情況
points := [][]int{
{1, 4}, // A
{3, 4}, // B
{5, 4}, // C
}
// 詳細分析:
// (A, B): (1,4) -> (3,4) ✓ 矩形是線段,無其他點
// (A, C): (1,4) -> (5,4) ✗ 點B在矩形內
// (B, C): (3,4) -> (5,4) ✓ 矩形是線段,無其他點
expected := 2
// Act
result := numberOfPairs(points)
// Assert
if result != expected {
t.Errorf("TestCase5 failed. Expected: %v, Got: %v", expected, result)
}
}
func TestCase6_PointsInsideRectangle(t *testing.T) {
// Arrange - 矩形內有其他點的情況
points := [][]int{
{0, 4}, // A
{4, 0}, // B
{2, 2}, // C
}
// 詳細分析:
// (A, B): (0,4) -> (4,0) ✗ 點C在矩形內
// (A, C): (0,4) -> (2,2) ✓ 點B不在矩形內
// (C, B): (2,2) -> (4,0) ✓ 點A不在矩形內
expected := 2
// Act
result := numberOfPairs(points)
// Assert
if result != expected {
t.Errorf("TestCase6 failed. Expected: %v, Got: %v", expected, result)
}
}
func TestCase7_PointsOnBorder(t *testing.T) {
// Arrange - 點在矩形邊界上的情況
points := [][]int{
{0, 3}, // A
{3, 0}, // B
{0, 0}, // C
}
// 詳細分析:
// (A, B): (0,3) -> (3,0) ✗ 點C在矩形邊界上
// (A, C): (0,3) -> (0,0) ✓ 矩形是線段點B不在其中
// (C, B): (0,0) -> (3,0) ✓ 矩形是線段點A不在其中
expected := 2
// Act
result := numberOfPairs(points)
// Assert
if result != expected {
t.Errorf("TestCase7 failed. Expected: %v, Got: %v", expected, result)
}
}
func TestEdgeCases_MinimumPoints(t *testing.T) {
// Arrange - 最少點數情況 (題目限制 n >= 2)
points := [][]int{
{0, 1},
{1, 0},
}
expected := 1 // (0,1) 在 (1,0) 的左上方
// Act
result := numberOfPairs(points)
// Assert
if result != expected {
t.Errorf("TestEdgeCases_MinimumPoints failed. Expected: %v, Got: %v", expected, result)
}
}
func TestEdgeCases_MaxCoordinateValues(t *testing.T) {
// Arrange - 最大座標值情況 (題目限制 0 <= coordinates <= 50)
points := [][]int{
{0, 50}, // A
{50, 0}, // B
{25, 25}, // C
}
expected := 2 // (A,C) 和 (C,B) 有效
// Act
result := numberOfPairs(points)
// Assert
if result != expected {
t.Errorf("TestEdgeCases_MaxCoordinateValues failed. Expected: %v, Got: %v", expected, result)
}
}
func TestEdgeCases_EmptyArray(t *testing.T) {
// Arrange - 空陣列情況
points := [][]int{}
expected := 0
// Act
result := numberOfPairs(points)
// Assert
if result != expected {
t.Errorf("TestEdgeCases_EmptyArray failed. Expected: %v, Got: %v", expected, result)
}
}
func TestEdgeCases_MaxPoints_RandomPattern(t *testing.T) {
// Arrange - 50個不同的點隨機模式
points := make([][]int, 0, 50)
usedPoints := make(map[string]bool)
// 使用固定種子確保測試可重現
rand.Seed(42)
for len(points) < 50 {
x := rand.Intn(51) // 0-50
y := rand.Intn(51) // 0-50
pointKey := fmt.Sprintf("%d,%d", x, y)
if !usedPoints[pointKey] {
usedPoints[pointKey] = true
points = append(points, []int{x, y})
}
}
// Act
result := numberOfPairs(points)
// Assert
if result < 0 {
t.Errorf("TestEdgeCases_MaxPoints_RandomPattern failed. Result should be non-negative, got: %v", result)
}
if result > 50*49 {
t.Errorf("TestEdgeCases_MaxPoints_RandomPattern failed. Result should not exceed 50*49, got: %v", result)
}
// 額外驗證:確保所有點都是不同的
distinctPoints := make(map[string]bool)
for _, point := range points {
key := fmt.Sprintf("%d,%d", point[0], point[1])
distinctPoints[key] = true
}
if len(distinctPoints) != 50 {
t.Errorf("TestEdgeCases_MaxPoints_RandomPattern failed. Expected 50 distinct points, got: %v", len(distinctPoints))
}
}

View File

@@ -0,0 +1,244 @@
// LeetCode 3025 單元測試
// 使用 xUnit 框架
using Xunit;
using System;
using System.Collections.Generic;
public class SolutionTests
{
private readonly Solution _solution;
public SolutionTests()
{
_solution = new Solution();
}
[Fact]
public void TestCase1_ExampleFromProblem()
{
// Arrange
int[][] points = new int[][] {
new int[] {6, 2},
new int[] {4, 4},
new int[] {2, 6}
};
int expected = 2;
// Act
var result = _solution.NumberOfPairs(points);
// Assert
Assert.Equal(expected, result);
}
[Fact]
public void TestCase2_TwoPoints()
{
// Arrange
int[][] points = new int[][] {
new int[] {1, 3},
new int[] {2, 1}
};
int expected = 1;
// Act
var result = _solution.NumberOfPairs(points);
// Assert
Assert.Equal(expected, result);
}
[Fact]
public void TestCase3_NoValidPairs()
{
// Arrange - 沒有有效點對的情況
int[][] points = new int[][] {
new int[] {1, 1},
new int[] {2, 2},
new int[] {3, 3}
};
int expected = 0;
// Act
var result = _solution.NumberOfPairs(points);
// Assert
Assert.Equal(expected, result);
}
[Fact]
public void TestCase4_SameXCoordinate()
{
// Arrange - x 座標相同的情況
int[][] points = new int[][] {
new int[] {3, 5},
new int[] {3, 2},
new int[] {3, 1}
};
int expected = 2;
// Act
var result = _solution.NumberOfPairs(points);
// Assert
Assert.Equal(expected, result);
}
[Fact]
public void TestCase5_SameYCoordinate()
{
// Arrange - y 座標相同的情況
int[][] points = new int[][] {
new int[] {1, 4},
new int[] {3, 4},
new int[] {5, 4}
};
int expected = 2;
// Act
var result = _solution.NumberOfPairs(points);
// Assert
Assert.Equal(expected, result);
}
[Fact]
public void TestCase6_PointsInsideRectangle()
{
// Arrange - 矩形內有其他點的情況
int[][] points = new int[][] {
new int[] {0, 4}, // A
new int[] {4, 0}, // B
new int[] {2, 2} // C (在 A-B 矩形內)
};
int expected = 2;
// Act
var result = _solution.NumberOfPairs(points);
// Assert
Assert.Equal(expected, result);
}
[Fact]
public void TestCase7_PointsOnBorder()
{
// Arrange - 點在矩形邊界上的情況
int[][] points = new int[][] {
new int[] {0, 3}, // A
new int[] {3, 0}, // B
new int[] {0, 0} // C (在矩形邊界上)
};
int expected = 2; // (A,C) 和 (C,B) 有效
// Act
var result = _solution.NumberOfPairs(points);
// Assert
Assert.Equal(expected, result);
}
[Fact]
public void TestEdgeCases_MinimumPoints()
{
// Arrange - 最少點數情況 (題目限制 n >= 2)
int[][] points = new int[][] {
new int[] {0, 1},
new int[] {1, 0}
};
int expected = 1; // (0,1) 在 (1,0) 的左上方
// Act
int result = _solution.NumberOfPairs(points);
// Assert
Assert.Equal(expected, result);
}
[Fact]
public void TestEdgeCases_IdenticalCoordinates()
{
// Arrange - 座標值相同的情況
int[][] points = new int[][] {
new int[] {2, 2},
new int[] {2, 2} // 題目保證所有點都不同,但測試邊界
};
// 這個測試案例實際上違反了題目條件 (All points[i] are distinct)
// 但可以測試程式的健壯性
int expected = 2; // 兩個相同點互相滿足左上方條件
// Act
int result = _solution.NumberOfPairs(points);
// Assert
Assert.Equal(expected, result);
}
[Fact]
public void TestEdgeCases_MaxCoordinateValues()
{
// Arrange - 最大座標值情況 (題目限制 0 <= coordinates <= 50)
int[][] points = new int[][] {
new int[] {0, 50},
new int[] {50, 0},
new int[] {25, 25}
};
int expected = 2; // (A,C) 和 (C,B) 有效
// Act
int result = _solution.NumberOfPairs(points);
// Assert
Assert.Equal(expected, result);
}
[Fact]
public void TestEdgeCases_EmptyArray()
{
// Arrange - 空陣列情況
int[][] points = new int[0][];
int expected = 0;
// Act
int result = _solution.NumberOfPairs(points);
// Assert
Assert.Equal(expected, result);
}
[Fact]
public void TestEdgeCases_MaxPoints_AllDistinct_RandomPattern() {
// Arrange - 50個不同的點更複雜的模式
var points = new List<int[]>();
// 創建一個螺旋模式的50個不同點確保都在 [0,50] 範圍內且互不相同
var usedPoints = new HashSet<string>();
var random = new Random(42); // 固定種子確保測試可重現
while (points.Count < 50) {
int x = random.Next(0, 51); // 0-50
int y = random.Next(0, 51); // 0-50
string pointKey = $"{x},{y}";
if (!usedPoints.Contains(pointKey)) {
usedPoints.Add(pointKey);
points.Add(new int[] { x, y });
}
}
int[][] pointsArray = points.ToArray();
// 由於是隨機分佈,很難預測確切結果,但應該是一個合理的正數
// 這個測試主要驗證程式在最大輸入時不會崩潰或超時
// Act
int result = _solution.NumberOfPairs(pointsArray);
// Assert
Assert.True(result >= 0); // 至少結果應該是非負數
Assert.True(result <= 50 * 49); // 最多不會超過所有可能的點對
}
}

View File

@@ -0,0 +1,22 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
<IsPackable>false</IsPackable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.1.0" />
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="../csharp/csharp.csproj" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,13 @@
# 邊界情況清單
## 需要測試的邊界情況
- [x] 空輸入 (空陣列) - `TestEdgeCases_EmptyArray`
- [x] 最少元素 (n=2) - `TestEdgeCases_MinimumPoints`
- [x] 重複座標 (雖然違反題目條件) - `TestEdgeCases_IdenticalCoordinates`
- [x] 最大值/最小值 (座標範圍 [0,50]) - `TestEdgeCases_MaxCoordinateValues`
- [x] 最大資料量 (n=50) - `TestEdgeCases_MaxPoints_AllDistinct_RandomPattern`
- [x] 相同 x 座標 - `TestCase4_SameXCoordinate`
- [x] 相同 y 座標 - `TestCase5_SameYCoordinate`
- [x] 矩形內含其他點 - `TestCase6_PointsInsideRectangle`
- [x] 點在矩形邊界上 - `TestCase7_PointsOnBorder`
- [x] 無有效點對情況 - `TestCase3_NoValidPairs`

View File

@@ -0,0 +1,39 @@
#!/bin/bash
echo "🧪 執行 LeetCode 題目測試"
echo "=========================="
# 執行 C# 測試
echo "📋 C# 測試結果:"
cd ../csharp
if dotnet build > /dev/null 2>&1; then
cd ../test
if dotnet test --logger "console;verbosity=minimal" 2>/dev/null; then
echo "✅ C# 測試通過"
else
echo "❌ C# 測試失敗"
fi
else
echo "❌ C# 編譯失敗"
fi
echo ""
# 執行 Go 測試
echo "📋 Go 測試結果:"
cd ../go
if go build > /dev/null 2>&1; then
# cd ../test
if go test -v > /dev/null 2>&1; then
echo "✅ Go 測試通過"
else
echo "❌ Go 測試失敗"
echo "詳細輸出:"
go test -v
fi
else
echo "❌ Go 編譯失敗"
fi
echo ""
echo "📊 測試完成!"

View File

@@ -0,0 +1,68 @@
# [3027] Find The Number Of Ways To Place People II
## 題目資訊
- **難度**: Hard
- **標籤**: Array, Math, Geometry, Enumeration
- **題目連結**: [LeetCode](https://leetcode.com/problems/find-the-number-of-ways-to-place-people-ii/)
- **練習日期**: 2025-09-03
## 題目描述
You are given a 2D array `points` of size `n x 2` representing integer coordinates of some points on a 2D-plane, where `points[i] = [xi, yi]`.
We define the **right** direction as positive x-axis **(increasing x-coordinate)** and the **left** direction as negative x-axis **(decreasing x-coordinate)**. Similarly, we define the **up** direction as positive y-axis **(increasing y-coordinate)** and the **down** direction as negative y-axis **(decreasing y-coordinate)**
You have to place `n` people, including Alice and Bob, at these points such that there is **exactly one** person at every point. Alice wants to be alone with Bob, so Alice will build a rectangular fence with Alice's position as the **upper left corner** and Bob's position as the **lower right corner** of the fence (**Note** that the fence **might not** enclose any area, i.e. it can be a line). If any person other than Alice and Bob is either **inside** the fence or on the fence, Alice will be sad.
Return the number of *pairs of points* where you can place Alice and Bob, such that Alice *does not* become sad on building the fence.
**Note** that Alice can only build a fence with Alice's position as the upper left corner, and Bob's position as the lower right corner. For example, Alice cannot build either of the fences in the picture below with four corners `(1, 1)`, `(1, 3)`, `(3, 1)`, and `(3, 3)`, because:
- With Alice at `(3, 3)` and Bob at `(1, 1)`, Alice's position is not the upper left corner and Bob's position is not the lower right corner of the fence.
- With Alice at `(1, 3)` and Bob at `(1, 1)`, Bob's position is not the lower right corner of the fence.
## 解題思路
### 初步分析
此題同[#3025](../3025-find-the-number-of-ways-to-place-people-i/README.md)
### 解法概述
此題同[#3025](../3025-find-the-number-of-ways-to-place-people-i/README.md)
## 測試案例
### 範例輸入輸出
```
Input: points = [[6,2],[4,4],[2,6]]
Output: 2
Explanation:
There are two ways to place Alice and Bob such that Alice will not be sad:
- Place Alice at (4, 4) and Bob at (6, 2).
- Place Alice at (2, 6) and Bob at (4, 4).
You cannot place Alice at (2, 6) and Bob at (6, 2) because the person at (4, 4) will be inside the fence.
```
### 邊界情況
- 2 <= n <= 1000
- points[i].length == 2
- -10^9 <= points[i][0], points[i][1] <= 10^9
- All points[i] are distinct.
## 學習筆記
### 今天學到什麼?
- 跟 [#3025]一樣, 但多了更多描述, 可能英文要再加強(?)
- 多了更大的邊界條件, 寫unit test 需要考慮更多覆蓋率
### 遇到的困難
-
### 改善方向
-
### 相關題目
- [#223](https://leetcode.com/problems/rectangle-area/) Rectangle Area
---
**總結**: 這題的核心概念是...,適合練習...技巧。

View File

@@ -0,0 +1,76 @@
// LeetCode 3027: Find The Number Of Ways To Place People Ii
// 難度: Hard
// 日期: 2025-09-03
using System;
using System.Collections.Generic;
using System.Linq;
public class Solution {
public int NumberOfPairs(int[][] points)
{
int n = points.Length;
int result = 0;
for (var i = 0; i < n; i++)
{
for (var j = 0; j < n; j++)
{
if (i == j) continue;
// 判斷 Alice points[i] 是否在 Bob points[j] 左上角
var Alice = points[i];
var Bob = points[j];
if (Alice[0] <= Bob[0] && Alice[1] >= Bob[1])
{
// get border
int minX = Alice[0];
int maxX = Bob[0];
int minY = Bob[1];
int maxY = Alice[1];
bool isAnyPerson = false;
for (var k = 0; k < n; k++)
{
if (i == k || j == k) continue;
var person = points[k];
if (minX <= person[0] && person[0] <= maxX && minY <= person[1] && person[1] <= maxY)
{
isAnyPerson = true;
break;
}
}
if (!isAnyPerson) result++;
}
}
}
return result;
}
}
public class Program {
public static void Main() {
Solution solution = new Solution();
// 測試案例
TestCase(solution);
}
static void TestCase(Solution solution) {
// Input:
int[][] points = new int[][] {
new int[] {6, 2},
new int[] {4, 4},
new int[] {2, 6}
};
// Expected:
Console.WriteLine($"Test Case: [[6,2],[4,4],[2,6]]");
Console.WriteLine($"Expected: 2");
// Actual:
int result1 = solution.NumberOfPairs(points);
Console.WriteLine($"Result: {result1}");
}
}

View File

@@ -0,0 +1,313 @@
// LeetCode 3027 單元測試
// 使用 xUnit 框架
using Xunit;
using System;
using System.Collections.Generic;
public class SolutionTests
{
private readonly Solution _solution;
public SolutionTests()
{
_solution = new Solution();
}
[Fact]
public void TestCase1_ExampleFromProblem()
{
// Arrange
int[][] points = new int[][] {
new int[] {6, 2},
new int[] {4, 4},
new int[] {2, 6}
};
int expected = 2;
// Act
var result = _solution.NumberOfPairs(points);
// Assert
Assert.Equal(expected, result);
}
[Fact]
public void TestCase2_TwoPoints()
{
// Arrange
int[][] points = new int[][] {
new int[] {1, 3},
new int[] {2, 1}
};
int expected = 1;
// Act
var result = _solution.NumberOfPairs(points);
// Assert
Assert.Equal(expected, result);
}
[Fact]
public void TestCase3_NoValidPairs()
{
// Arrange - 沒有有效點對的情況
int[][] points = new int[][] {
new int[] {1, 1},
new int[] {2, 2},
new int[] {3, 3}
};
int expected = 0;
// Act
var result = _solution.NumberOfPairs(points);
// Assert
Assert.Equal(expected, result);
}
[Fact]
public void TestCase4_SameXCoordinate()
{
// Arrange - x 座標相同的情況
int[][] points = new int[][] {
new int[] {3, 5},
new int[] {3, 2},
new int[] {3, 1}
};
int expected = 2;
// Act
var result = _solution.NumberOfPairs(points);
// Assert
Assert.Equal(expected, result);
}
[Fact]
public void TestCase5_SameYCoordinate()
{
// Arrange - y 座標相同的情況
int[][] points = new int[][] {
new int[] {1, 4},
new int[] {3, 4},
new int[] {5, 4}
};
int expected = 2;
// Act
var result = _solution.NumberOfPairs(points);
// Assert
Assert.Equal(expected, result);
}
[Fact]
public void TestCase6_PointsInsideRectangle()
{
// Arrange - 矩形內有其他點的情況
int[][] points = new int[][] {
new int[] {0, 4}, // A
new int[] {4, 0}, // B
new int[] {2, 2} // C (在 A-B 矩形內)
};
int expected = 2;
// Act
var result = _solution.NumberOfPairs(points);
// Assert
Assert.Equal(expected, result);
}
[Fact]
public void TestCase7_PointsOnBorder()
{
// Arrange - 點在矩形邊界上的情況
int[][] points = new int[][] {
new int[] {0, 3}, // A
new int[] {3, 0}, // B
new int[] {0, 0} // C (在矩形邊界上)
};
int expected = 2; // (A,C) 和 (C,B) 有效
// Act
var result = _solution.NumberOfPairs(points);
// Assert
Assert.Equal(expected, result);
}
[Fact]
public void TestCase8_NegativeCoordinates()
{
// Arrange - 負座標情況 (題目一允許 -10^9 到 10^9)
int[][] points = new int[][] {
new int[] {-5, 5},
new int[] {5, -5},
new int[] {0, 0}
};
int expected = 2; // (-5,5) -> (0,0) 和 (0,0) -> (5,-5) 有效
// Act
var result = _solution.NumberOfPairs(points);
// Assert
Assert.Equal(expected, result);
}
[Fact]
public void TestCase9_LargeCoordinates()
{
// Arrange - 大座標值情況
int[][] points = new int[][] {
new int[] {-1000000, 1000000},
new int[] {1000000, -1000000},
new int[] {0, 0}
};
int expected = 2;
// Act
var result = _solution.NumberOfPairs(points);
// Assert
Assert.Equal(expected, result);
}
[Fact]
public void TestEdgeCases_MinimumPoints()
{
// Arrange - 最少點數情況 (題目限制 n >= 2)
int[][] points = new int[][] {
new int[] {0, 1},
new int[] {1, 0}
};
int expected = 1; // (0,1) 在 (1,0) 的左上方
// Act
int result = _solution.NumberOfPairs(points);
// Assert
Assert.Equal(expected, result);
}
[Fact]
public void TestEdgeCases_MaximumCoordinateRange()
{
// Arrange - 最大座標範圍測試
int[][] points = new int[][] {
new int[] {-1000000000, 1000000000}, // 最小x最大y
new int[] {1000000000, -1000000000}, // 最大x最小y
new int[] {0, 0} // 中心點
};
int expected = 2;
// Act
int result = _solution.NumberOfPairs(points);
// Assert
Assert.Equal(expected, result);
}
[Fact]
public void TestCase_LargerDataSet()
{
// Arrange - 較大的數據集 (接近題目一的限制 n <= 1000)
var points = new List<int[]>();
// 創建 100 個不同的點 (可以增加到更接近 1000但為了測試速度這裡用 100)
for (int i = 0; i < 10; i++)
{
for (int j = 0; j < 10; j++)
{
points.Add(new int[] { i * 100 - 500, j * 100 - 500 });
}
}
int[][] pointsArray = points.ToArray();
// Act
int result = _solution.NumberOfPairs(pointsArray);
// Assert
Assert.True(result >= 0); // 結果應該是非負數
Assert.True(result <= 100 * 99); // 最多不會超過所有可能的點對
}
[Fact]
public void TestCase_StressTest_MediumSize()
{
// Arrange - 中等規模壓力測試 (200個點)
var points = new List<int[]>();
var usedPoints = new HashSet<string>();
var random = new Random(42); // 固定種子確保可重現
while (points.Count < 200)
{
int x = random.Next(-10000, 10001); // 較大範圍
int y = random.Next(-10000, 10001);
string pointKey = $"{x},{y}";
if (!usedPoints.Contains(pointKey))
{
usedPoints.Add(pointKey);
points.Add(new int[] { x, y });
}
}
int[][] pointsArray = points.ToArray();
// Act
var startTime = DateTime.Now;
int result = _solution.NumberOfPairs(pointsArray);
var endTime = DateTime.Now;
var elapsed = endTime - startTime;
// Assert
Assert.True(result >= 0);
Assert.True(result <= 200 * 199);
Assert.True(elapsed.TotalMilliseconds < 5000); // 應該在5秒內完成
}
[Fact]
public void TestCase_AllPointsOnSameLine_Vertical()
{
// Arrange - 所有點在同一條垂直線上
int[][] points = new int[][] {
new int[] {0, 10},
new int[] {0, 5},
new int[] {0, 0},
new int[] {0, -5},
new int[] {0, -10}
};
int expected = 4; // 每個點都可以與y座標更小的點配對
// Act
int result = _solution.NumberOfPairs(points);
// Assert
Assert.Equal(expected, result);
}
[Fact]
public void TestCase_AllPointsOnSameLine_Horizontal()
{
// Arrange - 所有點在同一條水平線上
int[][] points = new int[][] {
new int[] {-10, 0},
new int[] {-5, 0},
new int[] {0, 0},
new int[] {5, 0},
new int[] {10, 0}
};
int expected = 4; // 每個點都可以與x座標更大的點配對
// Act
int result = _solution.NumberOfPairs(points);
// Assert
Assert.Equal(expected, result);
}
}

View File

@@ -0,0 +1,22 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
<IsPackable>false</IsPackable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.1.0" />
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="../csharp/csharp.csproj" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,20 @@
#!/bin/bash
echo "🧪 執行 LeetCode 題目測試"
echo "=========================="
# 執行 C# 測試
echo "📋 C# 測試結果:"
cd ../csharp
if dotnet build > /dev/null 2>&1; then
cd ../test
if dotnet test --logger "console;verbosity=minimal" 2>/dev/null; then
echo "✅ C# 測試通過"
else
echo "❌ C# 測試失敗"
fi
else
echo "❌ C# 編譯失敗"
fi
echo "📊 測試完成!"

View File

@@ -0,0 +1,30 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.5.2.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "csharp", "csharp\csharp.csproj", "{CF022C7B-CAF3-706D-67E1-FB93518229B7}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestProject", "test\TestProject.csproj", "{C670389A-9CE7-B456-51E5-A79D56E199CF}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{CF022C7B-CAF3-706D-67E1-FB93518229B7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{CF022C7B-CAF3-706D-67E1-FB93518229B7}.Debug|Any CPU.Build.0 = Debug|Any CPU
{CF022C7B-CAF3-706D-67E1-FB93518229B7}.Release|Any CPU.ActiveCfg = Release|Any CPU
{CF022C7B-CAF3-706D-67E1-FB93518229B7}.Release|Any CPU.Build.0 = Release|Any CPU
{C670389A-9CE7-B456-51E5-A79D56E199CF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C670389A-9CE7-B456-51E5-A79D56E199CF}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C670389A-9CE7-B456-51E5-A79D56E199CF}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C670389A-9CE7-B456-51E5-A79D56E199CF}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {15EA9854-706B-456C-B6A2-6AF4670868DE}
EndGlobalSection
EndGlobal

View File

@@ -0,0 +1,82 @@
# [3227] Vowels Game In A String
## 題目資訊
- **難度**: Medium
- **標籤**: Math, String, Brainteaser, Game Theory
- **題目連結**: https://leetcode.com/problems/vowels-game-in-a-string/
- **練習日期**: 2025-09-12
- **目標複雜度**: 時間 O(n)、空間 O(1)
## 題目描述
Alice and Bob are playing a game on a string.
You are given a string `s`, Alice and Bob will take turns playing the following game where Alice starts **first**:
On Alice's turn, she has to remove any **non-empty** substring from `s` that contains an odd number of vowels.
On Bob's turn, he has to remove any non-empty substring from `s` that contains an even number of vowels.
The first player who cannot make a move on their turn loses the game. We assume that both Alice and Bob play optimally.
Return `true` if Alice wins the game, and `false` otherwise.
The English vowels are: `a`, `e`, `i`, `o`, and `u`.
## 先備條件與限制
- 輸入限制n ∈ [1, 10^5]、字符為小寫英文字母
- 回傳/輸出格式boolean 值true 表示 Alice 獲勝
## 解題思路
### 初步分析
- 類型:博弈論 / 數學 / 腦筋急轉彎
- 關鍵觀察:
- Alice 先手,需移除含奇數個母音的子字串
- Bob 後手,需移除含偶數個母音的子字串
- 複雜度目標理由:只需檢查是否存在母音
### 解法比較
1. 解法A基準/暴力):
- 思路:
發現 Alice 獲勝條件極其簡單
- 正確性:
只需檢查是否存在母音
- 複雜度O(n) / O(1)
### 常見陷阱
- 邊界:空字串(題目保證 n≥1、全母音、無母音
- 過度複雜化:誤以為需要複雜的博弈分析
- 計數錯誤:誤以為需要精確計算母音數量
- 大小寫:題目保證小寫字母
## 測試案例
### 範例輸入輸出
```
Input: s = "leetcode"
Output: true
Explanation: Alice 可以移除 "leetcod"含3個母音剩下 "e"Bob 無法移除含偶數母音的子字串
```
### 邊界清單
- 全母音字串Alice 立即移除整個字串獲勝
- 無母音字串Alice 無法行動敗北
- 單一字符(母音/子音)
- 混合字串(含有母音和子音)
- 長字串壓力測試
## 複雜度分析
- 最壞:時間 O(n)、空間 O(1)
- 最佳:時間 O(1)(首字符即為母音)、空間 O(1)
## 相關題目 / Follow-up
- LeetCode 345: Reverse Vowels of a String
- LeetCode 1456: Maximum Number of Vowels in a Substring of Given Length
- LeetCode 2062: Count Vowel Substrings of a String
## 學習筆記
- 今天學到:
- 卡住與修正:
- 待優化:
---
**總結**:這題的核心在於 ______,適合練習 ______

View File

@@ -0,0 +1,24 @@
// LeetCode 3227: Vowels Game In A String
// 難度: Medium
// 日期: 2025-09-12
using System;
using System.Collections.Generic;
using System.Linq;
public class Solution {
public bool DoesAliceWin(string s)
{
string vowels = "aeiou";
foreach (var character in s)
{
if (vowels.Contains(character))
{
return true;
}
}
return false;
}
}

View File

@@ -0,0 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
</Project>

View File

@@ -0,0 +1,4 @@
module leetcode/3227-vowels-game-in-a-string
go 1.18

View File

@@ -0,0 +1,19 @@
// LeetCode 3227: Vowels Game In A String
// 難度: Medium
// 日期: 2025-09-12
package vowels
import "strings"
// DoesAliceWin returns true if the string contains any vowel.
// Game theory reduces to: Alice wins iff there exists at least one vowel.
func DoesAliceWin(s string) bool {
const vowels = "aeiou"
for _, ch := range s {
if strings.ContainsRune(vowels, ch) {
return true
}
}
return false
}

View File

@@ -0,0 +1,168 @@
// LeetCode 3227: Vowels Game in a String 單元測試xUnit
// Problem: Alice and Bob play a game. Alice removes substrings with odd vowels,
// Bob removes substrings with even vowels. Alice wins if string has any vowels.
using Xunit;
public class SolutionTests
{
private readonly Solution _s = new Solution();
[Fact]
public void Example1_StringWithVowels_AliceWins()
{
// Arrange
var input = "leetcode"; // contains vowels: e,e,o,e
var expected = true; // Alice wins
// Act
var got = _s.DoesAliceWin(input);
// Assert
Assert.Equal(expected, got);
}
[Fact]
public void Example2_StringWithoutVowels_BobWins()
{
// Arrange
var input = "bcdf"; // no vowels
var expected = false; // Bob wins (Alice can't make first move)
// Act
var got = _s.DoesAliceWin(input);
// Assert
Assert.Equal(expected, got);
}
[Fact]
public void AllVowels_AliceWins()
{
// Arrange
var input = "aeiou"; // all vowels (odd count = 5)
var expected = true; // Alice removes entire string
// Act
var got = _s.DoesAliceWin(input);
// Assert
Assert.Equal(expected, got);
}
[Fact]
public void SingleVowel_AliceWins()
{
// Arrange
var input = "a"; // single vowel
var expected = true; // Alice removes it immediately
// Act
var got = _s.DoesAliceWin(input);
// Assert
Assert.Equal(expected, got);
}
[Fact]
public void SingleConsonant_BobWins()
{
// Arrange
var input = "b"; // single consonant, no vowels
var expected = false; // Alice can't move
// Act
var got = _s.DoesAliceWin(input);
// Assert
Assert.Equal(expected, got);
}
[Fact]
public void MixedString_EvenVowelCount_AliceWins()
{
// Arrange
var input = "programming"; // vowels: o,a,i (3 vowels, odd)
var expected = true; // Alice can remove all vowels at once
// Act
var got = _s.DoesAliceWin(input);
// Assert
Assert.Equal(expected, got);
}
[Fact]
public void LongStringNoVowels_BobWins()
{
// Arrange
var input = "bcdfghjklmnpqrstvwxyz"; // all consonants
var expected = false; // No vowels = Bob wins
// Act
var got = _s.DoesAliceWin(input);
// Assert
Assert.Equal(expected, got);
}
[Fact]
public void RepeatedVowels_AliceWins()
{
// Arrange
var input = "aaaa"; // 4 vowels (even count)
var expected = true; // Alice can remove 3, leaving 1 (Bob can't move)
// Act
var got = _s.DoesAliceWin(input);
// Assert
Assert.Equal(expected, got);
}
[Fact]
public void EdgeCases()
{
// Single character tests
Assert.True(_s.DoesAliceWin("e")); // vowel
Assert.False(_s.DoesAliceWin("x")); // consonant
// Two character tests
Assert.True(_s.DoesAliceWin("ab")); // has vowel 'a'
Assert.False(_s.DoesAliceWin("xy")); // no vowels
// Vowel at different positions
Assert.True(_s.DoesAliceWin("xabc")); // vowel at start-middle
Assert.True(_s.DoesAliceWin("abcx")); // vowel in middle
Assert.True(_s.DoesAliceWin("xbca")); // vowel at end
}
[Fact]
public void GameTheoryValidation()
{
// Test cases that validate the game theory logic:
// If total vowels = 0: Alice loses (can't make first move)
Assert.False(_s.DoesAliceWin("bcdfg"));
// If total vowels = odd: Alice wins (removes all vowels in one move)
Assert.True(_s.DoesAliceWin("hello")); // e,o = 2 vowels (even), but Alice still wins
Assert.True(_s.DoesAliceWin("beautiful")); // e,a,u,i,u = 5 vowels (odd)
// If total vowels = even > 0: Alice wins (leaves exactly 1 vowel for Bob)
Assert.True(_s.DoesAliceWin("code")); // o,e = 2 vowels (even)
Assert.True(_s.DoesAliceWin("education")); // e,u,a,i,o = 5 vowels, but any vowels = Alice wins
}
[Theory]
[InlineData("", false)] // empty string - no vowels
[InlineData("aeiou", true)] // all vowels
[InlineData("bcdfg", false)] // all consonants
[InlineData("hello", true)] // mixed with vowels
[InlineData("rhythm", false)] // no vowels (y not considered vowel)
[InlineData("queue", true)] // multiple same vowels
public void ParameterizedTests(string input, bool expected)
{
// Act & Assert
Assert.Equal(expected, _s.DoesAliceWin(input));
}
}

View File

@@ -0,0 +1,19 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
<IsPackable>false</IsPackable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.1.0" />
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="../csharp/csharp.csproj" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,20 @@
# 邊界情況清單3227 Vowels Game In A String
## 需要測試的邊界
- [ ] 空輸入 / 單一元素
- [ ] 重複元素 / 全相同
- [ ] 極值(最小/最大)
- [ ] 含負數 / 0 / 大數
- [ ] 大資料量(接近上限)
## 額外案例
### 案例 1
- 輸入:
- 預期:
- 說明:
### 案例 2
- 輸入:
- 預期:
- 說明:

View File

@@ -0,0 +1,188 @@
// LeetCode 3227: Vowels Game in a String 單元測試Go testing
// Problem: Alice and Bob play a game. Alice removes substrings with odd vowels,
// Bob removes substrings with even vowels. Alice wins if string has any vowels.
package vowels_test
import (
"fmt"
"testing"
vowels "leetcode/3227-vowels-game-in-a-string/go"
)
func TestExample1(t *testing.T) {
// "leetcode" contains vowels: e,e,o,e
input := "leetcode"
got := vowels.DoesAliceWin(input)
want := true // Alice wins
if got != want {
t.Fatalf("input %q: want %v got %v", input, want, got)
}
}
func TestExample2(t *testing.T) {
// "bcdf" has no vowels
input := "bcdf"
got := vowels.DoesAliceWin(input)
want := false // Bob wins (Alice can't make first move)
if got != want {
t.Fatalf("input %q: want %v got %v", input, want, got)
}
}
func TestAllVowels(t *testing.T) {
// All vowels string - Alice removes entire string
input := "aeiou"
got := vowels.DoesAliceWin(input)
want := true
if got != want {
t.Fatalf("input %q: want %v got %v", input, want, got)
}
}
func TestSingleVowel(t *testing.T) {
// Single vowel - Alice removes it immediately
input := "a"
got := vowels.DoesAliceWin(input)
want := true
if got != want {
t.Fatalf("input %q: want %v got %v", input, want, got)
}
}
func TestSingleConsonant(t *testing.T) {
// Single consonant - Alice can't move
input := "b"
got := vowels.DoesAliceWin(input)
want := false
if got != want {
t.Fatalf("input %q: want %v got %v", input, want, got)
}
}
func TestMixedString(t *testing.T) {
// "programming" has vowels: o,a,i
input := "programming"
got := vowels.DoesAliceWin(input)
want := true // Alice can remove vowels
if got != want {
t.Fatalf("input %q: want %v got %v", input, want, got)
}
}
func TestLongStringNoVowels(t *testing.T) {
// All consonants - no vowels means Bob wins
input := "bcdfghjklmnpqrstvwxyz"
got := vowels.DoesAliceWin(input)
want := false
if got != want {
t.Fatalf("input %q: want %v got %v", input, want, got)
}
}
func TestRepeatedVowels(t *testing.T) {
// Even number of same vowels - Alice can leave 1 for Bob
input := "aaaa"
got := vowels.DoesAliceWin(input)
want := true
if got != want {
t.Fatalf("input %q: want %v got %v", input, want, got)
}
}
func TestEdgeCases(t *testing.T) {
testCases := []struct {
input string
want bool
desc string
}{
{"e", true, "single vowel"},
{"x", false, "single consonant"},
{"ab", true, "has vowel 'a'"},
{"xy", false, "no vowels"},
{"xabc", true, "vowel in middle"},
{"abcx", true, "vowel at start"},
{"xbca", true, "vowel at end"},
}
for _, tc := range testCases {
t.Run(tc.desc, func(t *testing.T) {
got := vowels.DoesAliceWin(tc.input)
if got != tc.want {
t.Fatalf("input %q (%s): want %v got %v", tc.input, tc.desc, tc.want, got)
}
})
}
}
func TestGameTheoryValidation(t *testing.T) {
testCases := []struct {
input string
want bool
desc string
}{
// If total vowels = 0: Alice loses
{"bcdfg", false, "no vowels - Alice can't move"},
{"rhythm", false, "no vowels (y not counted)"},
// Any vowels > 0: Alice wins
{"hello", true, "e,o vowels - Alice wins"},
{"beautiful", true, "e,a,u,i,u vowels - Alice wins"},
{"code", true, "o,e vowels - Alice wins"},
{"education", true, "e,u,a,i,o vowels - Alice wins"},
{"queue", true, "u,e,u,e vowels - Alice wins"},
}
for _, tc := range testCases {
t.Run(tc.desc, func(t *testing.T) {
got := vowels.DoesAliceWin(tc.input)
if got != tc.want {
t.Fatalf("input %q (%s): want %v got %v", tc.input, tc.desc, tc.want, got)
}
})
}
}
func TestParameterized(t *testing.T) {
testCases := []struct {
input string
want bool
}{
{"", false}, // empty string
{"aeiou", true}, // all vowels
{"bcdfg", false}, // all consonants
{"hello", true}, // mixed with vowels
{"rhythm", false}, // no vowels
{"queue", true}, // multiple same vowels
{"xyz", false}, // short no vowels
{"programming", true}, // longer mixed
}
for _, tc := range testCases {
t.Run(tc.input, func(t *testing.T) {
got := vowels.DoesAliceWin(tc.input)
if got != tc.want {
t.Errorf("doesAliceWin(%q) = %v, want %v", tc.input, got, tc.want)
}
})
}
}
// Benchmark test
func BenchmarkDoesAliceWin(b *testing.B) {
testString := "abcdefghijklmnopqrstuvwxyz"
b.ResetTimer()
for i := 0; i < b.N; i++ {
vowels.DoesAliceWin(testString)
}
}
// Example test for documentation
func ExampleDoesAliceWin() {
result1 := vowels.DoesAliceWin("leetcode")
result2 := vowels.DoesAliceWin("bcdf")
fmt.Println(result1)
fmt.Println(result2)
// Output:
// true
// false
}

View File

@@ -0,0 +1,70 @@
# [3516] Find Closest Person
## 題目資訊
- **難度**: Easy
- **標籤**: Math
- **題目連結**: [LeetCode](https://leetcode.com/problems/find-closest-person/)
- **練習日期**: 2025-09-04
## 題目描述
You are given three integers `x`, `y`, and `z`, representing the positions of three people on a number line:
`x` is the position of Person 1.
`y` is the position of Person 2.
`z` is the position of Person 3, who does **not** move.
Both Person 1 and Person 2 move toward Person 3 at the same speed.
Determine which person reaches Person 3 first:
Return 1 if Person 1 arrives first.
Return 2 if Person 2 arrives first.
Return 0 if both arrive at the same time.
Return the result accordingly.
## 解題思路
### 初步分析
- 這題主要考察什麼概念?
距離計算和比較。使用絕對值計算兩點間距離
- 有什麼關鍵限制條件?
比較兩個距離的大小關係
- 預期時間/空間複雜度?
時間 O(1),空間 O(1) - 只需要常數時間的計算
### 解法概述
**解法**:
- 思路:
分別計算 Person 1 和 Person 2 到 Person 3 的距離,直接比較大小
- 時間複雜度O(1)
- 空間複雜度O(1)
## 測試案例
### 範例輸入輸出
```
Input: x = 2, y = 7, z = 4
Output: 1
Explanation:
- Person 1 is at position 2 and can reach Person 3 (at position 4) in 2 steps.
- Person 2 is at position 7 and can reach Person 3 in 3 steps.
Since Person 1 reaches Person 3 first, the output is 1.
```
### 邊界情況
`1 <= x, y, z <= 100`
## 學習筆記
### 今天學到什麼?
- 稍微練習了一下go func
### 遇到的困難
-
### 改善方向
-
### 相關題目
---
**總結**: 今天這題考弱智?

View File

@@ -0,0 +1,60 @@
// LeetCode 3516: Find Closest Person
// 難度: Easy
// 日期: 2025-09-04
using System;
using System.Collections.Generic;
using System.Linq;
public class Solution {
public int FindClosest(int x, int y, int z)
{
var distanceX = Math.Abs(x - z);
var distanceY = Math.Abs(y - z);
return distanceX == distanceY ? 0 : distanceX > distanceY ? 2 : 1;
}
}
// 測試程式
public class Program
{
public static void Main()
{
TestCase1();
TestCase2();
TestCase3();
}
// 基本測試案例 - Example 1
static void TestCase1()
{
var solution = new Solution();
// Input: x = 2, y = 7, z = 4
// Expected: 1 (Person 1 距離較近: |2-4| = 2 < |7-4| = 3)
var actual = solution.FindClosest(2, 7, 4);
var expected = 1;
Console.WriteLine($"Test 1: Input(2, 7, 4) Expected: {expected}, Actual: {actual}, Result: {(actual == expected ? "PASS" : "FAIL")}");
}
// 基本測試案例 - Example 2
static void TestCase2()
{
var solution = new Solution();
// Input: x = 2, y = 5, z = 6
// Expected: 2 (Person 2 距離較近: |5-6| = 1 < |2-6| = 4)
var actual = solution.FindClosest(2, 5, 6);
var expected = 2;
Console.WriteLine($"Test 2: Input(2, 5, 6) Expected: {expected}, Actual: {actual}, Result: {(actual == expected ? "PASS" : "FAIL")}");
}
// 基本測試案例 - Example 3
static void TestCase3() {
var solution = new Solution();
// Input: x = 1, y = 5, z = 3
// Expected: 0 (距離相等: |1-3| = 2 = |5-3| = 2)
var actual = solution.FindClosest(1, 5, 3);
var expected = 0;
Console.WriteLine($"Test 3: Input(1, 5, 3) Expected: {expected}, Actual: {actual}, Result: {(actual == expected ? "PASS" : "FAIL")}");
}
}

View File

@@ -0,0 +1,10 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
</Project>

View File

@@ -0,0 +1,3 @@
module leetcode-3516
go 1.18

View File

@@ -0,0 +1,71 @@
// LeetCode 3516: Find Closest Person
// 難度: Easy
// 日期: 2025-09-04
package main
import "fmt"
// TODO: 實作解法
func findClosest(x, y, z int) int {
distanceX := abs(x - z)
distanceY := abs(y - z)
if distanceX == distanceY{
return 0
}else if distanceX > distanceY{
return 2
}else{
return 1
}
}
func abs(n int) int{
if n < 0 {
return -n
}
return n
}
func main() {
testCase1()
testCase2()
testCase3()
}
// 基本測試案例 - Example 1
func testCase1() {
// Input: x = 2, y = 7, z = 4
// Expected: 1 (Person 1 距離較近: |2-4| = 2 < |7-4| = 3)
actual := findClosest(2, 7, 4)
expected := 1
fmt.Printf("Test 1: Input(2, 7, 4) Expected: %d, Actual: %d, Result: %s\n",
expected, actual, getResult(actual == expected))
}
// 基本測試案例 - Example 2
func testCase2() {
// Input: x = 2, y = 5, z = 6
// Expected: 2 (Person 2 距離較近: |5-6| = 1 < |2-6| = 4)
actual := findClosest(2, 5, 6)
expected := 2
fmt.Printf("Test 2: Input(2, 5, 6) Expected: %d, Actual: %d, Result: %s\n",
expected, actual, getResult(actual == expected))
}
// 基本測試案例 - Example 3
func testCase3() {
// Input: x = 1, y = 5, z = 3
// Expected: 0 (距離相等: |1-3| = 2 = |5-3| = 2)
actual := findClosest(1, 5, 3)
expected := 0
fmt.Printf("Test 3: Input(1, 5, 3) Expected: %d, Actual: %d, Result: %s\n",
expected, actual, getResult(actual == expected))
}
func getResult(pass bool) string {
if pass {
return "PASS"
}
return "FAIL"
}

View File

@@ -0,0 +1,99 @@
# YYYY年M月 學習記錄
## 本月設定(目標與主題)
- 主題:雙指針 / 滑動視窗 / DP / 圖論(自訂)
- 目標題數X 題Easy Y / Medium Z / Hard W
- 投入時間:每日 ≥ N 分鐘;每週 ≥ M 小時
- 挑戰:至少完成 Hard ≥ H 題;每週寫 1 篇總結
## 📅 每日練習記錄
### Week 1 (YYYY-MM-DD ~ YYYY-MM-DD)
| 日期 | 題目 | 難度 | 語言 | 耗時 | 狀態 | 心得 |
|------|------|------|------|------|------|------|
| | | | | | | |
### Week 2 (YYYY-MM-DD ~ YYYY-MM-DD)
| 日期 | 題目 | 難度 | 語言 | 耗時 | 狀態 | 心得 |
|------|------|------|------|------|------|------|
| | | | | | | |
### Week 3 (YYYY-MM-DD ~ YYYY-MM-DD)
| 日期 | 題目 | 難度 | 語言 | 耗時 | 狀態 | 心得 |
|------|------|------|------|------|------|------|
| | | | | | | |
### Week 4 (YYYY-MM-DD ~ YYYY-MM-DD)
| 日期 | 題目 | 難度 | 語言 | 耗時 | 狀態 | 心得 |
|------|------|------|------|------|------|------|
| | | | | | | |
## 🧭 主題覆蓋追蹤(勾選)
- [ ] 陣列/字串Two Pointers / Sliding Window
- [ ] 資料結構Stack/Queue/Heap/Set/Map
- [ ] 排序與搜尋Sorting / Binary Search
- [ ] 數學與位運算Math / Bit
- [ ] 動態規劃DP
- [ ] 圖論BFS/DFS/最短路/拓撲)
- [ ] 樹BST/遍歷/序列化)
## 📈 本月統計
### 完成情況
- 練習天數:天
- 完成題數Easy / Medium / Hard
- 語言分布C# (題), Go (題)
- 連續天數Streak本月斷點第 天
### 時間投入
- 總時間:小時
- 平均每題:分鐘
- 每日平均:分鐘
### 正確率 / 嘗試次數
- 一次通過:題
- 二次通過:題
- 多次調整:題(主因:邊界/複雜度/實作)
## 🎯 本月重點學習
### 新掌握的技巧(至少 3 條)
1.
2.
3.
### 常見錯誤與對策
1. 錯誤:;對策:
2. 錯誤:;對策:
3. 錯誤:;對策:
### 語言心得(實作層面)
- C#LINQ/Span/效能注意點/測試習慣
- Goslice/map/指標/錯誤處理/benchmark 習慣
## 🔄 困難案例復盤
### 案例1題號/主題
- 問題:
- 嘗試:
- 解決:
- 學習:
### 案例2題號/主題
- 問題:
- 嘗試:
- 解決:
- 學習:
## 📝 下月計畫
- 目標題數:
- 重點主題:
- 練習節奏:
- 要避免的坑:
## 💡 本月金句
>
---
**總結**:本月最大收穫是 ______接下來專注 ______。

View File

@@ -0,0 +1,105 @@
# [題目編號] 題目名稱
## 題目資訊
- **難度**: Easy/Medium/Hard
- **標籤**: Array, Hash Table, Two Pointers, Sliding Window, Greedy, DP, Graph, Tree, Math, etc.
- **題目連結**: [LeetCode](https://leetcode.com/problems/xxx/)
- **練習日期**: YYYY-MM-DD
- **目標複雜度**: 時間 O(?), 空間 O(?)
## 題目描述
> 在這裡貼上題目的完整描述(或摘要)
## 先備條件與限制
- 輸入限制n ∈ [?, ?]、值域 ∈ [?, ?]、是否有重複、是否有負數/零
- 回傳/輸出格式:...
- 其他排序是否允許改變輸入、是否需穩定、是否需就地in-place
## 解題思路
### 初步分析(快速定位問題類型)
- 問題類型:如 雙指針 / 滑動視窗 / 排序 + 掃描 / 貪心 / DP / 單調結構 / 前綴和 / 二分 / 位運算 ...
- 關鍵觀察:列出 2-4 點(不等式關係、單調性、區間性質、可分解性)
- 目標複雜度理由:為什麼 O(n) 或 O(n log n) 足夠/必要?
### 解法比較
1. **解法 A基準/暴力/直接枚舉)**
- 思路:步驟 1-2-3
- 正確性:為什麼不會漏/不會重?
- 複雜度:時間 O(?)、空間 O(?)
- 優缺點:易寫/慢;好理解/不通過大資料
2. **解法 B優化排序/雙指針/結構)**
- 思路:步驟 1-2-3指出與解法 A 最大差異)
- 正確性:單調性/貪心選擇/狀態定義 的論證要點
- 複雜度:時間 O(?)、空間 O(?)
- 優缺點:通過大資料/實作較複雜;可讀性需注意
3. (可選)**解法 C進一步優化/其他路線)**
- 思路、正確性、複雜度、優缺點
### 乾跑Dry Run
使用一組小範例逐步展示索引/指標/狀態如何變化(建議附上 3-5 步驟)。
## 實作細節與 API 設計
### C# 方法簽名
```csharp
public class Solution {
// TODO: 根據題意調整簽名
public int Solve(int[] nums) {
// ...
}
}
```
### Go 方法簽名
```go
// TODO: 根據題意調整簽名
func solve(nums []int) int {
// ...
}
```
### 實作要點 / 常見陷阱
- 邊界空集合、單元素、全相等、極值INT_MIN/INT_MAX
- 去重:排序後跳重複、集合/哈希去重
- 早停:提早終止條件(例如 window 擴不動就停)
- 精度/溢位除法、乘法、64 位整數
## 測試案例
### 範例輸入輸出
```
Input: ...
Output: ...
Explanation: ...
```
### 邊界與特殊情況清單
- [ ] 空陣列/空字串
- [ ] 單一元素 / 全相同 / 全遞增 / 全遞減
- [ ] 含負數 / 含 0 / 大數
- [ ] 有重複值 / 需去重
- [ ] 大資料壓力測試n 接近上限)
### 對拍/隨機測試(可選)
- 與暴力解法對拍 1000 次;隨機生成測資,確保輸出一致
## 複雜度分析
- 最壞:時間 O(?)、空間 O(?)
- 平均:時間 O(?)
- 最佳:時間 O(?)(若有)
## 相關題目與 Follow-up
- [題目編號] 題目名稱(相同套路)
- Follow-up若輸入動態變化/資料流版本/線上查詢如何處理?
## 學習筆記
- 今天學到:
- 卡住點與修正:
- 下次優化想法:
---
**總結**:這題的核心在於 ______適合練習 ______ 技巧。

View File

@@ -0,0 +1,91 @@
# [{{NUMBER}}] {{NAME_TITLE}}
## 題目資訊
- **難度**: {{DIFFICULTY}}
- **標籤**:
- **題目連結**: https://leetcode.com/problems/{{NAME_SLUG}}/
- **練習日期**: {{DATE}}
- **目標複雜度**: 時間 O(?)、空間 O(?)
## 題目描述
> 在這裡貼上題目的完整描述(或重點)
## 先備條件與限制
- 輸入限制n ∈ [?, ?]、值域 ∈ [?, ?]
- 回傳/輸出格式:...
- 其他:是否允許排序/就地修改
## 解題思路
### 初步分析
- 類型:雙指針 / 滑動視窗 / 排序 / DP / 貪心 / 圖論 ...
- 關鍵觀察:
- 複雜度目標理由:
### 解法比較
1. 解法A基準/暴力):
- 思路:
- 正確性:
- 複雜度O(?) / O(?)
2. 解法B優化
- 思路:
- 正確性:
- 複雜度O(?) / O(?)
### 乾跑Dry Run
- 範例:...
## 實作細節與 API 設計
### C# 方法簽名(示意)
```csharp
public class Solution {
// TODO: 根據題意調整簽名
public int Solve(int[] nums) {
return 0;
}
}
```
### Go 方法簽名(示意)
```go
func solve(nums []int) int {
return 0
}
```
### 常見陷阱
- 邊界:空/單一/極值/全相等
- 去重:排序後跳重複、集合
- 溢位:使用 64-bit
## 測試案例
### 範例輸入輸出
```
Input: ...
Output: ...
Explanation: ...
```
### 邊界清單
- [ ] 空陣列/空字串
- [ ] 單一元素 / 全相同
- [ ] 含負數/0/大數
- [ ] 去重
- [ ] 大資料壓力
## 複雜度分析
- 最壞:時間 O(?)、空間 O(?)
## 相關題目 / Follow-up
-
## 學習筆記
- 今天學到:
- 卡住與修正:
- 待優化:
---
**總結**:這題的核心在於 ______適合練習 ______。

View File

@@ -0,0 +1,24 @@
// LeetCode {{NUMBER}}: {{NAME_TITLE}}
// 難度: {{DIFFICULTY}}
// 日期: {{DATE}}
using System;
using System.Collections.Generic;
using System.Linq;
public class Solution {
// TODO: 根據題意調整簽名
public int Solve(int[] nums) {
// 實作解法
return 0;
}
}
public class Program {
public static void Main() {
var s = new Solution();
// TODO: 可加入簡單輸入/輸出測試
Console.WriteLine("Hello LeetCode {{NUMBER}}!");
}
}

Some files were not shown because too many files have changed in this diff Show More