-
Notifications
You must be signed in to change notification settings - Fork 126
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
8 changed files
with
572 additions
and
0 deletions.
There are no files selected for viewing
84 changes: 84 additions & 0 deletions
84
construct-binary-tree-from-preorder-and-inorder-traversal/EGON.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
from typing import List, Optional | ||
from unittest import TestCase, main | ||
|
||
|
||
# Definition for a binary tree node. | ||
class TreeNode: | ||
def __init__(self, val=0, left=None, right=None): | ||
self.val = val | ||
self.left = left | ||
self.right = right | ||
|
||
|
||
class Solution: | ||
def buildTree(self, preorder: List[int], inorder: List[int]) -> Optional[TreeNode]: | ||
return self.solve_1(preorder, inorder) | ||
|
||
""" | ||
Runtime: 112 ms (Beats 66.16%) | ||
Time Complexity: O(n ** 2) | ||
Space Complexity: O(n) | ||
Memory: 52.83 MB (Beats 63.14%) | ||
""" | ||
def solve_1(self, preorder: List[int], inorder: List[int]) -> Optional[TreeNode]: | ||
index = 0 | ||
|
||
def build_tree(preorder: List[int], inorder: List[int]) -> Optional[TreeNode]: | ||
nonlocal index | ||
|
||
if not inorder: | ||
return None | ||
|
||
if not 0 <= index < len(preorder): | ||
return None | ||
|
||
root = TreeNode(preorder[index]) | ||
index += 1 | ||
split_index = inorder.index(root.val) | ||
root.left = build_tree(preorder, inorder[:split_index]) | ||
root.right = build_tree(preorder, inorder[split_index + 1:]) | ||
|
||
return root | ||
|
||
return build_tree(preorder, inorder) | ||
|
||
|
||
class _LeetCodeTestCases(TestCase): | ||
def test_1(self): | ||
preorder = [3, 9, 20, 15, 7] | ||
inorder = [9, 3, 15, 20, 7] | ||
output = TreeNode( | ||
val=3, | ||
left=TreeNode( | ||
val=9 | ||
), | ||
right=TreeNode( | ||
val=20, | ||
left=TreeNode(val=15), | ||
right=TreeNode(val=7) | ||
) | ||
) | ||
self.assertEqual(Solution.buildTree(Solution(), preorder, inorder), output) | ||
|
||
def test_2(self): | ||
preorder = [-1] | ||
inorder = [-1] | ||
output = TreeNode( | ||
val=-1 | ||
) | ||
self.assertEqual(Solution.buildTree(Solution(), preorder, inorder), output) | ||
|
||
def test_3(self): | ||
preorder = [1, 2] | ||
inorder = [1, 2] | ||
output = TreeNode( | ||
val=1, | ||
right=TreeNode( | ||
val=2 | ||
) | ||
) | ||
self.assertEqual(Solution.buildTree(Solution(), preorder, inorder), output) | ||
|
||
|
||
if __name__ == '__main__': | ||
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
from typing import List | ||
from unittest import TestCase, main | ||
|
||
|
||
class Solution: | ||
def countBits(self, n: int) -> List[int]: | ||
return self.solve_1(n) | ||
|
||
""" | ||
Runtime: 78 ms (Beats 31.22%) | ||
Time Complexity: O(n * log n), 크기가 n인 배열의 원소들에 대해 시행마다 크기가 2로 나누어지는 비트연산을 수행하므로 | ||
Space Complexity: O(1), 변수 저장 없이 바로 결과 반환 | ||
Memory: 23.26 MB (Beats 39.52%) | ||
""" | ||
def solve_1(self, n: int) -> List[int]: | ||
def count_number_of_1(n: int): | ||
count = 0 | ||
while n: | ||
n &= (n - 1) | ||
count += 1 | ||
return count | ||
|
||
return [count_number_of_1(num) for num in range(n + 1)] | ||
|
||
|
||
class _LeetCodeTestCases(TestCase): | ||
def test_1(self): | ||
n = 2 | ||
output = [0, 1, 1] | ||
self.assertEqual(Solution.countBits(Solution(), n), output) | ||
|
||
def test_2(self): | ||
n = 5 | ||
output = [0, 1, 1, 2, 1, 2] | ||
self.assertEqual(Solution.countBits(Solution(), n), output) | ||
|
||
|
||
if __name__ == '__main__': | ||
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
import Foundation | ||
|
||
class Solution { | ||
func countBits(_ n: Int) -> [Int] { | ||
return solve_2(n) | ||
} | ||
|
||
/* | ||
**내장함수를 사용한 풀이** | ||
|
||
Runtime: 37 ms (Beats 49.12%) | ||
Time Complexity: O(n * log n) | ||
- 길이가 n인 range를 순회하므로 O(n) | ||
- 정수에 대해 non zero bit를 세는데 O(log n) | ||
> O(n * log n) | ||
Space Complexity: O(n) | ||
- 배열에 값을 저장하며 크기가 n이 되므로 O(n) | ||
Memory: 20.86 MB (Beats 90.106%) | ||
*/ | ||
func solve_1(_ n: Int) -> [Int] { | ||
var result: [Int] = [] | ||
for num in 0...n { | ||
result.append(num.nonzeroBitCount) | ||
} | ||
return result | ||
} | ||
|
||
/* | ||
** Brian Kernighan's Algorithm을 사용한 풀이 ** | ||
|
||
Runtime: 39 ms (Beats 42.11%) | ||
Time Complexity: O(n * log n) | ||
- 길이가 n인 range를 순회하므로 O(n) | ||
- bitCountWithBrianKernighan 에서 내부 while문 실행마다 num이 절반으로 줄어드므로, 실행횟수는 O(log n) | ||
> O(n * log n) | ||
Space Complexity: O(n) | ||
- 배열에 값을 저장하며 크기가 n이 되므로 O(n) | ||
Memory: 16.01 MB (Beats 67.84%) | ||
*/ | ||
func solve_2(_ n: Int) -> [Int] { | ||
|
||
func bitCountWithBrianKernighan(_ num: Int) -> Int { | ||
var num = num | ||
var bitCount = 0 | ||
while 0 < num { | ||
num &= (num - 1) | ||
bitCount += 1 | ||
} | ||
|
||
return bitCount | ||
} | ||
|
||
var result: [Int] = [] | ||
for num in 0...n { | ||
result.append(bitCountWithBrianKernighan(num)) | ||
} | ||
return result | ||
} | ||
|
||
/* | ||
** MSB에 대해 DP를 사용한 풀이 ** | ||
> num의 비트 카운트 = MSB의 비트 카운트(1 고정) + (num - msb)의 비트 카운트 | ||
|
||
Runtime: 36 ms (Beats 58.48%) | ||
Time Complexity: O(n) | ||
- 0부터 n까지 range를 순회하므로 O(n) | ||
> O(n) | ||
Space Complexity: O(n) | ||
- 길이가 n인 dp 배열을 저장하므로 O(n) | ||
Memory: 21.15 MB (Beats 67.84%) | ||
*/ | ||
func solve_3(_ n: Int) -> [Int] { | ||
guard 1 <= n else { return [0] } | ||
|
||
var dp = [Int](repeating: 0, count: n + 1) | ||
var msb = 1 | ||
for num in 1...n { | ||
if msb << 1 == num { | ||
msb = num | ||
} | ||
|
||
dp[num] = 1 + dp[num - msb] | ||
} | ||
|
||
return dp | ||
} | ||
|
||
/* | ||
** LSB에 대해 DP를 사용한 풀이 ** | ||
> num의 비트 카운트 = num을 right shift한 숫자의 비트 카운트 + LSB의 비트 카운트(1 또는 0) | ||
|
||
Runtime: 28 ms (Beats 97.08%) | ||
Time Complexity: O(n) | ||
- 0부터 n까지 range를 순회하므로 O(n) | ||
> O(n) | ||
Space Complexity: O(n) | ||
- 길이가 n인 dp 배열을 저장하므로 O(n) | ||
Memory: 21.26 MB (Beats 53.80%) | ||
*/ | ||
func solve_4(_ n: Int) -> [Int] { | ||
guard 1 <= n else { return [0] } | ||
|
||
var dp = [Int](repeating: 0, count: n + 1) | ||
for num in 1...n { | ||
dp[num] = dp[num >> 1] + (num & 1) | ||
} | ||
|
||
return dp | ||
} | ||
} | ||
|
||
let solution = Solution() | ||
print(solution.solve_4(0)) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
from typing import List | ||
from unittest import TestCase, main | ||
|
||
|
||
class Solution: | ||
def numDecodings(self, s: str) -> int: | ||
return self.solve_1(s) | ||
|
||
""" | ||
Runtime: 32 ms (Beats 80.36%) | ||
Time Complexity: O(n) | ||
Space Complexity: O(n) | ||
Memory: 16.59 MB (Beats 51.72%) | ||
""" | ||
def solve_1(self, s: str) -> int: | ||
if len(s) == 0: | ||
return 0 | ||
|
||
if len(s) == 1: | ||
return 0 if int(s) == 0 else 1 | ||
|
||
if len(s) == 2: | ||
last_one_digit, last_two_digits = int(s[1]), int(s) | ||
if last_one_digit == 0: | ||
return 1 if 10 <= last_two_digits <= 26 else 0 | ||
else: | ||
if 0 <= last_two_digits < 10: | ||
return 0 | ||
elif 10 <= last_two_digits <= 26: | ||
return 2 | ||
else: | ||
return 1 | ||
|
||
dp = [0] * (len(s) + 1) | ||
dp[0], dp[1], dp[2] = self.solve_1(s[:0]), self.solve_1(s[:1]), self.solve_1(s[:2]) | ||
for i in range(3, len(s) + 1): | ||
last_one_digit, last_two_digits = int(s[i - 1]), int(s[i - 2: i]) | ||
last_two_digits = int(s[i - 2: i]) | ||
if last_one_digit == 0: | ||
dp[i] += dp[i - 2] if 10 <= last_two_digits <= 26 else 0 | ||
else: | ||
dp[i] += dp[i - 1] + (dp[i - 2] if 10 <= last_two_digits <= 26 else 0) | ||
|
||
return dp[-1] | ||
|
||
|
||
class _LeetCodeTestCases(TestCase): | ||
def test_1(self): | ||
s = "226" | ||
output = 3 | ||
self.assertEqual(Solution.numDecodings(Solution(), s), output) | ||
|
||
def test_2(self): | ||
s = "2101" | ||
output = 1 | ||
self.assertEqual(Solution.numDecodings(Solution(), s), output) | ||
|
||
def test_3(self): | ||
s = "06" | ||
output = 0 | ||
self.assertEqual(Solution.numDecodings(Solution(), s), output) | ||
|
||
|
||
if __name__ == '__main__': | ||
main() |
Oops, something went wrong.