Compare commits
38 Commits
38f948f691
...
main
Author | SHA1 | Date | |
---|---|---|---|
8146e2176d | |||
5189c524ef | |||
959f8a6861 | |||
5f8bf18795 | |||
72aa011de9 | |||
c4e23d5be3 | |||
c7453b45e6 | |||
7c86a4a99a | |||
c396a84294 | |||
2d6209a043 | |||
1e562065e8 | |||
8dfafaaf43 | |||
6d9993cd9f | |||
9ff736e11c | |||
d724a5fb65 | |||
002e9e6c32 | |||
75f3d9e320 | |||
f4a7029b7e | |||
31d68d2f04 | |||
4b2df683a4 | |||
cf3a952d1d | |||
63880d4717 | |||
c3955ad390 | |||
08c96f8636 | |||
![]() |
ec12425cb9 | ||
![]() |
17eaaa52c2 | ||
![]() |
58acd6e8d8 | ||
![]() |
b81da2e59e | ||
bd46985abc | |||
26696bf229 | |||
d120af6661 | |||
614434de14 | |||
bcbea676c2 | |||
b9965b192c | |||
8a49217c3d | |||
0c278fa275 | |||
c760afc0f7 | |||
b99708dc36 |
338
README.md
338
README.md
@@ -1,85 +1,289 @@
|
||||
# LeetCode Practice Journey 🚀
|
||||
# LeetCode 練習專案
|
||||
|
||||
## 📊 進度統計
|
||||
- **總題數**: 0
|
||||
- **已完成**: 0
|
||||
- **開始日期**: 2025-09-01
|
||||
- **最後更新**: 2025-09-01
|
||||
這是一個用來紀錄與管理 LeetCode 練習的專案,整合 C# 與 Go 的題解、基本測試模板、月度學習日誌,以及一支小工具腳本,協助快速建立新題目與維持一致的結構與習慣。
|
||||
|
||||
### 難度分布
|
||||
| 難度 | 完成數 | 總數 | 進度 |
|
||||
|------|--------|------|------|
|
||||
| Easy | 0 | 0 | 0% |
|
||||
| Medium | 0 | 0 | 0% |
|
||||
| Hard | 0 | 0 | 0% |
|
||||
## 專案架構
|
||||
|
||||
### 語言分布
|
||||
| 語言 | 完成題數 |
|
||||
|------|----------|
|
||||
| C++ | 0 |
|
||||
| C# | 0 |
|
||||
| Go | 0 |
|
||||
```
|
||||
.
|
||||
├── 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
|
||||
```
|
||||
|
||||
## 🎯 學習目標
|
||||
- [ ] 熟悉基本資料結構 (Array, LinkedList, Stack, Queue)
|
||||
- [ ] 掌握雙指針技巧
|
||||
- [ ] 動態規劃入門 (目標:完成 10 題)
|
||||
- [ ] 樹和圖的遍歷
|
||||
- [ ] 二分搜尋應用
|
||||
命名慣例:問題資料夾以「4 位數題號 + 題目英文 kebab-case」命名,例如 `3025-find-the-number-of-ways-to-place-people-i`。
|
||||
|
||||
## 📚 題目分類
|
||||
## 需求與環境
|
||||
|
||||
### Array & Hash Table
|
||||
| 題號 | 題目 | 難度 | 狀態 | 語言 | 筆記 |
|
||||
|------|------|------|------|------|------|
|
||||
| 1 | [Two Sum](problems/0001-two-sum/) | Easy | ✅ | C#, Go | 經典入門題 |
|
||||
| 15 | [3Sum](problems/0015-3sum/) | Medium | ✅ | C#, Go | 雙指針技巧 |
|
||||
- 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`
|
||||
|
||||
### Two Pointers
|
||||
| 題號 | 題目 | 難度 | 狀態 | 語言 | 筆記 |
|
||||
|------|------|------|------|------|------|
|
||||
| 11 | [Container With Most Water](problems/0011-container-with-most-water/) | Medium | ✅ | C# | 貪心思維 |
|
||||
初次使用請先授權腳本:
|
||||
|
||||
### String
|
||||
| 題號 | 題目 | 難度 | 狀態 | 語言 | 筆記 |
|
||||
|------|------|------|------|------|------|
|
||||
| 3 | [Longest Substring Without Repeating Characters](problems/0003-longest-substring/) | Medium | 🔄 | C# | 滑動窗口 |
|
||||
```
|
||||
chmod +x utils/leetcode_helper.sh utils/run_tests.sh
|
||||
```
|
||||
|
||||
### Dynamic Programming
|
||||
| 題號 | 題目 | 難度 | 狀態 | 語言 | 筆記 |
|
||||
|------|------|------|------|------|------|
|
||||
| 70 | [Climbing Stairs](problems/0070-climbing-stairs/) | Easy | 📝 | - | 待開始 |
|
||||
## 常用操作
|
||||
|
||||
## 📅 月度學習記錄
|
||||
- [2025年9月](logs/2025-09.md) - 基礎入門月 (完成 8 題)
|
||||
- [2025年10月](logs/2025-09.md) - 進階提升月 (進行中...)
|
||||
- 新增題目(自動建立資料夾、README、C#/Go 程式與測試模板)
|
||||
|
||||
## 🧠 重點學習筆記
|
||||
```
|
||||
./utils/leetcode_helper.sh problem <題號> <題目名稱-kebab> <難度>
|
||||
|
||||
### 常用模式總結
|
||||
1. **雙指針**: 適用於有序陣列的搜尋問題
|
||||
2. **滑動窗口**: 子陣列/子字串的最佳化問題
|
||||
3. **Hash Map**: 快速查找和計數問題
|
||||
# 範例
|
||||
./utils/leetcode_helper.sh problem 1 two-sum Easy
|
||||
./utils/leetcode_helper.sh problem 3000 maximum-area-rectangle Medium
|
||||
# 顯示說明:
|
||||
./utils/leetcode_helper.sh --help
|
||||
```
|
||||
|
||||
### 容易出錯的地方
|
||||
- 邊界條件檢查 (空陣列、單一元素)
|
||||
- 整數溢位問題
|
||||
- 陣列索引越界
|
||||
建立完成後的結構(示意):
|
||||
|
||||
## 📈 學習曲線反思
|
||||
- **第一週**: 熟悉基本語法和 LeetCode 平台
|
||||
- **第二週**: 開始理解演算法思維
|
||||
- **第三週**: 能獨立分析中等難度題目
|
||||
- **第四週**: 開始關注時間空間複雜度最佳化
|
||||
```
|
||||
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
|
||||
```
|
||||
|
||||
## 🔗 有用資源
|
||||
- [LeetCode Patterns](https://leetcode.com/discuss/general-discussion/458695/dynamic-programming-patterns)
|
||||
- [演算法與資料結構筆記](https://github.com/your-notes-repo)
|
||||
- [LeetCode Solutions 參考](https://github.com/your-solutions-repo)
|
||||
- 建立月度日誌(依模板生成 `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`。
|
||||
|
||||
## 測試範例(可直接複製改題名)
|
||||
|
||||
- xUnit(C#)
|
||||
|
||||
```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、邊界測資)
|
||||
|
||||
---
|
||||
*最後更新: 2025-09-01*
|
||||
|
||||
---
|
||||
account : iak64825@jioso.com
|
||||
password : ww5&Hy73dgh
|
||||
歡迎依個人習慣調整腳本與模板,持續穩定地練習最重要!
|
||||
|
@@ -1,586 +0,0 @@
|
||||
# 1. 讓腳本可執行:
|
||||
# chmod +x leetcode_helper.sh
|
||||
# 2. 建立新題目:
|
||||
# ./leetcode_helper.sh problem 1 two-sum Easy
|
||||
# ./leetcode_helper.sh problem 3000 maximum-area-rectangle Medium
|
||||
# 3. 建立月度日誌:
|
||||
# ./leetcode_helper.sh log 2025-09
|
||||
# 4. 更新README:
|
||||
# ./leetcode_helper.sh readme
|
||||
|
||||
#!/bin/bash
|
||||
|
||||
# 建立測試檔案
|
||||
function create_test_files() {
|
||||
local problem_dir="$1"
|
||||
local number="$2"
|
||||
local name="$3"
|
||||
|
||||
# 建立 C# 單元測試 (xUnit)
|
||||
cat > "$problem_dir/test/SolutionTests.cs" << EOF
|
||||
// LeetCode $number 單元測試
|
||||
// 使用 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() {
|
||||
// Arrange
|
||||
// TODO: 設定輸入資料
|
||||
// var input = ;
|
||||
// var expected = ;
|
||||
|
||||
// Act
|
||||
// var result = _solution.YourMethod(input);
|
||||
|
||||
// Assert
|
||||
// Assert.Equal(expected, result);
|
||||
|
||||
Assert.True(true); // 暫時通過,等待實作
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestCase2() {
|
||||
// TODO: 第二個測試案例
|
||||
Assert.True(true);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestEdgeCases() {
|
||||
// TODO: 邊界情況測試
|
||||
// 空陣列、單一元素、最大值、最小值等
|
||||
Assert.True(true);
|
||||
}
|
||||
}
|
||||
EOF
|
||||
|
||||
# 建立 C# 測試專案檔
|
||||
cat > "$problem_dir/test/TestProject.csproj" << EOF
|
||||
<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>
|
||||
EOF
|
||||
|
||||
# 建立 Go 測試檔案
|
||||
cat > "$problem_dir/test/main_test.go" << EOF
|
||||
// LeetCode $number Go 單元測試
|
||||
package main
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
func TestCase1(t *testing.T) {
|
||||
// TODO: 設定測試資料
|
||||
// input :=
|
||||
// expected :=
|
||||
|
||||
// result := solve(input)
|
||||
|
||||
// if !reflect.DeepEqual(result, expected) {
|
||||
// t.Errorf("TestCase1 failed. Expected: %v, Got: %v", expected, result)
|
||||
// }
|
||||
|
||||
// 暫時通過測試
|
||||
if false {
|
||||
t.Errorf("請實作測試案例")
|
||||
}
|
||||
}
|
||||
|
||||
func TestCase2(t *testing.T) {
|
||||
// TODO: 第二個測試案例
|
||||
if false {
|
||||
t.Errorf("請實作測試案例")
|
||||
}
|
||||
}
|
||||
|
||||
func TestEdgeCases(t *testing.T) {
|
||||
// TODO: 邊界情況測試
|
||||
if false {
|
||||
t.Errorf("請實作邊界測試")
|
||||
}
|
||||
}
|
||||
|
||||
// 輔助函數:比較 slice
|
||||
func equalSlices(a, b []int) bool {
|
||||
if len(a) != len(b) {
|
||||
return false
|
||||
}
|
||||
for i := range a {
|
||||
if a[i] != b[i] {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
EOF
|
||||
|
||||
# 建立測試資料檔案模板
|
||||
cat > "$problem_dir/test/input1.txt" << EOF
|
||||
# 測試案例 1 輸入
|
||||
# TODO: 從 LeetCode 複製範例輸入
|
||||
EOF
|
||||
|
||||
cat > "$problem_dir/test/output1.txt" << EOF
|
||||
# 測試案例 1 期望輸出
|
||||
# TODO: 從 LeetCode 複製範例輸出
|
||||
EOF
|
||||
|
||||
cat > "$problem_dir/test/input2.txt" << EOF
|
||||
# 測試案例 2 輸入
|
||||
# TODO: 加入額外測試案例
|
||||
EOF
|
||||
|
||||
cat > "$problem_dir/test/output2.txt" << EOF
|
||||
# 測試案例 2 期望輸出
|
||||
# TODO: 加入額外測試案例期望結果
|
||||
EOF
|
||||
|
||||
cat > "$problem_dir/test/edge_cases.md" << EOF
|
||||
# 邊界情況清單
|
||||
|
||||
## 需要測試的邊界情況
|
||||
- [ ] 空輸入 (空陣列、空字串等)
|
||||
- [ ] 單一元素
|
||||
- [ ] 重複元素
|
||||
- [ ] 最大值/最小值
|
||||
- [ ] 負數情況
|
||||
- [ ] 超大資料量
|
||||
- [ ] 特殊字符 (如果是字串題目)
|
||||
|
||||
## 額外測試案例
|
||||
### 案例 1:
|
||||
**輸入**:
|
||||
**輸出**:
|
||||
**說明**:
|
||||
|
||||
### 案例 2:
|
||||
**輸入**:
|
||||
**輸出**:
|
||||
**說明**:
|
||||
EOF
|
||||
|
||||
# 建立測試執行腳本
|
||||
cat > "$problem_dir/test/run_tests.sh" << 'EOF'
|
||||
#!/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 "📊 測試完成!"
|
||||
EOF
|
||||
|
||||
chmod +x "$problem_dir/test/run_tests.sh"
|
||||
}
|
||||
|
||||
# create_problem.sh - 建立新題目資料夾和檔案
|
||||
|
||||
function create_problem() {
|
||||
local number="$1"
|
||||
local name="$2"
|
||||
local difficulty="$3"
|
||||
|
||||
if [[ -z "$number" || -z "$name" || -z "$difficulty" ]]; then
|
||||
echo "使用方法: create_problem <題號> <題目名稱> <難度>"
|
||||
echo "範例: create_problem 1 two-sum Easy"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 格式化題號 (補零到4位數)
|
||||
local formatted_number=$(printf "%04d" "$number")
|
||||
local folder_name="${formatted_number}-${name}"
|
||||
local problem_dir="problems/${folder_name}"
|
||||
|
||||
# 建立資料夾結構
|
||||
mkdir -p "$problem_dir"
|
||||
mkdir -p "$problem_dir/test"
|
||||
|
||||
# 建立 README.md
|
||||
cat > "$problem_dir/README.md" << EOF
|
||||
# [$number] $(echo "$name" | tr '-' ' ' | sed 's/\b\w/\u&/g')
|
||||
|
||||
## 題目資訊
|
||||
- **難度**: $difficulty
|
||||
- **標籤**:
|
||||
- **題目連結**: [LeetCode](https://leetcode.com/problems/$name/)
|
||||
- **練習日期**: $(date +%Y-%m-%d)
|
||||
|
||||
## 題目描述
|
||||
>
|
||||
|
||||
## 解題思路
|
||||
|
||||
### 初步分析
|
||||
- 這題主要考察什麼概念?
|
||||
- 有什麼關鍵限制條件?
|
||||
- 預期時間/空間複雜度?
|
||||
|
||||
### 解法概述
|
||||
1. **暴力解法**:
|
||||
- 思路:
|
||||
- 時間複雜度:O(?)
|
||||
- 空間複雜度:O(?)
|
||||
|
||||
2. **優化解法**:
|
||||
- 思路:
|
||||
- 時間複雜度:O(?)
|
||||
- 空間複雜度:O(?)
|
||||
|
||||
## 實作細節
|
||||
|
||||
### C# 解法
|
||||
\`\`\`csharp
|
||||
// 核心程式碼片段或關鍵邏輯說明
|
||||
\`\`\`
|
||||
|
||||
### Go 解法
|
||||
\`\`\`go
|
||||
// 核心程式碼片段或關鍵邏輯說明
|
||||
\`\`\`
|
||||
|
||||
## 測試案例
|
||||
|
||||
### 範例輸入輸出
|
||||
\`\`\`
|
||||
Input:
|
||||
Output:
|
||||
Explanation:
|
||||
\`\`\`
|
||||
|
||||
### 邊界情況
|
||||
- [ ] 空陣列/空字串
|
||||
- [ ] 單一元素
|
||||
- [ ] 最大/最小值
|
||||
- [ ] 重複元素
|
||||
|
||||
## 學習筆記
|
||||
|
||||
### 今天學到什麼?
|
||||
-
|
||||
|
||||
### 遇到的困難
|
||||
-
|
||||
|
||||
### 改善方向
|
||||
-
|
||||
|
||||
### 相關題目
|
||||
- [題目編號] 題目名稱 - 相似概念
|
||||
- [題目編號] 題目名稱 - 進階版本
|
||||
|
||||
---
|
||||
**總結**: 這題的核心概念是...,適合練習...技巧。
|
||||
EOF
|
||||
|
||||
# 建立 C# 專案
|
||||
mkdir -p "$problem_dir/csharp"
|
||||
cd "$problem_dir/csharp"
|
||||
dotnet new console --force > /dev/null 2>&1
|
||||
|
||||
# 覆寫自動生成的 Program.cs
|
||||
cat > "Program.cs" << EOF
|
||||
// LeetCode $number: $(echo "$name" | tr '-' ' ' | sed 's/\b\w/\u&/g')
|
||||
// 難度: $difficulty
|
||||
// 日期: $(date +%Y-%m-%d)
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
public class Solution {
|
||||
public void Solve() {
|
||||
// TODO: 實作解法
|
||||
Console.WriteLine("Hello LeetCode $number!");
|
||||
}
|
||||
}
|
||||
|
||||
// 測試程式
|
||||
public class Program {
|
||||
public static void Main() {
|
||||
Solution sol = new Solution();
|
||||
sol.Solve();
|
||||
|
||||
// TODO: 加入測試案例
|
||||
// TestCase1();
|
||||
// TestCase2();
|
||||
}
|
||||
|
||||
// 測試案例模板
|
||||
/*
|
||||
static void TestCase1() {
|
||||
// Input:
|
||||
// Expected:
|
||||
// Actual:
|
||||
Console.WriteLine("Test 1: ");
|
||||
}
|
||||
*/
|
||||
}
|
||||
EOF
|
||||
cd - > /dev/null
|
||||
|
||||
# 建立 Go 解法檔案
|
||||
mkdir -p "$problem_dir/go"
|
||||
cat > "$problem_dir/go/main.go" << EOF
|
||||
// LeetCode $number: $(echo "$name" | tr '-' ' ' | sed 's/\b\w/\u&/g')
|
||||
// 難度: $difficulty
|
||||
// 日期: $(date +%Y-%m-%d)
|
||||
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
// TODO: 實作解法
|
||||
func solve() {
|
||||
fmt.Printf("Hello LeetCode %d!\n", $number)
|
||||
}
|
||||
|
||||
// 測試程式
|
||||
func main() {
|
||||
solve()
|
||||
|
||||
// TODO: 加入測試案例
|
||||
// testCase1()
|
||||
// testCase2()
|
||||
}
|
||||
|
||||
// 測試案例模板
|
||||
/*
|
||||
func testCase1() {
|
||||
// Input:
|
||||
// Expected:
|
||||
// Actual:
|
||||
fmt.Println("Test 1:")
|
||||
}
|
||||
*/
|
||||
EOF
|
||||
|
||||
# 初始化 Go module
|
||||
cd "$problem_dir/go"
|
||||
go mod init "leetcode-$number" > /dev/null 2>&1
|
||||
cd - > /dev/null
|
||||
|
||||
# 建立測試檔案
|
||||
create_test_files "$problem_dir" "$number" "$name"
|
||||
|
||||
echo "✅ 已建立題目資料夾: $problem_dir"
|
||||
echo "📁 檔案結構:"
|
||||
echo "$problem_dir/"
|
||||
echo "├── README.md"
|
||||
echo "├── csharp/"
|
||||
echo "│ ├── Program.cs"
|
||||
echo "│ └── *.csproj"
|
||||
echo "├── go/"
|
||||
echo "│ ├── main.go"
|
||||
echo "│ └── go.mod"
|
||||
echo "└── test/"
|
||||
echo " ├── SolutionTests.cs"
|
||||
echo " ├── TestProject.csproj"
|
||||
echo " ├── main_test.go"
|
||||
echo " ├── input1.txt"
|
||||
echo " ├── output1.txt"
|
||||
echo " ├── input2.txt"
|
||||
echo " ├── output2.txt"
|
||||
echo " ├── edge_cases.md"
|
||||
echo " └── run_tests.sh"
|
||||
echo ""
|
||||
echo "🚀 執行方式:"
|
||||
echo "C#: cd $problem_dir/csharp && dotnet run"
|
||||
echo "Go: cd $problem_dir/go && go run main.go"
|
||||
echo "測試: cd $problem_dir/test && ./run_tests.sh"
|
||||
}
|
||||
|
||||
# update_readme.sh - 更新主 README
|
||||
function update_readme() {
|
||||
echo "🔄 更新主 README.md..."
|
||||
|
||||
# 計算統計資料
|
||||
local total_problems=$(find problems -maxdepth 1 -type d | wc -l)
|
||||
total_problems=$((total_problems - 1)) # 排除 problems 資料夾本身
|
||||
|
||||
local completed_problems=$(find problems -name "README.md" -exec grep -l "✅" {} \; | wc -l)
|
||||
|
||||
echo "📊 發現 $total_problems 個題目,其中 $completed_problems 個已完成"
|
||||
|
||||
# 這裡可以加入更複雜的統計和README更新邏輯
|
||||
# 暫時只顯示統計結果
|
||||
}
|
||||
|
||||
# create_monthly_log.sh - 建立月度日誌
|
||||
function create_monthly_log() {
|
||||
local year_month="$1"
|
||||
|
||||
if [[ -z "$year_month" ]]; then
|
||||
year_month=$(date +%Y-%m)
|
||||
fi
|
||||
|
||||
local log_file="logs/${year_month}.md"
|
||||
|
||||
if [[ -f "$log_file" ]]; then
|
||||
echo "⚠️ 月度日誌已存在: $log_file"
|
||||
return 1
|
||||
fi
|
||||
|
||||
mkdir -p logs
|
||||
|
||||
cat > "$log_file" << EOF
|
||||
# ${year_month} 學習記錄
|
||||
|
||||
## 📅 每日練習記錄
|
||||
|
||||
### Week 1
|
||||
| 日期 | 題目 | 難度 | 語言 | 耗時 | 狀態 | 心得 |
|
||||
|------|------|------|------|------|------|------|
|
||||
| | | | | | | |
|
||||
|
||||
### Week 2
|
||||
| 日期 | 題目 | 難度 | 語言 | 耗時 | 狀態 | 心得 |
|
||||
|------|------|------|------|------|------|------|
|
||||
| | | | | | | |
|
||||
|
||||
### Week 3
|
||||
| 日期 | 題目 | 難度 | 語言 | 耗時 | 狀態 | 心得 |
|
||||
|------|------|------|------|------|------|------|
|
||||
| | | | | | | |
|
||||
|
||||
### Week 4
|
||||
| 日期 | 題目 | 難度 | 語言 | 耗時 | 狀態 | 心得 |
|
||||
|------|------|------|------|------|------|------|
|
||||
| | | | | | | |
|
||||
|
||||
## 📈 本月統計
|
||||
|
||||
### 完成情況
|
||||
- **總練習天數**: 天
|
||||
- **完成題數**: 題
|
||||
- **語言分布**: C# (題), Go (題)
|
||||
- **難度分布**: Easy (題), Medium (題), Hard (題)
|
||||
|
||||
### 時間投入
|
||||
- **總時間**: 小時
|
||||
- **平均每題**: 分鐘
|
||||
- **每日平均**: 分鐘
|
||||
|
||||
## 🎯 本月重點學習
|
||||
|
||||
### 新掌握的技巧
|
||||
1.
|
||||
|
||||
### 常犯錯誤分析
|
||||
1.
|
||||
|
||||
### 語言學習心得
|
||||
- **C#**:
|
||||
- **Go**:
|
||||
|
||||
## 🔄 遇到的困難與解決
|
||||
|
||||
### 困難1:
|
||||
- **問題**:
|
||||
- **解決**:
|
||||
- **學習**:
|
||||
|
||||
## 📝 改進計畫
|
||||
|
||||
### 下月目標
|
||||
1.
|
||||
|
||||
### 學習方法調整
|
||||
1.
|
||||
|
||||
## 💡 本月金句
|
||||
>
|
||||
|
||||
---
|
||||
**總結**:
|
||||
EOF
|
||||
|
||||
echo "✅ 已建立月度日誌: $log_file"
|
||||
}
|
||||
|
||||
# 主程式
|
||||
case "$1" in
|
||||
"problem")
|
||||
create_problem "$2" "$3" "$4"
|
||||
;;
|
||||
"readme")
|
||||
update_readme
|
||||
;;
|
||||
"log")
|
||||
create_monthly_log "$2"
|
||||
;;
|
||||
*)
|
||||
echo "LeetCode Practice Helper"
|
||||
echo ""
|
||||
echo "使用方法:"
|
||||
echo " $0 problem <題號> <題目名稱> <難度> # 建立新題目"
|
||||
echo " $0 readme # 更新主README"
|
||||
echo " $0 log [年月] # 建立月度日誌"
|
||||
echo ""
|
||||
echo "範例:"
|
||||
echo " $0 problem 1 two-sum Easy"
|
||||
echo " $0 problem 15 3sum Medium"
|
||||
echo " $0 log 2025-09"
|
||||
;;
|
||||
esac
|
@@ -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
|
@@ -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"));
|
||||
}
|
||||
}
|
@@ -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"))
|
||||
}
|
@@ -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
|
@@ -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));
|
||||
}
|
||||
}
|
@@ -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.
|
@@ -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
|
@@ -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));
|
||||
|
||||
}
|
||||
}
|
@@ -1,38 +0,0 @@
|
||||
public class Solution
|
||||
{
|
||||
public int AreaOfMaxDiagonal(int[][] dimensions)
|
||||
{
|
||||
int max = 0;
|
||||
int maxArea = 0;
|
||||
|
||||
foreach (var dimension in dimensions)
|
||||
{
|
||||
var dimensionSqrt = dimension[0] * dimension[0] + dimension[1] * dimension[1];
|
||||
var area = dimension[0] * dimension[1];
|
||||
if (dimensionSqrt > max)
|
||||
{
|
||||
max = dimensionSqrt;
|
||||
maxArea = area;
|
||||
}
|
||||
else if (dimensionSqrt == max)
|
||||
{
|
||||
maxArea = Math.Max(maxArea, area);
|
||||
}
|
||||
}
|
||||
return maxArea;
|
||||
}
|
||||
}
|
||||
|
||||
public class Program
|
||||
{
|
||||
public static void Main()
|
||||
{
|
||||
var Solution = new Solution();
|
||||
|
||||
var dimensions = new int[][] { [6,5],[8,6],[2,10],[8,1],[9,2],[3,5],[3,5]};
|
||||
|
||||
var result = Solution.AreaOfMaxDiagonal(dimensions);
|
||||
Console.WriteLine(result);
|
||||
}
|
||||
}
|
||||
|
@@ -1,27 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
)
|
||||
|
||||
func areaOfMaxDiagonal(dimensions [][]int) int{
|
||||
maxDiagonal := 0
|
||||
maxArea := 0
|
||||
|
||||
for _, dimension := range dimensions{
|
||||
l := dimension[0]
|
||||
w := dimension[1]
|
||||
diagonalSquare := l * l + w * w
|
||||
area := l * w
|
||||
|
||||
if diagonalSquare > maxDiagonal{
|
||||
maxDiagonal = diagonalSquare
|
||||
maxArea = area
|
||||
}else if diagonalSquare == maxDiagonal{
|
||||
maxArea = int(math.Max(float64(maxArea), float64(area)))
|
||||
}
|
||||
}
|
||||
|
||||
return maxArea
|
||||
}
|
@@ -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}") = "MinimumArea", "MinimumArea.csproj", "{61A8B87F-638B-4246-13C4-CC226CFBBEA5}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{61A8B87F-638B-4246-13C4-CC226CFBBEA5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{61A8B87F-638B-4246-13C4-CC226CFBBEA5}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{61A8B87F-638B-4246-13C4-CC226CFBBEA5}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{61A8B87F-638B-4246-13C4-CC226CFBBEA5}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {C6FDF6F7-60CD-4B35-B619-6F79B7243CA7}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
@@ -1,28 +0,0 @@
|
||||
public class Solution {
|
||||
public int MinimumArea(int[][] grid)
|
||||
{
|
||||
var x = grid[0].Length;
|
||||
var y = grid.Length;
|
||||
|
||||
int min_x = x;
|
||||
int max_x = 0;
|
||||
int min_y = y;
|
||||
int max_y = 0;
|
||||
|
||||
for (var i = 0; i < x; i++)
|
||||
{
|
||||
for (var j = 0; j < y; j++)
|
||||
{
|
||||
if (grid[j][i])
|
||||
{
|
||||
min_x = Math.Min(min_x, i);
|
||||
max_x = Math.Max(max_x, i);
|
||||
min_y = Math.Min(min_y, j);
|
||||
max_y = Math.Max(max_y, j);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (max_x - min_x + 1) * (max_y - min_y + 1);
|
||||
}
|
||||
}
|
@@ -1,40 +0,0 @@
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
func minimumArea(grid [][]int) int {
|
||||
row := len(grid)
|
||||
col := len(grid[0])
|
||||
|
||||
min_x := col
|
||||
max_x := 0
|
||||
min_y := row
|
||||
max_y := 0
|
||||
|
||||
for i:=0; i<row; i++{
|
||||
for j:=0; j<col; j++{
|
||||
if grid[i][j] == 1{
|
||||
min_x = Min(min_x, j)
|
||||
max_x = Max(max_x, j)
|
||||
min_y = Min(min_y, i)
|
||||
max_y = Max(max_y, i)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (max_x-min_x+1) * (max_y-min_y+1)
|
||||
}
|
||||
|
||||
func Min(a, b int)int{
|
||||
if a < b {
|
||||
return a
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
func Max(a, b int)int{
|
||||
if a > b{
|
||||
return a
|
||||
}
|
||||
return b
|
||||
}
|
@@ -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));
|
||||
}
|
||||
}
|
@@ -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).
|
||||
|
@@ -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))
|
||||
}
|
@@ -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
|
@@ -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));
|
||||
}
|
||||
}
|
@@ -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}") = "SortMatrix", "SortMatrix.csproj", "{60318F94-4F41-A4B8-C189-A8135ECCECCB}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{60318F94-4F41-A4B8-C189-A8135ECCECCB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{60318F94-4F41-A4B8-C189-A8135ECCECCB}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{60318F94-4F41-A4B8-C189-A8135ECCECCB}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{60318F94-4F41-A4B8-C189-A8135ECCECCB}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {9F59D1F6-D9F3-492C-BC39-A5771AF22B36}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
@@ -1,115 +0,0 @@
|
||||
public class Solution
|
||||
{
|
||||
public int[][] SortMatrix(int[][] grid)
|
||||
{
|
||||
// 左下
|
||||
var leftDiagonals = new Dictionary<int, List<int>>();
|
||||
for (var i = 0; i < grid.Length; i++)
|
||||
{
|
||||
// total -> 2n + 1 way
|
||||
for (var j = 0; j <= i; j++)
|
||||
{
|
||||
int diagonal = i - j;
|
||||
if (!leftDiagonals.ContainsKey(diagonal))
|
||||
{
|
||||
leftDiagonals[diagonal] = new List<int>();
|
||||
}
|
||||
leftDiagonals[diagonal].Add(grid[i][j]);
|
||||
}
|
||||
}
|
||||
|
||||
// 右上
|
||||
var rightDiagonals = new Dictionary<int, List<int>>();
|
||||
for (var i = 0; i < grid.Length; i++)
|
||||
{
|
||||
for (var j = i; j < grid.Length; j++)
|
||||
{
|
||||
int diagonal = j - i;
|
||||
if (!rightDiagonals.ContainsKey(diagonal))
|
||||
{
|
||||
rightDiagonals[diagonal] = new List<int>();
|
||||
}
|
||||
rightDiagonals[diagonal].Add(grid[i][j]);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var diagonal in leftDiagonals.Values)
|
||||
{
|
||||
diagonal.Sort((a, b) => b.CompareTo(a));
|
||||
}
|
||||
|
||||
foreach (var diagonal in rightDiagonals.Values)
|
||||
{
|
||||
diagonal.Sort((a, b) => a.CompareTo(b));
|
||||
}
|
||||
|
||||
for (var i = 0; i < grid.Length; i++)
|
||||
{
|
||||
for (var j = 0; j <= i; j++)
|
||||
{
|
||||
int diagonal = i - j;
|
||||
grid[i][j] = leftDiagonals[diagonal][0];
|
||||
leftDiagonals[diagonal].RemoveAt(0);
|
||||
}
|
||||
|
||||
for (var j = i; j < grid.Length; j++)
|
||||
{
|
||||
if (i == j) continue;
|
||||
int diagonal = j - i;
|
||||
grid[i][j] = rightDiagonals[diagonal][0];
|
||||
rightDiagonals[diagonal].RemoveAt(0);
|
||||
}
|
||||
}
|
||||
return grid;
|
||||
}
|
||||
}
|
||||
|
||||
public class Solution2 {
|
||||
public int[][] SortMatrix(int[][] grid) {
|
||||
int n = grid.Length;
|
||||
|
||||
for (int i = 0; i < n; i++) {
|
||||
List<int> tmp = new List<int>();
|
||||
for (int j = 0; i + j < n; j++) {
|
||||
tmp.Add(grid[i + j][j]);
|
||||
}
|
||||
tmp.Sort((a, b) => b.CompareTo(a));
|
||||
for (int j = 0; i + j < n; j++) {
|
||||
grid[i + j][j] = tmp[j];
|
||||
}
|
||||
}
|
||||
|
||||
for (int j = 1; j < n; j++) {
|
||||
List<int> tmp = new List<int>();
|
||||
for (int i = 0; j + i < n; i++) {
|
||||
tmp.Add(grid[i][j + i]);
|
||||
}
|
||||
tmp.Sort();
|
||||
for (int i = 0; j + i < n; i++) {
|
||||
grid[i][j + i] = tmp[i];
|
||||
}
|
||||
}
|
||||
|
||||
return grid;
|
||||
}
|
||||
}
|
||||
|
||||
class Program
|
||||
{
|
||||
static void Main()
|
||||
{
|
||||
var Solution = new Solution();
|
||||
|
||||
var gird = new int[][] { [1, 7, 3], [9, 8, 2], [4, 5, 6] };
|
||||
var result = Solution.SortMatrix(gird);
|
||||
|
||||
for (int i = 0; i < result.Length; i++)
|
||||
{
|
||||
for (int j = 0; j < result[i].Length; j++)
|
||||
{
|
||||
Console.Write(result[i][j] + " ");
|
||||
}
|
||||
Console.WriteLine();
|
||||
}
|
||||
}
|
||||
}
|
@@ -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}") = "FindDiagonalOrder", "FindDiagonalOrder.csproj", "{B3151728-C057-4305-DD4C-9A2AFBFC189A}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{B3151728-C057-4305-DD4C-9A2AFBFC189A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{B3151728-C057-4305-DD4C-9A2AFBFC189A}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{B3151728-C057-4305-DD4C-9A2AFBFC189A}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{B3151728-C057-4305-DD4C-9A2AFBFC189A}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {DB56539A-6F32-4D28-B91F-BB1DCF46F4D0}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
@@ -1,61 +0,0 @@
|
||||
public class Solution {
|
||||
public int[] FindDiagonalOrder(int[][] mat)
|
||||
{
|
||||
if (mat == null || mat.Length == 0 || mat[0].Length == 0)
|
||||
{
|
||||
return new int[0];
|
||||
}
|
||||
|
||||
var m = mat.Length;
|
||||
var n = mat[0].Length;
|
||||
|
||||
var diagonals = new Dictionary<int, List<int>>();
|
||||
|
||||
for (var i = 0; i < m; i++)
|
||||
{
|
||||
for (var j = 0; j < n; j++)
|
||||
{
|
||||
int diagonalIndex = i + j;
|
||||
if (!diagonals.ContainsKey(diagonalIndex))
|
||||
{
|
||||
diagonals[diagonalIndex] = new List<int>();
|
||||
}
|
||||
diagonals[diagonalIndex].Add(mat[i][j]);
|
||||
}
|
||||
}
|
||||
|
||||
var result = new List<int>();
|
||||
foreach (var key in diagonals.Keys)
|
||||
{
|
||||
var diagonal = diagonals[key];
|
||||
if (key % 2 == 0)
|
||||
{
|
||||
result.AddRange(diagonal);
|
||||
}
|
||||
else
|
||||
{
|
||||
diagonal.Reverse();
|
||||
result.AddRange(diagonal);
|
||||
}
|
||||
}
|
||||
|
||||
return result.ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
class Program
|
||||
{
|
||||
static void Main()
|
||||
{
|
||||
var Solution = new Solution();
|
||||
|
||||
int[][] mat1 = new int[][]{
|
||||
new int[]{1,2,3},
|
||||
new int[]{4,5,6},
|
||||
new int[]{7,8,9}
|
||||
};
|
||||
|
||||
Console.WriteLine(string.Join(", ", Solution.FindDiagonalOrder(mat1)));
|
||||
|
||||
}
|
||||
}
|
@@ -1,45 +0,0 @@
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
func findDiagonalOrder(mat [][]int) []int {
|
||||
if len(mat) == 0 || len(mat[0]) == 0{
|
||||
return []int{}
|
||||
}
|
||||
|
||||
m := len(mat)
|
||||
n := len(mat[0])
|
||||
|
||||
// maps
|
||||
diagonals := make(map[int][]int)
|
||||
|
||||
for i:=0; i< m;i++{
|
||||
for j:=0; j < n; j++{
|
||||
index := i+j
|
||||
diagonals[index] = append(diagonals[index], mat[i][j])
|
||||
}
|
||||
}
|
||||
|
||||
result := []int{}
|
||||
|
||||
for i:= 0; i< m+n-1; i++{
|
||||
if i% 2 == 0{
|
||||
reverse(diagonals[i])
|
||||
result = append(result, diagonals[i]...)
|
||||
}else{
|
||||
result = append(result, diagonals[i]...)
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
func reverse(slice []int){
|
||||
left, right :=0, len(slice)-1
|
||||
|
||||
for left < right{
|
||||
slice[left], slice[right] = slice[right], slice[left]
|
||||
left++
|
||||
right--
|
||||
}
|
||||
}
|
@@ -1,7 +0,0 @@
|
||||
1. 觀察矩陣對角線模式
|
||||
1. (0,0) -> 1 -> i+j = 0
|
||||
2. (1, 0), (0, 1) -> 2 -> i+j = 1
|
||||
3. (2, 0), (1, 1), (0, 2) -> 3 -> i+j = 2
|
||||
2. how to deal with diagonal sorting?
|
||||
1. while (i+j) % 2 == 1
|
||||
2. while (i+j) % 2 == 0 reversed
|
@@ -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
|
@@ -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);
|
||||
}
|
||||
}
|
@@ -1,10 +0,0 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
@@ -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)
|
||||
}
|
@@ -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.
|
@@ -5,12 +5,19 @@
|
||||
### Week 1
|
||||
| 日期 | 題目 | 難度 | 語言 | 耗時 | 狀態 | 心得 |
|
||||
|------|------|------|------|------|------|------|
|
||||
| 09-01 | Maximum Average Pass Ratio | Medium | C# | 1hr | Done | 第一次用到Priority Queue |
|
||||
| 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
|
||||
| 日期 | 題目 | 難度 | 語言 | 耗時 | 狀態 | 心得 |
|
||||
@@ -20,18 +27,19 @@
|
||||
### 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 |
|
||||
|
||||
## 📈 本月統計
|
||||
|
||||
### 完成情況
|
||||
- **總練習天數**: 1 天
|
||||
- **完成題數**: 1題
|
||||
- **語言分布**: C# 1(題), Go 0(題)
|
||||
- **難度分布**: Easy 0(題), Medium 1(題), Hard 0(題)
|
||||
- **總練習天數**: 9 天
|
||||
- **完成題數**: 9題
|
||||
- **語言分布**: C# 9(題), Go 2(題)
|
||||
- **難度分布**: Easy 3(題), Medium 5(題), Hard 1(題)
|
||||
|
||||
### 時間投入
|
||||
- **總時間**: 1小時
|
||||
- **總時間**: 4.5小時
|
||||
- **平均每題**: 分鐘
|
||||
- **每日平均**: 分鐘
|
||||
|
||||
@@ -39,6 +47,7 @@
|
||||
|
||||
### 新掌握的技巧
|
||||
1. 貪心策略
|
||||
2. string轉char, char轉string
|
||||
|
||||
### 常犯錯誤分析
|
||||
1.
|
||||
|
@@ -84,3 +84,101 @@
|
||||
|
||||
---
|
||||
**總結**: 八月是很好的開始,從完全新手到能獨立解決中等題目。九月要持續挑戰自己!
|
||||
# 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
99
logs/2025-11.md
Normal 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/效能注意點/測試習慣
|
||||
- Go:slice/map/指標/錯誤處理/benchmark 習慣
|
||||
|
||||
## 🔄 困難案例復盤
|
||||
|
||||
### 案例1:題號/主題
|
||||
- 問題:
|
||||
- 嘗試:
|
||||
- 解決:
|
||||
- 學習:
|
||||
|
||||
### 案例2:題號/主題
|
||||
- 問題:
|
||||
- 嘗試:
|
||||
- 解決:
|
||||
- 學習:
|
||||
|
||||
## 📝 下月計畫
|
||||
- 目標題數:
|
||||
- 重點主題:
|
||||
- 練習節奏:
|
||||
- 要避免的坑:
|
||||
|
||||
## 💡 本月金句
|
||||
>
|
||||
|
||||
---
|
||||
**總結**:本月最大收穫是 ______,接下來專注 ______。
|
||||
|
99
logs/2025-12.md
Normal file
99
logs/2025-12.md
Normal 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/效能注意點/測試習慣
|
||||
- Go:slice/map/指標/錯誤處理/benchmark 習慣
|
||||
|
||||
## 🔄 困難案例復盤
|
||||
|
||||
### 案例1:題號/主題
|
||||
- 問題:
|
||||
- 嘗試:
|
||||
- 解決:
|
||||
- 學習:
|
||||
|
||||
### 案例2:題號/主題
|
||||
- 問題:
|
||||
- 嘗試:
|
||||
- 解決:
|
||||
- 學習:
|
||||
|
||||
## 📝 下月計畫
|
||||
- 目標題數:
|
||||
- 重點主題:
|
||||
- 練習節奏:
|
||||
- 要避免的坑:
|
||||
|
||||
## 💡 本月金句
|
||||
>
|
||||
|
||||
---
|
||||
**總結**:本月最大收穫是 ______,接下來專注 ______。
|
||||
|
22
makefile
Normal file
22
makefile
Normal 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 未安裝成功"
|
85
problems/0165-compare-version-numbers/README.md
Normal file
85
problems/0165-compare-version-numbers/README.md
Normal 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 與缺段情況,適合練習字串雙指標與記憶體優化技巧。
|
144
problems/0165-compare-version-numbers/csharp/Program.cs
Normal file
144
problems/0165-compare-version-numbers/csharp/Program.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
5
legacy/3446 SortMatrix/C#/SortMatrix.csproj → problems/0165-compare-version-numbers/csharp/csharp.csproj
Executable file → Normal file
5
legacy/3446 SortMatrix/C#/SortMatrix.csproj → problems/0165-compare-version-numbers/csharp/csharp.csproj
Executable file → Normal file
@@ -1,10 +1,9 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
||||
|
56
problems/0165-compare-version-numbers/test/SolutionTests.cs
Normal file
56
problems/0165-compare-version-numbers/test/SolutionTests.cs
Normal 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);
|
||||
}
|
||||
}
|
@@ -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>
|
||||
|
29
problems/0165-compare-version-numbers/test/edge_cases.md
Normal file
29
problems/0165-compare-version-numbers/test/edge_cases.md
Normal 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 的版本字串,在最後一段差異才分勝負
|
@@ -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
|
80
problems/0166-fraction-to-recurring-decimal/README.md
Normal file
80
problems/0166-fraction-to-recurring-decimal/README.md
Normal 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 與取餘)就穩定
|
||||
- 另外注意:符號在輸出開頭先處理,整數和小數部分都用正數運算可避免重複符號
|
||||
- 待優化:可以先行預估非循環長度以減少插入成本,但對此題影響不大
|
||||
|
||||
---
|
||||
**總結**:這題的核心在於以餘數哈希判斷循環節,適合練習小數表示與溢位處理。
|
@@ -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();
|
||||
|
||||
}
|
||||
}
|
5
legacy/326 isPowerOfThree/C#/isPowerOfThree.csproj → problems/0166-fraction-to-recurring-decimal/csharp/csharp.csproj
Executable file → Normal file
5
legacy/326 isPowerOfThree/C#/isPowerOfThree.csproj → problems/0166-fraction-to-recurring-decimal/csharp/csharp.csproj
Executable file → Normal file
@@ -1,10 +1,9 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
||||
|
3
problems/0166-fraction-to-recurring-decimal/go/go.mod
Normal file
3
problems/0166-fraction-to-recurring-decimal/go/go.mod
Normal file
@@ -0,0 +1,3 @@
|
||||
module leetcode-166
|
||||
|
||||
go 1.18
|
18
problems/0166-fraction-to-recurring-decimal/go/main.go
Normal file
18
problems/0166-fraction-to-recurring-decimal/go/main.go
Normal 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: 可加入簡單測試
|
||||
}
|
||||
|
@@ -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);
|
||||
}
|
||||
}
|
@@ -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>
|
||||
|
@@ -0,0 +1,20 @@
|
||||
# 邊界情況清單(166 Fraction To Recurring Decimal)
|
||||
|
||||
## 需要測試的邊界
|
||||
- [ ] 空輸入 / 單一元素
|
||||
- [ ] 重複元素 / 全相同
|
||||
- [ ] 極值(最小/最大)
|
||||
- [ ] 含負數 / 0 / 大數
|
||||
- [ ] 大資料量(接近上限)
|
||||
|
||||
## 額外案例
|
||||
### 案例 1
|
||||
- 輸入:
|
||||
- 預期:
|
||||
- 說明:
|
||||
|
||||
### 案例 2
|
||||
- 輸入:
|
||||
- 預期:
|
||||
- 說明:
|
||||
|
@@ -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) }
|
||||
}
|
||||
|
@@ -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
|
||||
|
||||
## 學習筆記
|
||||
|
||||
### 今天學到什麼?
|
||||
-
|
||||
|
||||
### 遇到的困難
|
||||
-
|
||||
|
||||
### 改善方向
|
||||
-
|
||||
|
||||
### 相關題目
|
||||
|
||||
---
|
||||
**總結**: 這題的核心概念是...,適合練習...技巧。
|
@@ -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]}");
|
||||
}
|
||||
}
|
@@ -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. 學習二位元的使用技巧
|
@@ -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();
|
||||
}
|
||||
|
||||
}
|
70
problems/2785-sort-vowels-in-a-string/README.md
Normal file
70
problems/2785-sort-vowels-in-a-string/README.md
Normal 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.
|
||||
|
||||
## 學習筆記
|
||||
|
||||
### 今天學到什麼?
|
||||
-
|
||||
|
||||
### 遇到的困難
|
||||
-
|
||||
|
||||
### 改善方向
|
||||
-
|
||||
|
||||
### 相關題目
|
||||
- [題目編號] 題目名稱 - 相似概念
|
||||
- [題目編號] 題目名稱 - 進階版本
|
||||
|
||||
---
|
||||
**總結**: 這題的核心概念是...,適合練習...技巧。
|
108
problems/2785-sort-vowels-in-a-string/csharp/Program.cs
Normal file
108
problems/2785-sort-vowels-in-a-string/csharp/Program.cs
Normal 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}");
|
||||
}
|
||||
}
|
0
legacy/2787 numberOfWays/C#/numberOfWays.csproj → problems/2785-sort-vowels-in-a-string/csharp/csharp.csproj
Executable file → Normal file
0
legacy/2787 numberOfWays/C#/numberOfWays.csproj → problems/2785-sort-vowels-in-a-string/csharp/csharp.csproj
Executable file → Normal 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
|
@@ -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
|
||||
-
|
||||
|
||||
## 學習筆記
|
||||
- 今天學到:
|
||||
- 卡住與修正:
|
||||
- 待優化:
|
||||
|
||||
---
|
||||
**總結**:這題的核心在於 ______,適合練習 ______。
|
||||
|
@@ -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!");
|
||||
}
|
||||
}
|
||||
|
@@ -1,10 +1,9 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
||||
|
@@ -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: 可加入簡單測試
|
||||
}
|
||||
|
@@ -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);
|
||||
}
|
||||
}
|
||||
|
@@ -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>
|
||||
|
@@ -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) }
|
||||
}
|
||||
|
@@ -0,0 +1,3 @@
|
||||
module leetcode-3025
|
||||
|
||||
go 1.18
|
@@ -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)
|
||||
}
|
@@ -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))
|
||||
}
|
||||
}
|
39
problems/3025-find-the-number-of-ways-to-place-people-i/test/run_tests.sh
Executable file
39
problems/3025-find-the-number-of-ways-to-place-people-i/test/run_tests.sh
Executable 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 "📊 測試完成!"
|
@@ -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
|
||||
|
||||
---
|
||||
**總結**: 這題的核心概念是...,適合練習...技巧。
|
@@ -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}");
|
||||
}
|
||||
}
|
@@ -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);
|
||||
}
|
||||
}
|
@@ -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>
|
@@ -17,5 +17,4 @@ else
|
||||
echo "❌ C# 編譯失敗"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "📊 測試完成!"
|
@@ -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
|
82
problems/3227-vowels-game-in-a-string/README.md
Normal file
82
problems/3227-vowels-game-in-a-string/README.md
Normal 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
|
||||
|
||||
## 學習筆記
|
||||
- 今天學到:
|
||||
- 卡住與修正:
|
||||
- 待優化:
|
||||
|
||||
---
|
||||
**總結**:這題的核心在於 ______,適合練習 ______。
|
||||
|
24
problems/3227-vowels-game-in-a-string/csharp/Program.cs
Normal file
24
problems/3227-vowels-game-in-a-string/csharp/Program.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
</Project>
|
4
problems/3227-vowels-game-in-a-string/go.mod
Normal file
4
problems/3227-vowels-game-in-a-string/go.mod
Normal file
@@ -0,0 +1,4 @@
|
||||
module leetcode/3227-vowels-game-in-a-string
|
||||
|
||||
go 1.18
|
||||
|
19
problems/3227-vowels-game-in-a-string/go/main.go
Normal file
19
problems/3227-vowels-game-in-a-string/go/main.go
Normal 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
|
||||
}
|
168
problems/3227-vowels-game-in-a-string/test/SolutionTests.cs
Normal file
168
problems/3227-vowels-game-in-a-string/test/SolutionTests.cs
Normal 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));
|
||||
}
|
||||
}
|
@@ -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>
|
||||
|
20
problems/3227-vowels-game-in-a-string/test/edge_cases.md
Normal file
20
problems/3227-vowels-game-in-a-string/test/edge_cases.md
Normal file
@@ -0,0 +1,20 @@
|
||||
# 邊界情況清單(3227 Vowels Game In A String)
|
||||
|
||||
## 需要測試的邊界
|
||||
- [ ] 空輸入 / 單一元素
|
||||
- [ ] 重複元素 / 全相同
|
||||
- [ ] 極值(最小/最大)
|
||||
- [ ] 含負數 / 0 / 大數
|
||||
- [ ] 大資料量(接近上限)
|
||||
|
||||
## 額外案例
|
||||
### 案例 1
|
||||
- 輸入:
|
||||
- 預期:
|
||||
- 說明:
|
||||
|
||||
### 案例 2
|
||||
- 輸入:
|
||||
- 預期:
|
||||
- 說明:
|
||||
|
188
problems/3227-vowels-game-in-a-string/test/main_test.go
Normal file
188
problems/3227-vowels-game-in-a-string/test/main_test.go
Normal 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
|
||||
}
|
70
problems/3516-find-closest-person/README.md
Normal file
70
problems/3516-find-closest-person/README.md
Normal 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
|
||||
|
||||
### 遇到的困難
|
||||
- 無
|
||||
|
||||
### 改善方向
|
||||
- 無
|
||||
|
||||
### 相關題目
|
||||
|
||||
---
|
||||
**總結**: 今天這題考弱智?
|
60
problems/3516-find-closest-person/csharp/Program.cs
Normal file
60
problems/3516-find-closest-person/csharp/Program.cs
Normal 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")}");
|
||||
}
|
||||
}
|
0
legacy/3195 minimumArea/C#/MinimumArea.csproj → problems/3516-find-closest-person/csharp/csharp.csproj
Executable file → Normal file
0
legacy/3195 minimumArea/C#/MinimumArea.csproj → problems/3516-find-closest-person/csharp/csharp.csproj
Executable file → Normal file
3
problems/3516-find-closest-person/go/go.mod
Normal file
3
problems/3516-find-closest-person/go/go.mod
Normal file
@@ -0,0 +1,3 @@
|
||||
module leetcode-3516
|
||||
|
||||
go 1.18
|
71
problems/3516-find-closest-person/go/main.go
Normal file
71
problems/3516-find-closest-person/go/main.go
Normal 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"
|
||||
}
|
99
templates/logs-template.md.tmpl
Normal file
99
templates/logs-template.md.tmpl
Normal 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/效能注意點/測試習慣
|
||||
- Go:slice/map/指標/錯誤處理/benchmark 習慣
|
||||
|
||||
## 🔄 困難案例復盤
|
||||
|
||||
### 案例1:題號/主題
|
||||
- 問題:
|
||||
- 嘗試:
|
||||
- 解決:
|
||||
- 學習:
|
||||
|
||||
### 案例2:題號/主題
|
||||
- 問題:
|
||||
- 嘗試:
|
||||
- 解決:
|
||||
- 學習:
|
||||
|
||||
## 📝 下月計畫
|
||||
- 目標題數:
|
||||
- 重點主題:
|
||||
- 練習節奏:
|
||||
- 要避免的坑:
|
||||
|
||||
## 💡 本月金句
|
||||
>
|
||||
|
||||
---
|
||||
**總結**:本月最大收穫是 ______,接下來專注 ______。
|
||||
|
@@ -1,73 +0,0 @@
|
||||
# [題目編號] 題目名稱
|
||||
|
||||
## 題目資訊
|
||||
- **難度**: Easy/Medium/Hard
|
||||
- **標籤**: Array, Hash Table, Two Pointers, etc.
|
||||
- **題目連結**: [LeetCode](https://leetcode.com/problems/xxx/)
|
||||
- **練習日期**: YYYY-MM-DD
|
||||
|
||||
## 題目描述
|
||||
> 在這裡貼上題目的完整描述
|
||||
|
||||
## 解題思路
|
||||
|
||||
### 初步分析
|
||||
- 這題主要考察什麼概念?
|
||||
- 有什麼關鍵限制條件?
|
||||
- 預期時間/空間複雜度?
|
||||
|
||||
### 解法概述
|
||||
1. **暴力解法**:
|
||||
- 思路:
|
||||
- 時間複雜度:O(?)
|
||||
- 空間複雜度:O(?)
|
||||
|
||||
2. **優化解法**:
|
||||
- 思路:
|
||||
- 時間複雜度:O(?)
|
||||
- 空間複雜度:O(?)
|
||||
|
||||
## 實作細節
|
||||
|
||||
### C# 解法
|
||||
```csharp
|
||||
// 核心程式碼片段或關鍵邏輯說明
|
||||
```
|
||||
|
||||
### Go 解法
|
||||
```go
|
||||
// 核心程式碼片段或關鍵邏輯說明
|
||||
```
|
||||
|
||||
## 測試案例
|
||||
|
||||
### 範例輸入輸出
|
||||
```
|
||||
Input:
|
||||
Output:
|
||||
Explanation:
|
||||
```
|
||||
|
||||
### 邊界情況
|
||||
- [ ] 空陣列/空字串
|
||||
- [ ] 單一元素
|
||||
- [ ] 最大/最小值
|
||||
- [ ] 重複元素
|
||||
|
||||
## 學習筆記
|
||||
|
||||
### 今天學到什麼?
|
||||
-
|
||||
|
||||
### 遇到的困難
|
||||
-
|
||||
|
||||
### 改善方向
|
||||
-
|
||||
|
||||
### 相關題目
|
||||
- [題目編號] 題目名稱 - 相似概念
|
||||
- [題目編號] 題目名稱 - 進階版本
|
||||
|
||||
---
|
||||
**總結**: 這題的核心概念是...,適合練習...技巧。
|
105
templates/problem-template.md.tmpl
Normal file
105
templates/problem-template.md.tmpl
Normal 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:若輸入動態變化/資料流版本/線上查詢如何處理?
|
||||
|
||||
## 學習筆記
|
||||
- 今天學到:
|
||||
- 卡住點與修正:
|
||||
- 下次優化想法:
|
||||
|
||||
---
|
||||
**總結**:這題的核心在於 ______,適合練習 ______ 技巧。
|
||||
|
91
templates/problem/README.md.tmpl
Normal file
91
templates/problem/README.md.tmpl
Normal 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
|
||||
-
|
||||
|
||||
## 學習筆記
|
||||
- 今天學到:
|
||||
- 卡住與修正:
|
||||
- 待優化:
|
||||
|
||||
---
|
||||
**總結**:這題的核心在於 ______,適合練習 ______。
|
||||
|
24
templates/problem/csharp/Program.cs.tmpl
Normal file
24
templates/problem/csharp/Program.cs.tmpl
Normal 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}}!");
|
||||
}
|
||||
}
|
||||
|
5
legacy/498 FindDiagonalOrder/C#/FindDiagonalOrder.csproj → templates/problem/csharp/csharp.csproj.tmpl
Executable file → Normal file
5
legacy/498 FindDiagonalOrder/C#/FindDiagonalOrder.csproj → templates/problem/csharp/csharp.csproj.tmpl
Executable file → Normal file
@@ -1,10 +1,9 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user