1주차 1차 2 - LeetCode-Study-Team/solutions GitHub Wiki
70 Climbing Stairs / Easy / Dynamic Programming
class Solution {
private final static int[] caseStore = new int[46];
public int climbStairs(int n) {
if(n==0 || n==1 || n==2){
caseStore[n] = n;
return caseStore[n];
}
if(caseStore[n] > 2) {
return caseStore[n];
}
caseStore[n] = climbStairs(n-1) + climbStairs(n-2);
return caseStore[n];
}
}< 용어 정리 >
다이나믹 프로그래밍(Dynamic Programming)
특정 범위까지의 값을 구하기 위해서 그것과 다른 범위까지의 값을 이용하여 효율적으로 값을 구하는 알고리즘 설계 기법이다. 동적 계획법 답을 구하기 위해서 했던 계산을 또 하고 또 하고 계속해야 하는 종류의 문제에서 효과를 발휘한다. 이광근 교수의 저서 "컴퓨터 과학이 여는 세계"에서는 다이나믹 프로그래밍을 본질적인 의미를 더 살려서 기억하며 풀기로 더욱 적절하게 번역하였다.
분할 정복
분할 정복 알고리즘(Divide and conquer algorithm)은 그대로 해결할 수 없는 문제를 작은 문제로 분할하여 문제를 해결하는 방법이나 알고리즘이다.
동적 계획법과 분할 정복의 공통점과 차이점
[공통점] 문제를 작은 단위로 쪼개서 분할하여 접근함
[차이점] 동적 계획법은
- 중복되는 부분 문제가 상위 문제를 해결하는데 사용됨
- 메모이제이션을 활용
분할 정복은
- 부분 문제가 서로 중복되지 않음
- 메모이제이션을 활용하지 않음
출처 exp_blog [https://syujisu.tistory.com/147] (https://syujisu.tistory.com/147)
메모이제이션(Memoization)
컴퓨터 프로그래밍 용어로, 동일한 계산을 반복해야 할 경우 한 번 계산한 결과를 메모리에 저장해 두었다가 꺼내 씀으로써 중복 계산을 방지할 수 있게 하는 기법이다. 동적 계획법의 핵심이 되는 기술로써 결국 메모리라는 공간 비용을 투입해 계산에 소요되는 시간 비용을 줄이는 방식이다.
133 Clone Graph / medium / Graph
public Node cloneGraph(Node root) { //root : 복제 대상 노드
if (root == null) return null;
// use a queue to help BFS
Queue<Node> queue = new LinkedList<Node>();
queue.add(root);
// use a map to save cloned nodes
Map<Node, Node> map = new HashMap<Node, Node>();
// clone the root
map.put(root, new Node(root.val));
while (!queue.isEmpty()) {
Node node = queue.poll(); //poll() : 첫번째 값을 반환, 비어있다면 null 반환
// handle the neighbors
for (Node neighbor : node.neighbors) {
if (!map.containsKey(neighbor)) {
// clone the neighbor
map.put(neighbor, new Node(neighbor.val));
// add it to the next level
queue.add(neighbor);
}
// copy the neighbor
map.get(node).neighbors.add(map.get(neighbor));
}
}
return map.get(root);
}BFS(Breath-First Search)
너비 우선 탐색 특정 노드에서 시작해서 인접한 노드를 먼저 탐색하는 방식
DFS(Depth-Fisrt Search)
깊이 우선 탐색 깊이 갈 수 있는 만큼 최대한 가고, 더이상 갈 곳이 없다면 이전 정점으로 돌아가는 방식
큐(Queue)
먼저 들어온 데이터가 먼저 나가는 선입선출 방식의 자료구조
정점(vertice)
노드라고도 하며, 정점에는 데이터가 저장된다 (0, 1, 2, 3, 4)
엣지(edge)
정점을 잇는 선 엣지로 연결된 두 정점은 서로 알고있다는 관계를 의미
언다이렉트 그래프(undirected Graph)
엣지의 방향성이 없는 그래프
(정점1, 정점2)와 (정점2, 정점1)이 동일하다.
깊은 복사(Deep copy)
데이터 자체를 복사하는 것 복사된 두 객체는 완전히 독립적인 메모리를 차지한다 객체의 참조값이 아닌 실제 값을 복사하여 새로운 객체를 만들어 내는 것
얕은 복사(Shallow copy)
객체의 참조값(주소값)을 복사하는 것 복사한 객체의 속성을 변경하면 원본 객체에도 영향을 준다
57 Insert Interval / medium / Interval
class Solution {
public int[][] insert(int[][] intervals, int[] newInterval) {
int len = intervals.length;
int newLen = newInterval.length;
if(len == 0 && newLen == 0) { return new int[][]{}; }
if(len == 0 && newLen != 0) { return new int[][]{newInterval}; }
if(len != 0 && newLen == 0) { return intervals; }
List<int[]> store = new ArrayList<>();
int start = newInterval[0];
int end = newInterval[1];
int index = 0;
while (index < len && start > intervals[index][1]) {
store.add(new int[]{intervals[index][0], intervals[index][1]});
index++;
}
int left = newInterval[0];
int right = newInterval[1];
while (index < len && end >= intervals[index][0]) {
left = Math.min(left, intervals[index][0]);
right = Math.max(right, intervals[index][1]);
index++;
}
store.add(new int[]{left, right});
while (index < len) {
store.add(new int[]{intervals[index][0], intervals[index][1]});
index++;
}
int[][] new_intervals = new int[store.size()][2];
for(int i=0; i<store.size(); i++){
new_intervals[i] = store.get(i);
}
return new_intervals;
}
}영화배우가 영화를 선택하는 방법
- Shortest Interval
가장 구간이 짧은 영화들을 우선적으로 선택
- Eariest Left Endpoint
영화의 시작이 가장 왼쪽에 있는 영화를 우선적으로 선택
- Eariest Right Endpoint
영화가 끝나는 시점이 가장 왼쪽에 있는 영화를 우선적으로 선택 최적의 해 구할 수 있음
각 방법의 시간복잡도
- 구간이 가장 짧은 영화 : O(n^2)
- 끝나는 시점에서 가장 빨리 시작하는 영화 : O(n^2)
- 끝나는 시점에서 가장 빨리 끝나는 영화 : O(nlogn)
시간 복잡도
가장 간단한 정의는 알고리즘의 성능 알고리즘의 수행해야 하는 연산의 횟수를 수치화 한 것
빅오 표기법(Big-O)
빅오 표기법은 불필요한 연산을 제거하여 알고리즘 분석을 쉽게 할 목적으로 사용된다. 빅오 복잡성에는 시간복잡도와 공간복잡도가 있다 시간복잡도 : N의 크기에 따라 실행되는 조작의 수 공간복잡도 : 알고리즘이 실행될 때 사용하는 메모리의 양