일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
Tags
- data science
- Python Implementation
- 43. Multiply Strings
- 315. Count of Smaller Numbers After Self
- 밴픽
- Generator
- 컴퓨터의 구조
- 시바견
- shiba
- attribute
- kaggle
- concurrency
- Regular Expression
- Substring with Concatenation of All Words
- Python Code
- Python
- 프로그래머스
- Class
- 운영체제
- 715. Range Module
- t1
- Protocol
- 30. Substring with Concatenation of All Words
- iterator
- Decorator
- Convert Sorted List to Binary Search Tree
- LeetCode
- DWG
- 파이썬
- 109. Convert Sorted List to Binary Search Tree
Archives
- Today
- Total
Scribbling
LeetCode: 315. Count of Smaller Numbers After Self 본문
Computer Science/Coding Test
LeetCode: 315. Count of Smaller Numbers After Self
focalpoint 2022. 2. 10. 11:22
Several solutions and short analysis of each one.
1. List + Binary Search
The most straightforward solution, however, time complexity is O(N**2).
class Solution:
def countSmaller(self, nums: List[int]) -> List[int]:
from bisect import insort, bisect_left
arr = []
count = []
for i in range(len(nums) - 1, -1, -1):
num = nums[i]
idx = bisect_left(arr, num)
count.append(idx)
insort(arr, num)
return count[::-1]
2. Merge Sort
Basically, "# of elements on the rightside that are smaller than the current value" equals "# of movements in stable sort". This solution uses the above fact. Time complexity is O(NlogN).
class Solution:
def countSmaller(self, nums: List[int]) -> List[int]:
self.nums = nums
self.count = [0] * len(nums)
tobesorted = [i for i in range(len(nums))]
self.merge_sort(tobesorted, 0, len(nums)-1)
return self.count
def merge_sort(self, arr, left, right):
if left == right:
return [arr[left]]
mid = (left + right) // 2
larr = self.merge_sort(arr, left, mid)
rarr = self.merge_sort(arr, mid+1, right)
pl, pr = 0, 0
for i in range(left, right+1):
if pl == len(larr):
arr[i] = rarr[pr]
pr += 1
elif pr == len(rarr):
arr[i] = larr[pl]
self.count[arr[i]] += pr
pl += 1
elif self.nums[larr[pl]] <= self.nums[rarr[pr]]:
arr[i] = larr[pl]
self.count[arr[i]] += pr
pl += 1
else:
arr[i] = rarr[pr]
pr += 1
return arr[left:right+1]
3. AVL Tree
class TreeNode:
def __init__(self, val, smaller):
self.val = val
self.freq = 1
self.smaller = smaller
self.left = None
self.right = None
self.height = 1
class AVL:
def __init__(self):
self.root = None
def _height(self, node):
if not node:
return 0
return node.height
def _balance(self, node):
if not node:
return 0
return self._height(node.left) - self._height(node.right)
def _find_successor_node(self, node):
while node.left:
node = node.left
return node
def _rotateR(self, node):
y = node.left
node.smaller = node.smaller - y.smaller - y.freq
t2 = y.right
y.right = node
node.left = t2
node.height = 1 + max(self._height(node.left), self._height(node.right))
y.height = 1 + max(self._height(y.left), self._height(y.right))
return y
def _rotateL(self, node):
y = node.right
y.smaller = y.smaller + node.smaller + node.freq
t2 = y.left
y.left = node
node.right = t2
node.height = 1 + max(self._height(node.left), self._height(node.right))
y.height = 1 + max(self._height(y.left), self._height(y.right))
return y
def insert(self, val):
self.root, smaller = self._insert(self.root, val, 0)
return smaller
def _insert(self, node, val, smaller):
# Termination: Reaching Leaf
if not node:
return TreeNode(val, 0), smaller
if val == node.val:
node.freq += 1
return node, node.smaller + smaller
if val < node.val:
node.smaller += 1
node.left, smaller = self._insert(node.left, val, smaller)
else:
node.right, smaller = self._insert(node.right, val, smaller+node.smaller+node.freq)
node.height = 1 + max(self._height(node.left), self._height(node.right))
balance = self._balance(node)
# LL Case -> Right Rotation of node
if balance > 1 and val < node.left.val:
return self._rotateR(node), smaller
# RR Case -> Left Rotation of node
if balance < -1 and val > node.right.val:
return self._rotateL(node), smaller
# LR Case -> Left Rotation of node.left -> Right Rotation of node
if balance > 1 and val > node.left.val:
node.left = self._rotateL(node.left)
return self._rotateR(node), smaller
# RL Case -> Right Rotation of node.right -> Left Rotation of node
if balance < -1 and val < node.right.val:
node.right = self._rotateR(node.right)
return self._rotateL(node), smaller
return node, smaller
class Solution:
def countSmaller(self, nums):
tree = AVL()
ret = []
for i in range(len(nums)-1, -1, -1):
num = nums[i]
ret.append(tree.insert(num))
return ret[::-1]
4. Segment Tree
class Solution:
def countSmaller(self, nums: List[int]) -> List[int]:
offset = 10**4
n = 2 * 10**4 + 1
def update(num, idx=1, l=0, r=n-1):
if l == r:
tree[idx] += 1
return
mid = (l + r) // 2
if num <= mid:
update(num, idx*2, l, mid)
else:
update(num, idx*2+1, mid+1, r)
tree[idx] = tree[idx*2] + tree[idx*2+1]
def query(low, high, idx=1, l=0, r=n-1):
if l == low and high == r:
return tree[idx]
mid = (l + r) // 2
if high <= mid:
return query(low, high, idx*2, l, mid)
elif low > mid:
return query(low, high, idx*2+1, mid+1, r)
return query(low, mid, idx*2, l, mid) + query(mid+1, high, idx*2+1, mid+1, r)
tree = [0] * (4 * n)
ret = [0] * len(nums)
for i in range(len(nums)-1, -1, -1):
num = nums[i] + offset
update(num)
ret[i] = query(0, num-1)
return ret
'Computer Science > Coding Test' 카테고리의 다른 글
LeetCode: 465. Optimal Account Balancing (0) | 2022.02.17 |
---|---|
LeetCode: 410. Split Array Largest Sum (0) | 2022.02.17 |
LeetCode: 135. Candy (0) | 2022.02.03 |
LeetCode: 366. Find Leaves of Binary Tree (0) | 2022.02.02 |
LeetCode: 109. Convert Sorted List to Binary Search Tree (0) | 2022.01.26 |