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
84 changes: 84 additions & 0 deletions clone-graph/Geegong.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import java.util.*;

/*
// Definition for a Node.
class Node {
public int val;
public List<Node> neighbors;
public Node() {
val = 0;
neighbors = new ArrayList<Node>();
}
public Node(int _val) {
val = _val;
neighbors = new ArrayList<Node>();
}
public Node(int _val, ArrayList<Node> _neighbors) {
val = _val;
neighbors = _neighbors;
}
}
*/
public class Geegong {

/**
* dfs 방식으로 풀이
* visited 로 memoization 하여 방문해서 복사가 된 노드들을 저장
* 한번 방문했던 노드를 neighbors 탐색을 통해 또 방문하게 되면 visited 에서 꺼내서 return 하도록 한다.
*
* time complexity : O(2N) -> O(N)
* space complexity : O(N)
* @param node
* @return
*/
public Node cloneGraph(Node node) {
// node에 진입한 순간에 바로 visited 에 넣어서 cloned 된 node 들을 집어넣도록 관리
Map<Integer, Node> visited = new HashMap<>();

if (node == null) {
return null;
}

Node result = cloneDeeply(node, visited);
return result;
}

public Node cloneDeeply(Node origin, Map<Integer, Node> visited) {

// visited 에는 cloned 된 node 들을 저장하고 있어 한번 방문했던 노드라면 복사한 노드를 리턴한다.
if (visited.containsKey(origin.val)) {
return visited.get(origin.val);
}

Node clonedTarget = new Node(origin.val);
visited.put(origin.val, clonedTarget);

for (Node neighbor : origin.neighbors) {
Node clonedNeighbor = cloneDeeply(neighbor, visited);
clonedTarget.neighbors.add(clonedNeighbor);
}

return clonedTarget;
}


// 이미 다른 분들이 Node 클래스를 많이 만들어놓으셔서.. 개인 클래스 안에 이너 클래스로 Node 만듬
public static class Node {
public int val;
public List<Node> neighbors;
public Node() {
val = 0;
neighbors = new ArrayList<Node>();
}
public Node(int _val) {
val = _val;
neighbors = new ArrayList<Node>();
}
public Node(int _val, ArrayList<Node> _neighbors) {
val = _val;
neighbors = _neighbors;
}
}
}


82 changes: 82 additions & 0 deletions longest-common-subsequence/Geegong.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

public class Geegong {

/**
* LIS, LCS 와 연관지어서 풀이
* 1. 먼저 text1을 훑어보는데 text1에 중복되는 알파벳이 있을 수 있기에 각 캐릭터별로 인덱스들을 저장 (각 원소가 arrayList가 있는 배열)
* 2. text2 를 훑으면서 매칭되는 캐릭터들에 대해서만 1에서 저장된 인덱스들을 한 배열안에 나열
* -> 이떄 나열해서 넣을때마다 역순으로 집어넣는게 중요! (왜냐면 이 나열된 인덱스들을 가지고 LIS를 구할거라서)
* 3. 나열된 인덱스들의 값들을 가지고 LIS 를 구한다, 즉 이 LIS의 길이가 LCS 의 길이가 된다..!! (와우 신기)
* 그러나 leet code 에 돌렸을 때 runtime 이 영 좋지는 않음
*
* time complexity : O(M + N logN) => text2에 대해서 문자마다 바이너리서치가 수행됨
* space complexity : O(M+N)
* @param text1
* @param text2
* @return
*/
public int longestCommonSubsequence(String text1, String text2) {
char[] chText1 = text1.toCharArray();
char[] chText2 = text2.toCharArray();

// text1만 각 원소 별로 char가 가지는 index를 array 로 갖는 배열을 생성
List<Integer>[] positionIndices = new List[26];
for (int index = 0; index<chText1.length; index++) {
if (positionIndices[chText1[index] - 'a'] == null) {
positionIndices[chText1[index] - 'a'] = new ArrayList();
positionIndices[chText1[index] - 'a'].add(index);
} else {
positionIndices[chText1[index] - 'a'].add(index);
}
}


// 여기서부터 LIS 를 구할것임
List<Integer> indices = new ArrayList<>();
for (int index=0; index<chText2.length; index++) {

char find = chText2[index];
if (positionIndices[find-'a'] != null && positionIndices[find-'a'].size() > 0) {
// 역순 (LIS 를 구하기 위해서 일부러 뒤집어 높음, 즉 각 char 별 LIS 를 구할것이기 때문에..)
// positionIndices 에서 구했던 값들을 그대로 addAll 한다면 오름차순이 되기때문에 정확한 LIS 를 구할 수 없다

indices.addAll(positionIndices[find-'a'].stream().sorted(Comparator.reverseOrder()).toList());
}
}

// find LIS
return findLIS(indices).size();
}

public List<Integer> findLIS(List<Integer> source) {
if (source.size() == 0) {
return source;
}

List<Integer> LISResult = new ArrayList<>();
for (int index=0; index<source.size(); index++) {
int target = source.get(index);
int insertionPosition = Collections.binarySearch(LISResult, target);
//Returns:
//the index of the search key, if it is contained in the list;
// otherwise, (-(insertion point) - 1). The insertion point is defined as the point at which the key would be inserted into the list:
if (insertionPosition < 0) {
insertionPosition = -insertionPosition - 1;
}

if (LISResult.size() == insertionPosition) {
LISResult.add(target);
} else {
LISResult.set(insertionPosition, target);
}
}

return LISResult;
}

}

62 changes: 62 additions & 0 deletions palindromic-substrings/Geegong.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
public class Geegong {

/**
* leftIdx, rightIdx 를 둬서 왼족 인덱스를 기준으로 오른쪽 인덱스를 움직여가며 palindromic string 을 찾아간다
* time complexity : O(N^2)
* space complexity : O(1)
* @param s
* @return
*/
public int countSubstrings(String s) {
int count = 0;
char[] sArray = s.toCharArray();


for (int leftIdx = 0; leftIdx < sArray.length; leftIdx++) {
int rightIdx = leftIdx + 1;

// 한글자씩 따졌을 때 palindrome
count++;
while(leftIdx <= rightIdx && rightIdx < sArray.length) {
int offset = rightIdx - leftIdx;
boolean isEqual = sArray[leftIdx] == sArray[rightIdx];

if (!isEqual) {
rightIdx++;
continue;
}

if (offset == 1 && isEqual) {
count++;
rightIdx++;

} else { // isEqual 이고 offset > 1인 케이스
// 서로 조여가면서 palindrome 인지 체크
count += isPalindromic(sArray, leftIdx + 1, rightIdx - 1);
rightIdx++;
}
}
}

return count;

}

public int isPalindromic(char[] origin, int leftIdx, int rightIdx) {
// 서로 조여가면서 palindrome 인지 체크
while (leftIdx < rightIdx) {
if (origin[leftIdx] == origin[rightIdx]) {
leftIdx++;
rightIdx--;
continue;
}

return 0;
}

return 1;
}

}


36 changes: 36 additions & 0 deletions reverse-bits/Geegong.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
public class Geegong {

/**
* time complexity : O(1)
* space complexity : O(1)
* @param n
* @return
*/
public int reverseBits(int n) {

// 32bit 만큼 움직인다.
// for (int index=32; index > 0; index--) {
// // 맨 오른쪽 1bit만 꺼낸다
// int lastOneBit = n & 1;
// // 그런데!! 시프트연산이 하위 5비트까지 밖에 안되서ㅠㅠ << 32 가 아니가 << 0 으로 되어버림
// int temp = lastOneBit << index;
// result = result | temp;
// n = n >>> 1;
// }

int result = 0;
// 시프트 연산을 1비트씩 움직이는걸로 변경해야 한다
for (int index=1; index <= 32; index++) {
// 마지막 1비트를 추출하고 그걸 result 에서 왼쪽으로 1비트 시프트한걸 합쳐야 한다.
// 0001 -> 0010 -> 0100 -> .... 요렇게
result = (n & 1) | (result << 1);
n = n >>> 1;
}

return result;
}

}