Skip to content

[forest000014] Week 15 #1106

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 11 commits into from
Mar 22, 2025
111 changes: 111 additions & 0 deletions alien-dictionary/forest000014.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
/*
# Time Complexity: O(wl)
- w은 words의 길이, l은 words[i]의 길이
- word 하나를 trie에 등록하는 과정 O(l)
- 모든 word를 trie에 등록하는 과정 O(wl)
- graph를 순회하면서 위상정렬하는 과정 O(26^2) = O(1)
# Space Complexity: O(wl)
- trie의 공간복잡도 O(wl)
*/

class Solution {

private class TrieNode {
char ch;
boolean ends;
List<TrieNode> children;

TrieNode(char ch) {
this.ch = ch;
children = new ArrayList<>();
}
}

public String alienOrder(String[] words) {
List<List<Integer>> graph = new ArrayList<>();
for (int i = 0; i < 26; i++) {
graph.add(new ArrayList<>());
}
boolean[] visited = new boolean[26];
int[] inDegree = new int[26];
int[] outDegree = new int[26];
Queue<Character> queue = new LinkedList<>();

TrieNode root = new TrieNode('.');

for (int i = 0; i < words.length; i++) {
TrieNode curr = root;

for (int j = 0; j < words[i].length(); j++) {
// 유효한 순서가 아님이 확실하면, 곧바로 false를 리턴한다.
// 유효한 순서가 아님이 확실하지 않으면, trie에 추가하고, relation을 추가한다.
// 단, words[i]의 마지막 글자라면, trie의 마지막에 ends = true를 세팅한다.

char ch = words[i].charAt(j);
visited[ch - 'a'] = true;

if (curr.children.size() == 0) {
curr.children.add(new TrieNode(ch));
curr = curr.children.get(curr.children.size() - 1);
if (j == words[i].length()) curr.ends = true;
continue;
}

char lastCh = curr.children.get(curr.children.size() - 1).ch;
if (lastCh == ch) {
curr = curr.children.get(curr.children.size() - 1);
if (j == words[i].length() - 1) {
if (!curr.children.isEmpty()) return "";
else curr.ends = true;
}
continue;
}

for (int p = 0; p < curr.children.size() - 1; p++) {
if (curr.children.get(p).ch == ch) return "";
}

addEdge(graph, inDegree, outDegree, lastCh, ch);
curr.children.add(new TrieNode(ch));
curr = curr.children.get(curr.children.size() - 1);
}
}

for (int i = 0; i < 26; i++) {
if (inDegree[i] == 0 && outDegree[i] != 0) queue.offer((char)('a' + i));
}

StringBuilder sb = new StringBuilder();

for (int i = 0; i < 26; i++) {
if (visited[i] && inDegree[i] == 0 && outDegree[i] == 0) sb.append((char)('a' + i));
}

while (!queue.isEmpty()) {
char ch = queue.poll();
sb.append(ch);

for (int next : graph.get(ch - 'a')) {
if (--inDegree[next] == 0) queue.offer((char)('a' + next));
}
}

for (int i = 0; i < 26; i++) {
if (inDegree[i] > 0) return "";
}

return sb.toString();
}

private boolean addEdge(List<List<Integer>> graph, int[] inDegree, int[] outDegree, char from, char to) {
int sz = graph.get(from - 'a').size();
for (int i = 0; i < sz; i++) {
if (graph.get(from - 'a').get(i) == to - 'a') return false;
}

graph.get(from - 'a').add(to - 'a');
outDegree[from - 'a']++;
inDegree[to - 'a']++;
return true;
}
}
39 changes: 39 additions & 0 deletions course-schedule/forest000014.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*
# Time Complexity: O(n)
# Space Complexity: O(n)
위상 정렬을 사용해서 풀었습니다.
*/

class Solution {
public boolean canFinish(int numCourses, int[][] prerequisites) {
int[] inDegree = new int[numCourses];
Queue<Integer> queue = new LinkedList<>();
List<List<Integer>> graph = new ArrayList<>();
for (int i = 0; i < numCourses; i++) {
graph.add(new ArrayList<>());
}

for (int i = 0; i < prerequisites.length; i++) {
graph.get(prerequisites[i][1]).add(prerequisites[i][0]);
inDegree[prerequisites[i][0]]++;
}

for (int i = 0; i < numCourses; i++) {
if (inDegree[i] == 0) queue.offer(i);
}

while (!queue.isEmpty()) {
int curr = queue.poll();

for (int next : graph.get(curr)) {
inDegree[next]--;
if (inDegree[next] == 0) queue.offer(next);
}
}

for (int i = 0; i < numCourses; i++) {
if (inDegree[i] > 0) return false;
}
return true;
}
}
29 changes: 29 additions & 0 deletions longest-palindromic-substring/forest000014.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*
# Time Complexity: O(n^2)
# Spcae Complexity: O(1)
*/
class Solution {
public String longestPalindrome(String s) {
String ans = "";
for (int i = 0; i < s.length(); i++) {
int l = i;
int r = i;

while (l >= 0 && r < s.length() && s.charAt(l) == s.charAt(r)) {
if (r - l + 1 > ans.length()) ans = s.substring(l, r + 1);
l--;
r++;
}

l = i;
r = i + 1;
while (l >= 0 && r < s.length() && s.charAt(l) == s.charAt(r)) {
if (r - l + 1 > ans.length()) ans = s.substring(l, r + 1);
l--;
r++;
}
}

return ans;
}
}
50 changes: 50 additions & 0 deletions merge-k-sorted-lists/forest000014.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
# Time Complexity: O(nlogk)
- n은 lists[i].length의 합
# Space Complexity: O(k)
- pq에는 최대 k개의 원소가 저장됨
*/
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {

public ListNode mergeKLists(ListNode[] lists) {
if (lists.length == 0) return null;

PriorityQueue<ListNode> pq = new PriorityQueue<>(new Comparator<ListNode>() {
@Override
public int compare(ListNode n1, ListNode n2) {
return n1.val - n2.val;
}
});
for (int i = 0; i < lists.length; i++) {
if (lists[i] == null) continue;
pq.offer(lists[i]);
}

ListNode head = next(pq);
ListNode curr = head;

while (!pq.isEmpty()) {
curr.next = next(pq);
curr = curr.next;
}

return head;
}

private ListNode next(PriorityQueue<ListNode> pq) {
ListNode top = pq.poll();
if (top == null) return null;
if (top.next != null) pq.offer(top.next);
return top;
}
}
54 changes: 54 additions & 0 deletions minimum-window-substring/forest000014.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/*
# Time Complexity: O(m * c)
- c는 문자열에 사용된 문자의 가짓수(= 소문자 26 + 대문자 26)
- 슬라이딩 윈도우로 s 전체를 훑는데 O(m)이 필요하고, 각 윈도우마다 t의 전체 문자가 포함되어 있는지 판단하는데 O(c)가 필요함
# Space Complexity: O(c)
- sMap(슬라이딩 윈도우에 포함된 문자 카운트), tMap(문자열 t에 포함된 문자 카운트) 각각 O(c)
*/
class Solution {
public String minWindow(String s, String t) {
Map<Character, Integer> sMap = new HashMap<>();
Map<Character, Integer> tMap = new HashMap<>();
for (int i = 0; i < t.length(); i++) {
tMap.merge(t.charAt(i), 1, Integer::sum);
}

String ans = "";
int ansLen = Integer.MAX_VALUE;
int l = 0;
int r = 0;
sMap.merge(s.charAt(0), 1, Integer::sum);
while (l <= r) {
if (included(sMap, tMap)) {
if (r - l + 1 < ansLen) {
ansLen = r - l + 1;
ans = s.substring(l, r + 1);
}
sMap.merge(s.charAt(l), -1, Integer::sum);
l++;
} else {
r++;
if (r >= s.length()) break;
sMap.merge(s.charAt(r), 1, Integer::sum);
}
}

while (l <= r && included(sMap, tMap)) {
if (r - l + 1 > ansLen) {
ansLen = r - l + 1;
ans = s.substring(l, r + 1);
}
sMap.merge(s.charAt(l), -1, Integer::sum);
l++;
}

return ans;
}

private boolean included(Map<Character, Integer> sMap, Map<Character, Integer> tMap) {
for (Character key : tMap.keySet()) {
if (!sMap.containsKey(key) || sMap.get(key) < tMap.get(key)) return false;
}
return true;
}
}
84 changes: 84 additions & 0 deletions pacific-atlantic-water-flow/forest000014.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
/*
# Time Complexity: O(m * n * log(m * n))
# Space Complexity: O(m * n)
- visited, pq
DFS와 PQ를 조합하여 풀었습니다.
*/
class Solution {
private class Cell {
int r;
int c;
int h;

Cell(int r, int c, int h) {
this.r = r;
this.c = c;
this.h = h;
}
}

public List<List<Integer>> pacificAtlantic(int[][] heights) {
int m = heights.length;
int n = heights[0].length;
PriorityQueue<Cell> pq1 = new PriorityQueue<>(new Comparator<Cell>() {
@Override
public int compare(Cell c1, Cell c2) {
return c1.h - c2.h;
}
});
PriorityQueue<Cell> pq2 = new PriorityQueue<>(new Comparator<Cell>() {
@Override
public int compare(Cell c1, Cell c2) {
return c1.h - c2.h;
}
});
int[][] visited = new int[m][n];

for (int i = 0; i < m; i++) {
pq1.offer(new Cell(i, 0, heights[i][0]));
pq2.offer(new Cell(i, n - 1, heights[i][n - 1]));
visited[i][0] |= 1;
visited[i][n - 1] |= 2;
}
for (int i = 1; i < n; i++) {
pq1.offer(new Cell(0, i, heights[0][i]));
pq2.offer(new Cell(m - 1, i - 1, heights[m - 1][i - 1]));
visited[0][i] |= 1;
visited[m - 1][i - 1] |= 2;
}

int[] dr = {-1, 0, 1, 0};
int[] dc = {0, 1, 0, -1};
while (!pq1.isEmpty()) {
Cell curr = pq1.poll();
for (int i = 0; i < 4; i++) {
int nr = curr.r + dr[i];
int nc = curr.c + dc[i];
if (nr < 0 || nr >= m || nc < 0 || nc >= n || heights[nr][nc] < heights[curr.r][curr.c] || (visited[nr][nc] & 1) == 1) continue;
pq1.offer(new Cell(nr, nc, heights[nr][nc]));
visited[nr][nc] |= 1;
}
}
while (!pq2.isEmpty()) {
Cell curr = pq2.poll();
for (int i = 0; i < 4; i++) {
int nr = curr.r + dr[i];
int nc = curr.c + dc[i];
if (nr < 0 || nr >= m || nc < 0 || nc >= n || heights[nr][nc] < heights[curr.r][curr.c] || (visited[nr][nc] & 2) == 2) continue;
pq2.offer(new Cell(nr, nc, heights[nr][nc]));
visited[nr][nc] |= 2;
}
}

List<List<Integer>> ans = new ArrayList<>();
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (visited[i][j] == 3) {
ans.add(new ArrayList<>(List.of(i, j)));
}
}
}

return ans;
}
}
25 changes: 25 additions & 0 deletions rotate-image/forest000014.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/*
# Time Complexity: O(n^2)
# Space Complexity: O(1)
*/
class Solution {
public void rotate(int[][] matrix) {
int n = matrix.length;

for (int i = 0; i < n / 2; i++) {
for (int j = i; j < n - i - 1; j++) {
// [i][j] -> [j][n - i - 1]
// [j][n - i - 1] -> [n - i - 1][n - j - 1]
// [n - i - 1][n - j - 1] -> [n - j - 1][i]
// [n - j - 1][i] -> [i][j]
// (각 인덱스의 등장 횟수를 체크해서, 각각의 등장횟수가 4번임을 확인하면, 틀린 인덱스가 아님을 quick하게 체크해볼 수는 있음. 이 방법으로 맞다는 보장은 안 됨.)

int tmp = matrix[i][j];
matrix[i][j] = matrix[n - j - 1][i];
matrix[n - j - 1][i] = matrix[n - i - 1][n - j - 1];
matrix[n - i - 1][n - j - 1] = matrix[j][n - i - 1];
matrix[j][n - i - 1] = tmp;
}
}
}
}
Loading