-
Notifications
You must be signed in to change notification settings - Fork 126
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
[정현준] 12주차 #566
[정현준] 12주차 #566
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
package leetcode_study | ||
|
||
import io.kotest.matchers.shouldBe | ||
import org.junit.jupiter.api.Test | ||
import kotlin.math.max | ||
|
||
class `maximum-subarray` { | ||
|
||
fun maxSubArray(nums: IntArray): Int { | ||
return usingDP(nums) | ||
} | ||
|
||
/** | ||
* TC: O(n), SC: O(n) | ||
*/ | ||
private fun usingDP(nums: IntArray): Int { | ||
val dp = IntArray(nums.size).apply { | ||
this[0] = nums[0] | ||
} | ||
|
||
for (index in 1 until nums.size) { | ||
dp[index] = max(nums[index], nums[index] + dp[index - 1]) | ||
} | ||
|
||
return dp.max() | ||
} | ||
|
||
/** | ||
* TC: O(n), SC: O(1) | ||
*/ | ||
private fun usingKadane(nums: IntArray): Int { | ||
var (current, max) = nums[0] to nums[0] | ||
|
||
for (index in 1 until nums.size) { | ||
current = max(nums[index], current + nums[index]) | ||
max = max(max, current) | ||
} | ||
|
||
return max | ||
} | ||
|
||
@Test | ||
fun `정수 배열의 하위 배열 중 가장 큰 합을 반환한다`() { | ||
maxSubArray(intArrayOf(-2,1,-3,4,-1,2,1,-5,4)) shouldBe 6 | ||
maxSubArray(intArrayOf(1)) shouldBe 1 | ||
maxSubArray(intArrayOf(5,4,-1,7,8)) shouldBe 23 | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
import org.assertj.core.api.Assertions; | ||
import org.junit.jupiter.api.DisplayName; | ||
import org.junit.jupiter.api.Test; | ||
|
||
import java.util.HashSet; | ||
import java.util.Set; | ||
|
||
public class CountConnectedComponents { | ||
|
||
public int countComponents(int n, int[][] edges) { | ||
final int[] relation = new int[n]; | ||
for (int i = 0; i < n ; i++) { | ||
relation[i] = i; | ||
} | ||
|
||
int result = n; | ||
for (int[] edge : edges) { | ||
if (union(relation, edge) == 1) { | ||
result--; | ||
} | ||
} | ||
|
||
return result; | ||
} | ||
|
||
private int union(int[] relation, int[] edge) { | ||
int parent1 = find(relation, edge[0]); | ||
int parent2 = find(relation, edge[1]); | ||
|
||
if (parent1 == parent2) { | ||
return 0; | ||
} | ||
|
||
if (parent1 < parent2) { | ||
relation[parent2] = parent1; | ||
} else { | ||
relation[parent1] = parent2; | ||
} | ||
return 1; | ||
} | ||
|
||
private int find(int[] relation, int node) { | ||
int result = node; | ||
while (relation[result] != result) { | ||
relation[result] = relation[relation[result]]; | ||
result = relation[result]; | ||
} | ||
return result; | ||
} | ||
|
||
@Test | ||
@DisplayName("입력받은 노드와 간선을 통해 그래프의 개수를 반환한다") | ||
void graphCount() { | ||
int actual = countComponents(3, new int[][]{ {0,1}, {0,2} }); | ||
Assertions.assertThat(actual).isEqualTo(1); | ||
|
||
int actual1 = countComponents(6, new int[][]{ {0,1}, {1,2}, {2,3}, {4,5} }); | ||
Assertions.assertThat(actual1).isEqualTo(2); | ||
|
||
int actual2 = countComponents(6, new int[][]{ {0,1}, {2,3}, {4,5}, {1,2}, {3,4} }); | ||
Assertions.assertThat(actual2).isEqualTo(1); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
package leetcode_study | ||
|
||
import io.kotest.matchers.shouldBe | ||
import org.junit.jupiter.api.Test | ||
|
||
class `remove-nth-node-from-end-of-list` { | ||
|
||
fun removeNthFromEnd(head: ListNode?, n: Int): ListNode? { | ||
if (head == null || (head.next == null && n == 1)) { | ||
return null | ||
} | ||
return usingTwoPointers(head, n) | ||
} | ||
|
||
/** | ||
* TC: O(n), SC: O(n) | ||
*/ | ||
private fun usingExtraList(head: ListNode, n: Int): ListNode { | ||
|
||
fun toList(node: ListNode): List<ListNode> { | ||
val list = mutableListOf<ListNode>() | ||
var tmp: ListNode? = node | ||
while (tmp != null) { | ||
list.add(tmp) | ||
tmp = tmp.next | ||
} | ||
return list | ||
} | ||
|
||
val list = toList(head) | ||
var root = head | ||
if (list.size == n) { | ||
root = list[1] | ||
} else { | ||
list[list.size - n - 1].next = list[list.size - n].next | ||
} | ||
return root | ||
} | ||
|
||
/** | ||
* fast를 n만큼 먼저 이동 시킨 후 fast.next가 null일 때까지 fast와 slow를 다음 노드로 이동시킨다. | ||
* fast를 n만큼 이동시키면 결국 slow는 n의 이전 노드에 도달하게 되기에 해당 slow 노드의 next를 변경하면 된다. | ||
* TC: O(n), SC: O(1) | ||
*/ | ||
private fun usingTwoPointers(head: ListNode, n: Int): ListNode? { | ||
var fast: ListNode? = head | ||
var slow: ListNode? = head | ||
|
||
repeat(n) { | ||
fast = fast?.next | ||
} | ||
if (fast == null) return head.next | ||
|
||
while (fast?.next != null) { | ||
fast = fast?.next | ||
slow = slow?.next | ||
} | ||
slow?.next = slow?.next?.next | ||
return head | ||
} | ||
|
||
@Test | ||
fun `링크된 목록의 헤드가 주어지면 목록의 끝에서 n번째 노드를 제거하고 그 헤드를 반환합니다`() { | ||
removeNthFromEnd(ListNode.of(1), 1).also { | ||
it shouldBe null | ||
} | ||
|
||
removeNthFromEnd(ListNode.of(1, 2), 2).also { | ||
it shouldBe ListNode(2) | ||
} | ||
|
||
removeNthFromEnd(ListNode.of(1, 2), 1)!!.also { | ||
it shouldBe ListNode(1) | ||
it.next shouldBe null | ||
} | ||
|
||
removeNthFromEnd(ListNode.of(1, 2, 3, 4, 5), 2)!!.also { | ||
it.next!!.next!!.`val` shouldBe 3 | ||
it.next!!.next!!.next!!.`val` shouldBe 5 | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
package leetcode_study | ||
|
||
import io.kotest.matchers.shouldBe | ||
import org.junit.jupiter.api.Test | ||
|
||
class `same-tree` { | ||
|
||
fun isSameTree(p: TreeNode?, q: TreeNode?): Boolean { | ||
return if (p == null && q == null) { | ||
true | ||
} else if (p == null || q == null || p.`val` != q.`val`) { | ||
false | ||
} else { | ||
isSameTree(p.left, q.left) && isSameTree(p.right, q.right) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Kotlin은 Implicit return이 가능하군요 ㅎㅎ There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 코틀린에서는 if문과 try문을 식으로 작성할 수 있더라구요 ㅎㅎ There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 아 return 문이었네요 이거 ㅋㅋㅋ 제가 잘못 봤습니다 |
||
} | ||
} | ||
|
||
@Test | ||
fun `두 개의 트리의 동등성을 반환한다`() { | ||
isSameTree( | ||
TreeNode.of(1,1,2), | ||
TreeNode.of(1,1,2) | ||
) shouldBe true | ||
|
||
isSameTree( | ||
TreeNode.of(1,1,2), | ||
TreeNode.of(1,1,2,3) | ||
) shouldBe false | ||
|
||
isSameTree( | ||
TreeNode.of(1,1,2), | ||
TreeNode.of(1,1,3) | ||
) shouldBe false | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
package leetcode_study | ||
|
||
import io.kotest.matchers.shouldBe | ||
import org.junit.jupiter.api.Test | ||
import java.util.StringJoiner | ||
|
||
/** | ||
* 문제의 핵심은 트리를 탐색하는 순서 기준으로 직렬화된 문자열을 반대로 풀어내는 것 | ||
* 직렬화를 DFS로 해결하면 역직렬화시 선입선출 방식으로 해결하여야 하고, | ||
* 직렬화를 BFS로 해결하면 역직렬화시 힙의 인덱스 규칙을 이용하여 해결할 수 있을 듯 | ||
*/ | ||
class `serialize-and-deserialize-binary-tree` { | ||
|
||
private val empty = "X" | ||
private val delimiter = "|" | ||
|
||
/** | ||
* DFS로 탐색하면서 노드의 값을 누적한다. | ||
* TC: O(n), SC: O(n) | ||
*/ | ||
fun serialize(root: TreeNode?): String { | ||
if (root == null) return "" | ||
|
||
val joiner = StringJoiner("|") | ||
nodeToString(root, joiner) | ||
return joiner.toString() | ||
} | ||
|
||
private fun nodeToString(node: TreeNode?, joiner: StringJoiner) { | ||
if (node == null) { | ||
joiner.add(empty) | ||
} else { | ||
joiner.add(node.`val`.toString()) | ||
nodeToString(node.left, joiner) | ||
nodeToString(node.right, joiner) | ||
} | ||
} | ||
|
||
/** | ||
* 깊이 탐색으로 누적된 문자열을 선입선출로 꺼내어 노드를 생성한다. | ||
* TC: O(n), SC: O(n) | ||
*/ | ||
fun deserialize(data: String): TreeNode? { | ||
if (data.isEmpty()) return null | ||
return stringToNode(ArrayDeque(data.split(delimiter))) | ||
} | ||
|
||
private fun stringToNode(queue: ArrayDeque<String>): TreeNode? { | ||
val value = queue.removeFirst() | ||
return if (value == empty) { | ||
null | ||
} else { | ||
val node = TreeNode(value.toInt()) | ||
node.left = stringToNode(queue) | ||
node.right = stringToNode(queue) | ||
node | ||
} | ||
} | ||
|
||
@Test | ||
fun `트리 노드를 직렬화한다`() { | ||
serialize(TreeNode.of(1,2,3,null,null,4,5)) shouldBe "1|2|X|X|3|4|X|X|5|X|X" | ||
} | ||
|
||
@Test | ||
fun `문자열을 트리 노드로 역직렬화한다`() { | ||
deserialize("1|2|X|X|3|4|X|X|5|X|X") shouldBe TreeNode.of(1,2,3,null,null,4,5) | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
union find 풀이 잘 보았습니다 :)
helper 함수 깔끔하게 잘 나누어져 있어서 보기에도 편했습니다