Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions climbing-stairs/taekwon-dev.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/**
* 시간 복잡도: O(n)
* - n = 5 경우를 가정하고 생각해보기
* - 3층 계단 -> 2층, 1층 계산 (이 경우는 이미 메모되어 있어서 별도로 계산하진 않음)
* - 4층 계단 -> 3층, 2층 계산 (2층은 메모에 있는 것 활용)
* - 5층 계단 -> 4층, 3층 계산 (3층은 메모에 있는 것 활용)
* - ...
* - 각 단계 별로 (메모를 활용해) 아직 계산되지 않은 것을 한 번씩 호출하게 되므로 O(n)
* - 근데 만약 메모를 사용하지 않으면? (중복 호출이 많이 일어남 ... O(n^2))
Comment on lines +2 to +9
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

풀이를 따라갈 수 있어 이해하기 좋았습니다! 고생하셨습니다!

*
* 공간 복잡도: O(n)
*/
class Solution {
public int climbStairs(int n) {
int[] memo = new int[n + 1];
return climbStairs(n, memo);
}

public int climbStairs(int n, int[] memo) {
if (n == 1) return 1;
if (n == 2) return 2;

if (memo[n] > 0) return memo[n];

memo[n] = climbStairs(n - 1, memo) + climbStairs(n - 2, memo);
return memo[n];
}
}
46 changes: 46 additions & 0 deletions combination-sum/taekwon-dev.java
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

풀이와 설명이 깔끔해서 좋았습니다!

Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/**
* 알고리즘: 백트랙킹
* 시간 복잡도: O(n^t)
* - n: candidates.lenth
* - t: target / candidates의 최솟값
* - 예시를 통해 시간 복잡도를 이해해보자!
*
* - candidates: [2, 3], target: 6
* - [2] -> [2, 2] -> [2, 2, 2] -> OK (여기서 생각해보면, 아 재귀를 최대 6/2 만큼 타고 들어가겠군?)
* - [2, 2] -> [2, 2, 3] -> X
* - [2] -> [2, 3] -> [2, 3, 3] -> X
* - [3] -> [3, 3] -> OK
* - 중간에 sum > target, sum == target 인 경우 return 하기 때문에 모든 케이스를 다 검사하진 않지만
* - 기본적으로 아래와 같이 문제를 풀게 될 경우 최악의 경우에는 O(n^t) 만큼 소요된다.
*
* 공간 복잡도: O(t)
* - t: target / candidates의 최솟값
* - 이것도 생각해보니까 주어진 candidates.length (=n) 값에 비례하는 게 아니라
* - (가능한 케이스에서) 가장 작은 값으로 타겟을 채우는 게 가장 많은 사이즈를 차지하는 값이 될텐데, 이것에 영향을 받겠군.
*
*/
class Solution {

private List<List<Integer>> answer = new ArrayList<>();
private List<Integer> combination = new ArrayList<>();

public List<List<Integer>> combinationSum(int[] candidates, int target) {
backtracking(candidates, target, 0, 0);
return answer;
}

private void backtracking(int[] candidates, int target, int sum, int start) {
if (sum > target) {
return;
}
if (sum == target) {
answer.add(new ArrayList<>(combination));
return;
}
for (int i = start; i < candidates.length; i++) {
combination.add(candidates[i]);
backtracking(candidates, target, sum + candidates[i], i);
combination.remove(combination.size() - 1);
}
}
}
18 changes: 18 additions & 0 deletions two-sum/taekwon-dev.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/**
* 시간/공간 복잡도: O(n)
*/
class Solution {
public int[] twoSum(int[] nums, int target) {
Map<Integer, Integer> map = new HashMap<>();

for (int idx = 0; idx < nums.length; idx++) {
int complement = target - nums[idx];
if (map.containsKey(complement)) {
return new int[]{map.get(complement), idx};
}
map.put(nums[idx], idx);
}

return new int[]{-1, -1};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

저는 js를 사용하여 이와 비슷한 방식으로 풀이를 했는데요,

마지막에 return new int[]{-1, -1}; 의 역할이 궁금합니다!

Copy link
Contributor Author

@taekwon-dev taekwon-dev Aug 29, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@seona926 안녕하세요! 질문 감사합니다.

우선 결론부터 말씀드리면 해당 코드는 풀이와 관련한 의미를 가지진 않습니다! Java 문법상 어쩔 수 없이 추가한 부분이라고 보시면 좋은데요. 우선 문제 조건에 유일한 정답 케이스가 있다고 안내가 되어 있었어요. 근데 제가 푼 방향이 루프 속에서 중간에 정답 케이스를 찾으면 early return 하는 방식이었고요.

public int[] twoSum(int[] nums, int target) {
    Map<Integer, Integer> map = new HashMap<>();
    
    for (int idx = 0; idx < nums.length; idx++) {
        int complement = target - nums[idx];
        if (map.containsKey(complement)) {
           // 문제 제한 조건 상 중간에 반드시 이 리턴문이 실행돼서, 마지막 리턴문 실행 안됨.
            return new int[]{map.get(complement), idx};  
        }
        map.put(nums[idx], idx);
    }
    
    // 이 부분은 실행되지 않지만, 문법적으로 반드시 이 메서드는 int[] 를 리턴해야 함
    return new int[]{-1, -1}; 
}

사실 위 코드에서 중간에 early return 이 반드시 되기 때문에 마지막 줄에 있는 return 문이 실행되지는 않습니다. 그런데 만약에 early return 부분만 있다면, 문법상 해당 메서드가 특정 조건에는 int[] 를 반환하지만 반대로 조건에 부합하지 못한 경우에는 결국 메서드에 정의한 리턴 타입인 int[]를 반환하지 못하기 때문에 마지막 줄과 같이 리턴문을 보충해야 메서드 정의에 맞게 동작하기 때문에 위와 같이 추가한 상황입니다.!

}
}