Skip to content

Commit

Permalink
Merge branch 'DaleStudy:main' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
jinah92 authored Dec 20, 2024
2 parents a01d15d + 3854db0 commit 2d466a8
Show file tree
Hide file tree
Showing 264 changed files with 7,411 additions and 9 deletions.
5 changes: 5 additions & 0 deletions .github/labeler.yml
Original file line number Diff line number Diff line change
Expand Up @@ -52,3 +52,8 @@ elixir:
- changed-files:
- any-glob-to-any-file:
- "**/*.exs"

rust:
- changed-files:
- any-glob-to-any-file:
- "**/*.rs"
10 changes: 6 additions & 4 deletions .github/pull_request_template.md
Original file line number Diff line number Diff line change
@@ -1,17 +1,19 @@
## 답안 제출 문제

<!--
자신의 수준이나 일정에 맞게 금주에 푸시기로 정한 문제들만 나열해주세요.
코드 검토자들이 PR 승인 여부를 결정할 때 도움이 됩니다.
자신의 수준이나 일정에 맞게 👉금주에 푸시기로 정한 문제들👈만 나열해주세요.
리뷰어들이 검토와 PR 승인 여부를 결정할 때 도움이 됩니다.
-->

- [ ] 문제 1
- [ ] 문제 2
- [ ] 문제 3
<!-- - [ ] 문제 4 풀고싶지 않은 문제는 이렇게 주석처리 해 주셔도 좋아요 -->

## 체크 리스트

- [ ] PR을 프로젝트에 추가하고 Week를 현재 주차로 설정해주세요.
- [ ] 우측 메뉴에서 PR을 **Projects**에 추가해주세요.
- [ ] **Projects**의 오른쪽 버튼(▼)을 눌러 확장한 뒤, **Week**를 현재 주차로 설정해주세요.
- [ ] 바로 앞에 PR을 열어주신 분을 코드 검토자로 지정해주세요.
- [ ] 문제를 모두 푸시면 프로젝트에서 Status를 `In Review`로 설정해주세요.
- [ ] 문제를 모두 푸시면 프로젝트에서 **Status** `In Review`로 설정해주세요.
- [ ] 코드 검토자 1분 이상으로부터 승인을 받으셨다면 PR을 병합해주세요.
52 changes: 47 additions & 5 deletions .github/workflows/integration.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,19 @@ jobs:
- name: Get PR labels
id: pr-labels
run: |
echo "🔍 PR 번호: ${{ github.event.pull_request.number }}"
pr_number="${{ github.event.pull_request.number }}"
echo "📋 PR 라벨 조회 중..."
labels_json=$(gh pr view $pr_number --json labels -q '.labels[].name')
echo "확인된 라벨: $labels_json"
if [ -n "$labels_json" ]; then
echo "has_maintenance=$(echo $labels_json | grep -q 'maintenance' && echo 'true' || echo 'false')" >> $GITHUB_OUTPUT
has_maintenance=$(echo $labels_json | grep -q 'maintenance' && echo 'true' || echo 'false')
echo "maintenance 라벨 포함 여부: $has_maintenance"
echo "has_maintenance=$has_maintenance" >> $GITHUB_OUTPUT
else
echo "maintenance 라벨이 없는 PR입니다. 파일명 규칙 검사를 진행합니다."
echo "has_maintenance=false" >> $GITHUB_OUTPUT
fi
env:
Expand All @@ -28,35 +36,46 @@ jobs:
# 줄바꿈 체크
- name: Check for missing end line breaks
run: |
# 따옴표를 제거하고 파일 목록 가져오기
echo "🔍 줄바꿈 검사 시작"
echo "기준 커밋: ${{ github.event.pull_request.base.sha }}"
echo "현재 커밋: ${{ github.sha }}"
files=$(git diff --name-only ${{ github.event.pull_request.base.sha }} ${{ github.sha }} | tr -d '"')
success=true
echo "변경된 파일 목록:"
echo "📝 변경된 파일 목록:"
echo "$files"
echo "## 줄바꿈 누락 파일" >> $GITHUB_STEP_SUMMARY
for file in $files; do
echo "검사 중: $file"
if [ -s "$file" ] && [ "$(tail -c 1 $file | wc -l)" -eq 0 ]; then
echo "발견된 줄바꿈 누락: $file"
echo " 줄바꿈 누락: $file"
echo "- $file" >> $GITHUB_STEP_SUMMARY
success=false
else
echo "✅ 정상: $file"
fi
done
if [ "$success" = false ]; then
echo "⚠️ 줄바꿈 검사 실패"
echo -e "\n:warning: 파일 끝의 누락된 줄바꿈을 추가해 주세요." >> $GITHUB_STEP_SUMMARY
exit 1
else
echo "✅ 모든 파일의 줄바꿈 정상"
fi
# 제어문자 체크
- name: Check for control characters in filenames
run: |
echo "🔍 파일명 제어문자 검사 시작"
files=$(git diff --name-only ${{ github.event.pull_request.base.sha }} ${{ github.sha }} | tr -d '"')
success=true
echo "## 제어문자가 포함된 파일명" >> $GITHUB_STEP_SUMMARY
for file in $files; do
echo "검사 중: $file"
# basename으로 파일명만 추출하고 따옴표 제거
filename=$(basename "$file" | tr -d '"')
Expand All @@ -71,43 +90,66 @@ jobs:
# 이스케이프 시퀀스 체크
[[ "$filename" =~ (\\[0-7]{1,3}|\\x[0-9a-fA-F]{1,2}) ]]; then
echo "❌ 제어문자 발견: $file"
echo "- $file (제어문자 포함)" >> $GITHUB_STEP_SUMMARY
success=false
else
echo "✅ 정상: $file"
fi
done
if [ "$success" = false ]; then
echo "⚠️ 제어문자 검사 실패"
echo -e "\n:warning: 파일명에서 제어문자를 제거해 주세요." >> $GITHUB_STEP_SUMMARY
exit 1
else
echo "✅ 모든 파일명이 제어문자 없이 정상"
fi
# 파일명 규칙 체크 - maintenance 라벨이 없는 경우에만 실행
- name: Check filename rules
if: ${{ steps.pr-labels.outputs.has_maintenance != 'true' }}
run: |
files=$(git diff --name-only ${{ github.event.pull_request.base.sha }} ${{ github.event.pull_request.head.sha }} | tr -d '"')
echo "🔍 파일명 규칙 검사 시작"
echo "PR 작성자: ${{ github.event.pull_request.user.login }}"
# PR의 공통 조상 커밋을 찾아서 merge base로 설정
merge_base=$(git merge-base ${{ github.event.pull_request.base.sha }} ${{ github.event.pull_request.head.sha }})
echo "Merge base 커밋: $merge_base"
files=$(git diff --name-only $merge_base ${{ github.event.pull_request.head.sha }} | tr -d '"')
pr_author="${{ github.event.pull_request.user.login }}"
success=true
echo "📝 검사할 파일 목록:"
echo "$files"
echo "## 파일명 규칙 위반" >> $GITHUB_STEP_SUMMARY
for file in $files; do
if [ -f "$file" ]; then
echo "검사 중: $file"
# 파일명만 추출 (경로 제외)
filename=$(basename "$file")
# 파일명이 GitHub계정명인지 확인
shopt -s nocasematch
if [[ ! "$filename" = "$pr_author"* ]]; then
echo "❌ 규칙 위반: $file"
echo "- $file" >> $GITHUB_STEP_SUMMARY
success=false
else
echo "✅ 정상: $file"
fi
fi
done
if [ "$success" = false ]; then
echo "⚠️ 파일명 규칙 검사 실패"
echo -e "\n:warning: 파일명은 반드시 'GitHub계정명' 또는 'GitHub계정명-xxx' 형식으로 해주셔야 합니다. (예: ${pr_author}.ts, ${pr_author}-1.ts, ${pr_author}-2.ts)" >> $GITHUB_STEP_SUMMARY
exit 1
else
echo "✅ 모든 파일명이 규칙에 맞게 정상"
fi
env:
GH_TOKEN: ${{ github.token }}
48 changes: 48 additions & 0 deletions 3sum/GangBean.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
class Solution {
public List<List<Integer>> threeSum(int[] nums) {
/**
1. understanding
- integer array nums, find the whole combination of 3 nums, and the sum of the 3 nums equal to 0. And don't allow reusing same indiced number(but can duplicate in value)
2. solve strategy
- brute force
- in every combination, validate sum of the nums equal to 0
- but it can take O(N^3) times where N is the length of input array, and given that the N can be 3000 at most(3 * 10^3), time can be 27 * 10^9, which takes too long...
- sort and two pointers
- sort nums in ascending order, so move the left pointer to right means the sum of window is getting bigger.
- and mid pointer set to left + 1 index
- if sum of pointers is less than 0, then move mid pointer to right, until the sum is bigger than 0, and while processing them, if the sum of pointers is 0, then add the combination to the return list.
- [-4, -1, -1, 0, 1, 2]:
3. complexity
- time: O(N^2) -> each left pointer, you can search at most N-1, and left pointer's range is [0, N-1), so the max length is N-1 for left index pointer.
- space: O(1) -> no extra space is needed
*/
// 0. assign return variable Set
Set<List<Integer>> answer = new HashSet<>();

// 1. sort the num array in ascending order
Arrays.sort(nums); // O(NlogN)
// Arrays.stream(nums).forEach(System.out::println);

// 3. move the mid pointer from left to right to find the combination of which's sum is 0, and if the sum is over 0, and then move right pointer to the left. else if the sum is under 0, then move left pointer to right direction.
for (int left = 0; left < nums.length - 1; left++) {
int mid = left + 1;
int right = nums.length - 1;
while (mid < right) {
// System.out.println(String.format("%d,%d,%d", nums[left], nums[mid], nums[right]));
int sum = nums[left] + nums[mid] + nums[right];
if (sum > 0) {
right--;
} else if (sum == 0) {
answer.add(List.of(nums[left], nums[mid], nums[right]));
right--;
} else {
mid++;
}
}
}

return new ArrayList<>(answer);
}
}

46 changes: 46 additions & 0 deletions 3sum/easyone-jwlee.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// 풀이
// 배열을 정렬하고
// two pointer 사용

// TC
// 정렬 O(nlogn) + Two pointer 이중 루프 O(n^2) = O(n^2)

// SC
// Go의 sort.Ints()는 TimSort를 사용.
// Merge Sort와 Insertion Sort의 조합으로 동작.
// 정렬 O(n) + Two pointer O(1) + 결과 배열 O(n) = O(n)

func threeSum(nums []int) [][]int {
result := [][]int{}
sort.Ints(nums) // nums를 정렬

for i := 0; i < len(nums)-2; i++ {
if i > 0 && nums[i] == nums[i-1] {
continue // 중복된 값 건너뜀
}

left, right := i+1, len(nums)-1
for left < right {
sum := nums[i] + nums[left] + nums[right]
if sum == 0 {
result = append(result, []int{nums[i], nums[left], nums[right]})
left++
right--

// 중복 제거
for left < right && nums[left] == nums[left-1] {
left++
}
for left < right && nums[right] == nums[right+1] {
right--
}
} else if sum < 0 {
left++
} else {
right--
}
}
}

return result
}
35 changes: 35 additions & 0 deletions climbing-stairs/GangBean.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
class Solution {
public int climbStairs(int n) {
/**
1. Understanding
- return the count of ways to climb up to top
- way means the sequence of step count
- each state, there can be 2 ways. first climb 1 step, second climb 2 step
2. solve strategy
- assume the count of ways to climb up to K th stairs is C[K].
- then, C[0] = 1, C[1] = 1, C[2] = 2(because, you can up to 2nd stair from 0th stair and also from 1st stair.)
- and C[3] = C[2] + C[1], C[4] = C[3] + C[2], ... etc...
- so we can fomulate C[k] = C[k-1] + C[k-2]
- iterate over 0 to n, you can caculate C[k].
- and finally return C[n] is the answer.
3. complexity
- I answer to this part, along with coding upon each line description.
*/

// 1. create array to demonstrate each stairs way count to reach that position.
// the maximun step count is 45, so maybe there is over 2^32(approximately 2 billion; so i worry about the overflow), I assign long type array. Oh.. but i catch that return type of this method is integer, so i can assume that maximum value is under integer range. So, assign as integer.
int[] c = new int[n + 1]; // the extra plus 1 means 0th stair state
// space complexity: O(n)
for (int stair = 0; stair <= n; stair++) { // time complexity O(n)
if (stair <= 1) {
c[stair] = 1; // O(1)
continue;
}
c[stair] = c[stair-1] + c[stair-2]; // O(1)
}

return c[n];
}
}

23 changes: 23 additions & 0 deletions climbing-stairs/easyone-jwlee.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// 풀이
// 1 일 때, 가능한 step은 1 -> 1가지
// 2 일 때, 가능한 step은 1 1, 2 -> 2가지
// 3 일 때, 가능한 step은 1 1 1, 1 2, 2 1 -> 3가지
// n 일 때, 가능한 stop은 n-1의 가짓수에 1이 붙고, n-2의 가짓수에 2가 붙는다.

// TC
// O(n)

// SC
// int타입 변수만 사용해서 O(1)

func climbStairs(n int) int {
if n <= 2 {
return n
}
prev := 1 // climb1
curr := 2 // climb2
for i := 3; i <= n; i++ {
prev, curr = curr, (curr + prev)
}
return curr
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public TreeNode buildTree(int[] preorder, int[] inorder) {
/**
1. understanding
- preorder: mid -> left -> right
- inorder: left -> mid -> right
- so, first element of the preorder array is always mid node.
- if the idx of inorder's 1st depth mid node is k, then inorder[0:k-1] is the left tree part array. And also, preorder[k:] is the right tree part.
2. strategy
- find the inorder's mid node idx, and then split left tree part and right part, buildTree with each preorder and inorder part.
3. complexity
- time: O(N^2)
- space: O(N^2)
*/
if (preorder.length == 0) return null;
if (preorder.length == 1) return new TreeNode(preorder[0]);
int i = 0;
List<Integer> leftPreorder = new ArrayList<>(); // O(N)
List<Integer> leftInorder = new ArrayList<>(); // O(N)
List<Integer> rightPreorder = new ArrayList<>(); // O(N)
List<Integer> rightInorder = new ArrayList<>(); // O(N)
for (; i < inorder.length; i++) { // O(N)
if (inorder[i] == preorder[0]) break;
leftPreorder.add(preorder[i+1]);
leftInorder.add(inorder[i]);
}
for (int idx = i+1; idx < inorder.length; idx++) { // O(N)
rightPreorder.add(preorder[idx]);
rightInorder.add(inorder[idx]);
}

return new TreeNode(preorder[0], buildTree(leftPreorder.stream().mapToInt(Integer::intValue).toArray(), leftInorder.stream().mapToInt(Integer::intValue).toArray()), buildTree(rightPreorder.stream().mapToInt(Integer::intValue).toArray(), rightInorder.stream().mapToInt(Integer::intValue).toArray()));
}
}

Loading

0 comments on commit 2d466a8

Please sign in to comment.