Skip to content

Commit 941ab12

Browse files
committed
- 8주차 풀이 커밋
1 parent e8fe2f5 commit 941ab12

File tree

4 files changed

+264
-0
lines changed

4 files changed

+264
-0
lines changed

clone-graph/Geegong.java

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
import java.util.*;
2+
3+
/*
4+
// Definition for a Node.
5+
class Node {
6+
public int val;
7+
public List<Node> neighbors;
8+
public Node() {
9+
val = 0;
10+
neighbors = new ArrayList<Node>();
11+
}
12+
public Node(int _val) {
13+
val = _val;
14+
neighbors = new ArrayList<Node>();
15+
}
16+
public Node(int _val, ArrayList<Node> _neighbors) {
17+
val = _val;
18+
neighbors = _neighbors;
19+
}
20+
}
21+
*/
22+
public class Geegong {
23+
24+
/**
25+
* dfs 방식으로 풀이
26+
* visited 로 memoization 하여 방문해서 복사가 된 노드들을 저장
27+
* 한번 방문했던 노드를 neighbors 탐색을 통해 또 방문하게 되면 visited 에서 꺼내서 return 하도록 한다.
28+
*
29+
* time complexity : O(2N) -> O(N)
30+
* space complexity : O(N)
31+
* @param node
32+
* @return
33+
*/
34+
public Node cloneGraph(Node node) {
35+
// node에 진입한 순간에 바로 visited 에 넣어서 cloned 된 node 들을 집어넣도록 관리
36+
Map<Integer, Node> visited = new HashMap<>();
37+
38+
if (node == null) {
39+
return null;
40+
}
41+
42+
Node result = cloneDeeply(node, visited);
43+
return result;
44+
}
45+
46+
public Node cloneDeeply(Node origin, Map<Integer, Node> visited) {
47+
48+
// visited 에는 cloned 된 node 들을 저장하고 있어 한번 방문했던 노드라면 복사한 노드를 리턴한다.
49+
if (visited.containsKey(origin.val)) {
50+
return visited.get(origin.val);
51+
}
52+
53+
Node clonedTarget = new Node(origin.val);
54+
visited.put(origin.val, clonedTarget);
55+
56+
for (Node neighbor : origin.neighbors) {
57+
Node clonedNeighbor = cloneDeeply(neighbor, visited);
58+
clonedTarget.neighbors.add(clonedNeighbor);
59+
}
60+
61+
return clonedTarget;
62+
}
63+
64+
65+
// 이미 다른 분들이 Node 클래스를 많이 만들어놓으셔서.. 개인 클래스 안에 이너 클래스로 Node 만듬
66+
public static class Node {
67+
public int val;
68+
public List<Node> neighbors;
69+
public Node() {
70+
val = 0;
71+
neighbors = new ArrayList<Node>();
72+
}
73+
public Node(int _val) {
74+
val = _val;
75+
neighbors = new ArrayList<Node>();
76+
}
77+
public Node(int _val, ArrayList<Node> _neighbors) {
78+
val = _val;
79+
neighbors = _neighbors;
80+
}
81+
}
82+
}
83+
84+
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
import java.util.ArrayList;
2+
import java.util.Collections;
3+
import java.util.Comparator;
4+
import java.util.List;
5+
6+
public class Geegong {
7+
8+
/**
9+
* LIS, LCS 와 연관지어서 풀이
10+
* 1. 먼저 text1을 훑어보는데 text1에 중복되는 알파벳이 있을 수 있기에 각 캐릭터별로 인덱스들을 저장 (각 원소가 arrayList가 있는 배열)
11+
* 2. text2 를 훑으면서 매칭되는 캐릭터들에 대해서만 1에서 저장된 인덱스들을 한 배열안에 나열
12+
* -> 이떄 나열해서 넣을때마다 역순으로 집어넣는게 중요! (왜냐면 이 나열된 인덱스들을 가지고 LIS를 구할거라서)
13+
* 3. 나열된 인덱스들의 값들을 가지고 LIS 를 구한다, 즉 이 LIS의 길이가 LCS 의 길이가 된다..!! (와우 신기)
14+
* 그러나 leet code 에 돌렸을 때 runtime 이 영 좋지는 않음
15+
*
16+
* time complexity : O(M + N logN) => text2에 대해서 문자마다 바이너리서치가 수행됨
17+
* space complexity : O(M+N)
18+
* @param text1
19+
* @param text2
20+
* @return
21+
*/
22+
public int longestCommonSubsequence(String text1, String text2) {
23+
char[] chText1 = text1.toCharArray();
24+
char[] chText2 = text2.toCharArray();
25+
26+
// text1만 각 원소 별로 char가 가지는 index를 array 로 갖는 배열을 생성
27+
List<Integer>[] positionIndices = new List[26];
28+
for (int index = 0; index<chText1.length; index++) {
29+
if (positionIndices[chText1[index] - 'a'] == null) {
30+
positionIndices[chText1[index] - 'a'] = new ArrayList();
31+
positionIndices[chText1[index] - 'a'].add(index);
32+
} else {
33+
positionIndices[chText1[index] - 'a'].add(index);
34+
}
35+
}
36+
37+
38+
// 여기서부터 LIS 를 구할것임
39+
List<Integer> indices = new ArrayList<>();
40+
for (int index=0; index<chText2.length; index++) {
41+
42+
char find = chText2[index];
43+
if (positionIndices[find-'a'] != null && positionIndices[find-'a'].size() > 0) {
44+
// 역순 (LIS 를 구하기 위해서 일부러 뒤집어 높음, 즉 각 char 별 LIS 를 구할것이기 때문에..)
45+
// positionIndices 에서 구했던 값들을 그대로 addAll 한다면 오름차순이 되기때문에 정확한 LIS 를 구할 수 없다
46+
47+
indices.addAll(positionIndices[find-'a'].stream().sorted(Comparator.reverseOrder()).toList());
48+
}
49+
}
50+
51+
// find LIS
52+
return findLIS(indices).size();
53+
}
54+
55+
public List<Integer> findLIS(List<Integer> source) {
56+
if (source.size() == 0) {
57+
return source;
58+
}
59+
60+
List<Integer> LISResult = new ArrayList<>();
61+
for (int index=0; index<source.size(); index++) {
62+
int target = source.get(index);
63+
int insertionPosition = Collections.binarySearch(LISResult, target);
64+
//Returns:
65+
//the index of the search key, if it is contained in the list;
66+
// otherwise, (-(insertion point) - 1). The insertion point is defined as the point at which the key would be inserted into the list:
67+
if (insertionPosition < 0) {
68+
insertionPosition = -insertionPosition - 1;
69+
}
70+
71+
if (LISResult.size() == insertionPosition) {
72+
LISResult.add(target);
73+
} else {
74+
LISResult.set(insertionPosition, target);
75+
}
76+
}
77+
78+
return LISResult;
79+
}
80+
81+
}
82+
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
public class Geegong {
2+
3+
/**
4+
* leftIdx, rightIdx 를 둬서 왼족 인덱스를 기준으로 오른쪽 인덱스를 움직여가며 palindromic string 을 찾아간다
5+
* time complexity : O(N^2)
6+
* space complexity : O(1)
7+
* @param s
8+
* @return
9+
*/
10+
public int countSubstrings(String s) {
11+
int count = 0;
12+
char[] sArray = s.toCharArray();
13+
14+
15+
for (int leftIdx = 0; leftIdx < sArray.length; leftIdx++) {
16+
int rightIdx = leftIdx + 1;
17+
18+
// 한글자씩 따졌을 때 palindrome
19+
count++;
20+
while(leftIdx <= rightIdx && rightIdx < sArray.length) {
21+
int offset = rightIdx - leftIdx;
22+
boolean isEqual = sArray[leftIdx] == sArray[rightIdx];
23+
24+
if (!isEqual) {
25+
rightIdx++;
26+
continue;
27+
}
28+
29+
if (offset == 1 && isEqual) {
30+
count++;
31+
rightIdx++;
32+
33+
} else { // isEqual 이고 offset > 1인 케이스
34+
// 서로 조여가면서 palindrome 인지 체크
35+
count += isPalindromic(sArray, leftIdx + 1, rightIdx - 1);
36+
rightIdx++;
37+
}
38+
}
39+
}
40+
41+
return count;
42+
43+
}
44+
45+
public int isPalindromic(char[] origin, int leftIdx, int rightIdx) {
46+
// 서로 조여가면서 palindrome 인지 체크
47+
while (leftIdx < rightIdx) {
48+
if (origin[leftIdx] == origin[rightIdx]) {
49+
leftIdx++;
50+
rightIdx--;
51+
continue;
52+
}
53+
54+
return 0;
55+
}
56+
57+
return 1;
58+
}
59+
60+
}
61+
62+

reverse-bits/Geegong.java

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
public class Geegong {
2+
3+
/**
4+
* time complexity : O(1)
5+
* space complexity : O(1)
6+
* @param n
7+
* @return
8+
*/
9+
public int reverseBits(int n) {
10+
11+
// 32bit 만큼 움직인다.
12+
// for (int index=32; index > 0; index--) {
13+
// // 맨 오른쪽 1bit만 꺼낸다
14+
// int lastOneBit = n & 1;
15+
// // 그런데!! 시프트연산이 하위 5비트까지 밖에 안되서ㅠㅠ << 32 가 아니가 << 0 으로 되어버림
16+
// int temp = lastOneBit << index;
17+
// result = result | temp;
18+
// n = n >>> 1;
19+
// }
20+
21+
int result = 0;
22+
// 시프트 연산을 1비트씩 움직이는걸로 변경해야 한다
23+
for (int index=1; index <= 32; index++) {
24+
// 마지막 1비트를 추출하고 그걸 result 에서 왼쪽으로 1비트 시프트한걸 합쳐야 한다.
25+
// 0001 -> 0010 -> 0100 -> .... 요렇게
26+
result = (n & 1) | (result << 1);
27+
n = n >>> 1;
28+
}
29+
30+
return result;
31+
}
32+
33+
}
34+
35+
36+

0 commit comments

Comments
 (0)