2025-09/3025-find-the-number-of-ways-to-place-people-i #6
@@ -5,7 +5,9 @@
|
|||||||
### Week 1
|
### 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# | 0.5hr | Done | 二維點位判斷 |
|
||||||
|
| 09/02| Find The Number of Ways to Place People I | Medium | go | 0.2hr | Done | go Prictice |
|
||||||
|
|
||||||
### Week 2
|
### Week 2
|
||||||
| 日期 | 題目 | 難度 | 語言 | 耗時 | 狀態 | 心得 |
|
| 日期 | 題目 | 難度 | 語言 | 耗時 | 狀態 | 心得 |
|
||||||
@@ -25,13 +27,13 @@
|
|||||||
## 📈 本月統計
|
## 📈 本月統計
|
||||||
|
|
||||||
### 完成情況
|
### 完成情況
|
||||||
- **總練習天數**: 1 天
|
- **總練習天數**: 2 天
|
||||||
- **完成題數**: 1題
|
- **完成題數**: 2題
|
||||||
- **語言分布**: C# 1(題), Go 0(題)
|
- **語言分布**: C# 2(題), Go 1(題)
|
||||||
- **難度分布**: Easy 0(題), Medium 1(題), Hard 0(題)
|
- **難度分布**: Easy 0(題), Medium 2(題), Hard 0(題)
|
||||||
|
|
||||||
### 時間投入
|
### 時間投入
|
||||||
- **總時間**: 1小時
|
- **總時間**: 1.7小時
|
||||||
- **平均每題**: 分鐘
|
- **平均每題**: 分鐘
|
||||||
- **每日平均**: 分鐘
|
- **每日平均**: 分鐘
|
||||||
|
|
||||||
|
@@ -0,0 +1,69 @@
|
|||||||
|
# [3025] Find The Number Of Ways To Place People I
|
||||||
|
|
||||||
|
## 題目資訊
|
||||||
|
- **難度**: Medium
|
||||||
|
- **標籤**: Array, Math, Geometry, Sorting, Enumeration
|
||||||
|
- **題目連結**: [LeetCode](https://leetcode.com/problems/find-the-number-of-ways-to-place-people-i/)
|
||||||
|
- **練習日期**: 2025-09-02
|
||||||
|
|
||||||
|
## 題目描述
|
||||||
|
You are given a 2D array `points` of size `n x 2` representing integer coordinates of some points on a 2D plane, where `points[i] = [xi, yi]`.
|
||||||
|
|
||||||
|
Count the number of pairs of points `(A, B)`, where
|
||||||
|
- `A` is on **the upper** left side of `B`, and
|
||||||
|
- there are no other points in the rectangle (or line) they make (**including the border**).
|
||||||
|
|
||||||
|
Return the count.
|
||||||
|
|
||||||
|
## 解題思路
|
||||||
|
|
||||||
|
### 初步分析
|
||||||
|
- 核心概念
|
||||||
|
幾何關係判斷 + 區域內點的檢測
|
||||||
|
- 關鍵限制條件
|
||||||
|
1. A必須在B的左上方, A.x <= B.x, A.y >= B.y
|
||||||
|
2. 矩形區域內(包含邊界)不能有其他點
|
||||||
|
- 預期時間/空間複雜度?
|
||||||
|
|
||||||
|
### 解法概述
|
||||||
|
**解法**:
|
||||||
|
- 思路:
|
||||||
|
- 遍歷所有點對 (A, B)
|
||||||
|
- 檢查每個pair形成的矩形, 裡面跟邊界會不會包含其他點
|
||||||
|
- 時間複雜度:O(N^3)
|
||||||
|
- 空間複雜度:O(1)
|
||||||
|
|
||||||
|
## 測試案例
|
||||||
|
|
||||||
|
### 範例輸入輸出
|
||||||
|
```
|
||||||
|
Input: points = [[6,2],[4,4],[2,6]]
|
||||||
|
Output: 2
|
||||||
|
Explanation:
|
||||||
|
- The left one is the pair (points[1], points[0]), where points[1] is on the upper left side of points[0] and the rectangle is empty.
|
||||||
|
- The left one is the pair (points[1], points[0]), where points[1] is on the upper left side of points[0] and the rectangle is empty.
|
||||||
|
- The right one is the pair (points[2], points[0]), where points[2] is on the upper left side of points[0], but points[1] is inside the rectangle so it's not a valid pair.
|
||||||
|
```
|
||||||
|
|
||||||
|
### 邊界情況
|
||||||
|
- `2 <= n <= 50`
|
||||||
|
- `points[i].length == 2`
|
||||||
|
- `0 <= points[i][0], points[i][1] <= 50`
|
||||||
|
- All `points[i]` are distinct.
|
||||||
|
|
||||||
|
## 學習筆記
|
||||||
|
|
||||||
|
### 今天學到什麼?
|
||||||
|
- 二維空間判斷點大小
|
||||||
|
|
||||||
|
### 遇到的困難
|
||||||
|
- 無
|
||||||
|
|
||||||
|
### 改善方向
|
||||||
|
- 無
|
||||||
|
|
||||||
|
### 相關題目
|
||||||
|
- [#223](https://leetcode.com/problems/rectangle-area/) Rectangle Area
|
||||||
|
|
||||||
|
---
|
||||||
|
**總結**: 這題的核心概念是...,適合練習...技巧。
|
@@ -0,0 +1,86 @@
|
|||||||
|
// LeetCode 3025: Find The Number Of Ways To Place People I
|
||||||
|
// 難度: Medium
|
||||||
|
// 日期: 2025-09-02
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
public class Solution
|
||||||
|
{
|
||||||
|
public int NumberOfPairs(int[][] points)
|
||||||
|
{
|
||||||
|
// 遍歷所有點對 (A, B)
|
||||||
|
// 檢查每個pair形成的矩形, 裡面跟邊界會不會包含其他點
|
||||||
|
|
||||||
|
// points[0].Length == 2
|
||||||
|
int n = points.Length;
|
||||||
|
int count = 0;
|
||||||
|
|
||||||
|
for (var i = 0; i < n; i++)
|
||||||
|
{
|
||||||
|
for (var j = 0; j < n; j++)
|
||||||
|
{
|
||||||
|
if (i == j) continue;
|
||||||
|
|
||||||
|
int[] pointA = points[i];
|
||||||
|
int[] pointB = points[j];
|
||||||
|
|
||||||
|
// check if A.x <= B.x && A.y >= B.y
|
||||||
|
// if yes, check if any points in rectangle
|
||||||
|
if (pointA[0] <= pointB[0] && pointA[1] >= pointB[1])
|
||||||
|
{
|
||||||
|
// difinition of border
|
||||||
|
bool hasOtherPoint = false;
|
||||||
|
int minX = pointA[0];
|
||||||
|
int maxX = pointB[0];
|
||||||
|
int minY = pointB[1];
|
||||||
|
int maxY = pointA[1];
|
||||||
|
|
||||||
|
// check other point if its in border
|
||||||
|
for (var k = 0; k < n; k++)
|
||||||
|
{
|
||||||
|
if (k == i || k == j) continue;
|
||||||
|
|
||||||
|
var pointC = points[k];
|
||||||
|
if (minX <= pointC[0] && pointC[0] <= maxX
|
||||||
|
&& minY <= pointC[1] && pointC[1] <= maxY)
|
||||||
|
{
|
||||||
|
hasOtherPoint = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!hasOtherPoint) count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Program {
|
||||||
|
public static void Main() {
|
||||||
|
Solution solution = new Solution();
|
||||||
|
|
||||||
|
// 測試案例
|
||||||
|
TestCase(solution);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void TestCase(Solution solution) {
|
||||||
|
// Input:
|
||||||
|
int[][] points = new int[][] {
|
||||||
|
new int[] {6, 2},
|
||||||
|
new int[] {4, 4},
|
||||||
|
new int[] {2, 6}
|
||||||
|
};
|
||||||
|
// Expected:
|
||||||
|
Console.WriteLine($"Test Case: [[6,2],[4,4],[2,6]]");
|
||||||
|
Console.WriteLine($"Expected: 2");
|
||||||
|
|
||||||
|
// Actual:
|
||||||
|
int result1 = solution.NumberOfPairs(points);
|
||||||
|
Console.WriteLine($"Result: {result1}");
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,10 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
</Project>
|
@@ -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))
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,244 @@
|
|||||||
|
// LeetCode 3025 單元測試
|
||||||
|
// 使用 xUnit 框架
|
||||||
|
|
||||||
|
using Xunit;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
public class SolutionTests
|
||||||
|
{
|
||||||
|
private readonly Solution _solution;
|
||||||
|
|
||||||
|
public SolutionTests()
|
||||||
|
{
|
||||||
|
_solution = new Solution();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void TestCase1_ExampleFromProblem()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
int[][] points = new int[][] {
|
||||||
|
new int[] {6, 2},
|
||||||
|
new int[] {4, 4},
|
||||||
|
new int[] {2, 6}
|
||||||
|
};
|
||||||
|
int expected = 2;
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var result = _solution.NumberOfPairs(points);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Equal(expected, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void TestCase2_TwoPoints()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
int[][] points = new int[][] {
|
||||||
|
new int[] {1, 3},
|
||||||
|
new int[] {2, 1}
|
||||||
|
};
|
||||||
|
int expected = 1;
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var result = _solution.NumberOfPairs(points);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Equal(expected, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void TestCase3_NoValidPairs()
|
||||||
|
{
|
||||||
|
// Arrange - 沒有有效點對的情況
|
||||||
|
int[][] points = new int[][] {
|
||||||
|
new int[] {1, 1},
|
||||||
|
new int[] {2, 2},
|
||||||
|
new int[] {3, 3}
|
||||||
|
};
|
||||||
|
int expected = 0;
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var result = _solution.NumberOfPairs(points);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Equal(expected, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void TestCase4_SameXCoordinate()
|
||||||
|
{
|
||||||
|
// Arrange - x 座標相同的情況
|
||||||
|
int[][] points = new int[][] {
|
||||||
|
new int[] {3, 5},
|
||||||
|
new int[] {3, 2},
|
||||||
|
new int[] {3, 1}
|
||||||
|
};
|
||||||
|
int expected = 2;
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var result = _solution.NumberOfPairs(points);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Equal(expected, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void TestCase5_SameYCoordinate()
|
||||||
|
{
|
||||||
|
// Arrange - y 座標相同的情況
|
||||||
|
int[][] points = new int[][] {
|
||||||
|
new int[] {1, 4},
|
||||||
|
new int[] {3, 4},
|
||||||
|
new int[] {5, 4}
|
||||||
|
};
|
||||||
|
int expected = 2;
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var result = _solution.NumberOfPairs(points);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Equal(expected, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void TestCase6_PointsInsideRectangle()
|
||||||
|
{
|
||||||
|
// Arrange - 矩形內有其他點的情況
|
||||||
|
int[][] points = new int[][] {
|
||||||
|
new int[] {0, 4}, // A
|
||||||
|
new int[] {4, 0}, // B
|
||||||
|
new int[] {2, 2} // C (在 A-B 矩形內)
|
||||||
|
};
|
||||||
|
|
||||||
|
int expected = 2;
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var result = _solution.NumberOfPairs(points);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Equal(expected, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void TestCase7_PointsOnBorder()
|
||||||
|
{
|
||||||
|
// Arrange - 點在矩形邊界上的情況
|
||||||
|
int[][] points = new int[][] {
|
||||||
|
new int[] {0, 3}, // A
|
||||||
|
new int[] {3, 0}, // B
|
||||||
|
new int[] {0, 0} // C (在矩形邊界上)
|
||||||
|
};
|
||||||
|
int expected = 2; // (A,C) 和 (C,B) 有效
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var result = _solution.NumberOfPairs(points);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Equal(expected, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void TestEdgeCases_MinimumPoints()
|
||||||
|
{
|
||||||
|
// Arrange - 最少點數情況 (題目限制 n >= 2)
|
||||||
|
int[][] points = new int[][] {
|
||||||
|
new int[] {0, 1},
|
||||||
|
new int[] {1, 0}
|
||||||
|
};
|
||||||
|
int expected = 1; // (0,1) 在 (1,0) 的左上方
|
||||||
|
|
||||||
|
// Act
|
||||||
|
int result = _solution.NumberOfPairs(points);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Equal(expected, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void TestEdgeCases_IdenticalCoordinates()
|
||||||
|
{
|
||||||
|
// Arrange - 座標值相同的情況
|
||||||
|
int[][] points = new int[][] {
|
||||||
|
new int[] {2, 2},
|
||||||
|
new int[] {2, 2} // 題目保證所有點都不同,但測試邊界
|
||||||
|
};
|
||||||
|
|
||||||
|
// 這個測試案例實際上違反了題目條件 (All points[i] are distinct)
|
||||||
|
// 但可以測試程式的健壯性
|
||||||
|
int expected = 2; // 兩個相同點互相滿足左上方條件
|
||||||
|
|
||||||
|
// Act
|
||||||
|
int result = _solution.NumberOfPairs(points);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Equal(expected, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void TestEdgeCases_MaxCoordinateValues()
|
||||||
|
{
|
||||||
|
// Arrange - 最大座標值情況 (題目限制 0 <= coordinates <= 50)
|
||||||
|
int[][] points = new int[][] {
|
||||||
|
new int[] {0, 50},
|
||||||
|
new int[] {50, 0},
|
||||||
|
new int[] {25, 25}
|
||||||
|
};
|
||||||
|
int expected = 2; // (A,C) 和 (C,B) 有效
|
||||||
|
|
||||||
|
// Act
|
||||||
|
int result = _solution.NumberOfPairs(points);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Equal(expected, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void TestEdgeCases_EmptyArray()
|
||||||
|
{
|
||||||
|
// Arrange - 空陣列情況
|
||||||
|
int[][] points = new int[0][];
|
||||||
|
int expected = 0;
|
||||||
|
|
||||||
|
// Act
|
||||||
|
int result = _solution.NumberOfPairs(points);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Equal(expected, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void TestEdgeCases_MaxPoints_AllDistinct_RandomPattern() {
|
||||||
|
// Arrange - 50個不同的點,更複雜的模式
|
||||||
|
var points = new List<int[]>();
|
||||||
|
|
||||||
|
// 創建一個螺旋模式的50個不同點,確保都在 [0,50] 範圍內且互不相同
|
||||||
|
var usedPoints = new HashSet<string>();
|
||||||
|
var random = new Random(42); // 固定種子確保測試可重現
|
||||||
|
|
||||||
|
while (points.Count < 50) {
|
||||||
|
int x = random.Next(0, 51); // 0-50
|
||||||
|
int y = random.Next(0, 51); // 0-50
|
||||||
|
string pointKey = $"{x},{y}";
|
||||||
|
|
||||||
|
if (!usedPoints.Contains(pointKey)) {
|
||||||
|
usedPoints.Add(pointKey);
|
||||||
|
points.Add(new int[] { x, y });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int[][] pointsArray = points.ToArray();
|
||||||
|
|
||||||
|
// 由於是隨機分佈,很難預測確切結果,但應該是一個合理的正數
|
||||||
|
// 這個測試主要驗證程式在最大輸入時不會崩潰或超時
|
||||||
|
|
||||||
|
// Act
|
||||||
|
int result = _solution.NumberOfPairs(pointsArray);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.True(result >= 0); // 至少結果應該是非負數
|
||||||
|
Assert.True(result <= 50 * 49); // 最多不會超過所有可能的點對
|
||||||
|
}
|
||||||
|
}
|
@@ -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>
|
@@ -0,0 +1,13 @@
|
|||||||
|
# 邊界情況清單
|
||||||
|
|
||||||
|
## 需要測試的邊界情況
|
||||||
|
- [x] 空輸入 (空陣列) - `TestEdgeCases_EmptyArray`
|
||||||
|
- [x] 最少元素 (n=2) - `TestEdgeCases_MinimumPoints`
|
||||||
|
- [x] 重複座標 (雖然違反題目條件) - `TestEdgeCases_IdenticalCoordinates`
|
||||||
|
- [x] 最大值/最小值 (座標範圍 [0,50]) - `TestEdgeCases_MaxCoordinateValues`
|
||||||
|
- [x] 最大資料量 (n=50) - `TestEdgeCases_MaxPoints_AllDistinct_RandomPattern`
|
||||||
|
- [x] 相同 x 座標 - `TestCase4_SameXCoordinate`
|
||||||
|
- [x] 相同 y 座標 - `TestCase5_SameYCoordinate`
|
||||||
|
- [x] 矩形內含其他點 - `TestCase6_PointsInsideRectangle`
|
||||||
|
- [x] 點在矩形邊界上 - `TestCase7_PointsOnBorder`
|
||||||
|
- [x] 無有效點對情況 - `TestCase3_NoValidPairs`
|
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 "📊 測試完成!"
|
Reference in New Issue
Block a user