๐ ๋ชฉ์ฐจ
๐ค ๋ฌธ์ : Longest Palindromic Substring | LeetCode 802
์ ๋ ฌ๋ ๋ฐฐ์ด์์ ํ๊ฒ์ด๊ฐ์ด ๋์ค๋ ๊ตฌ๊ฐ์ ์ฐพ๋ ๋ฌธ์ ์ ๋๋ค.
time complexity ๋ฅผ O(logN)์ผ๋ก ํ๋ผ๋ ๋จ์๊ฐ ์์ต๋๋ค.
๐ก ํ์ด
1. Binary Search
์์์ , ๋์ ์ ์ฐพ๋ binary search๋ฅผ ๋๋ฒ ์ํํ๋ ๋ฐฉ์์ผ๋ก ์ฝ๋๋ฅผ ์์ฑํ์ต๋๋ค.
class Solution:
def searchRange(self, nums: List[int], target: int) -> List[int]:
last_idx = len(nums)-1
if not nums: return [-1, -1]
# binary search
def bs(stIdx, edIdx, searchStart = True):
if stIdx > edIdx: return -1
md = int((stIdx+edIdx)/2)
if nums[md] < target: return bs(md+1, edIdx, searchStart)
if nums[md] > target: return bs(stIdx, md-1, searchStart)
if nums[md] is target: [1]
if searchStart: [2]
if md == 0 or nums[md-1] < target: return md
else: return bs(stIdx, md-1, searchStart)
else: [3]
if md == last_idx or nums[md+1] > target: return md
else: return bs(md+1, edIdx, searchStart)
return [bs(0, last_idx), bs(0, last_idx, False)]
[1] ๋ฆฌ์คํธ์ ์ค๊ฐ ๊ฐ์ด target๊ฐ๊ณผ ์ผ์นํ ๋ ์์์ ์ ์ฐพ๋ ์ผ์ด์ค์ ๋์ ์ ์ฐพ๋ ์ผ์ด์ค๋ฅผ ๋ถ๊ธฐํฉ๋๋ค.
[2] ์์์ ์ ์ฐพ์ ๋๋, ๋ฐ๋ก ์ ๊ฐ์ด ํ๊ฒ๊ฐ๋ณด๋ค ์์์ง ํ์ธํฉ๋๋ค.
์์ง ์๋ค๋ฉด, ์ง๊ธ๋ณด๋ค ์ผ์ชฝ ๋ฒ์์์ ๋ค์ ์์์ ์ ์ฐพ์ต๋๋ค.
[3] ์์์ ์ ์ฐพ์ ๋๋, ๋ฐ๋ก ๋ค์ ๊ฐ์ด ํ๊ฒ๊ฐ๋ณด๋ค ํฐ์ง ํ์ธํฉ๋๋ค.
ํฌ์ง ์๋ค๋ฉด, ์ง๊ธ๋ณด๋ค ์ค๋ฅธ์ชฝ ๋ฒ์์์ ๋ค์ ์์์ ์ ์ฐพ์ต๋๋ค.
Time Complexity
O(2*logN)
ํต์ํธ๋ฅผ ๋๋ฒ ํ๋ ๋ฐฉ์์ ๋๋ค.
2. Binary Search + loop
Binary Search๋ก ํ๊ฒ ๊ฐ์ ์ฐพ๊ณ , ์ผ์ชฝ ์ค๋ฅธ์ชฝ์ ์ญ ํ์ธํ๋ฉฐ ๊ฐ์ ๊ฐ์ด ๋์ค๋ ์ธ๋ฑ์ค๊น์ง๋ฅผ ๋ฐํํ๋ ๋ฐฉ์์ ๋๋ค.
[5,5,5,5, ... 5], target : 5
์์ ๊ฐ์ด ์ ์ฒด ๋ฐฐ์ด์ด ๋ค ๊ฐ์ ๊ฐ์ธ ์ผ์ด์ค์ ๋ํด์๋, ์ฌ์ค์ ์ ์ฒด ๋ฐฐ์ด์ ํ์ธํ๊ฒ ๋๋ฏ๋ก Time complexity๋ O(N)์ด ๋ฉ๋๋ค.
๋ฌธ์ ์ ์กฐ๊ฑด์ ๋ง์กฑํ๋ ํ์ด๋ ์๋๊ฒ ์ฃ .
ํ์ง๋ง ์ฐ์ฐ ์์ฒด๊ฐ ๊ฐ๋จํ์ฌ, ์ํ์๊ฐ์ ํจ์ ๋น ๋ฅด๊ฒ ๋์ค๋ค์.
class Solution:
def searchRange(self, nums: List[int], target: int) -> List[int]:
last_idx = len(nums)-1
if not nums: return [-1, -1]
# binary search
def bsRange(stIdx, edIdx):
if stIdx > edIdx: return [-1, -1]
md = int((stIdx+edIdx)/2)
if nums[md] < target: return bsRange(md+1, edIdx)
if nums[md] > target: return bsRange(stIdx, md-1)
if nums[md] is target:
st = md
while 1:
if st is -1 or nums[st] != target: break
st -= 1
ed = md
while 1:
if ed == last_idx+1 or nums[ed] != target: break
ed += 1
return [st+1, ed-1]
return bsRange(0, last_idx)
Time Complexity
O(N)
์ต์ ์ ๊ฒฝ์ฐ ์ ์ฒด ๋ฐฐ์ด ์ํ
3. Python cheat - bisect
ํ์ด์ฌ์์ ๊ธฐ๋ณธ์ผ๋ก ์ ๊ณตํ๋ binary search๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ํ์ฉํ ํ์ด์ ๋๋ค.
- bisect.bisect_left : ์ ๋ ฌ๋ ์์๋ฅผ ์ ์งํ๋๋ก a์ x๋ฅผ ์ฝ์ ํ ์์น๋ฅผ ์ฐพ์ต๋๋ค. x๊ฐ a์ ์ด๋ฏธ ์์ผ๋ฉด, ์ฝ์ ์์น๋ ๊ธฐ์กด ํญ๋ชฉ ์(์ผ์ชฝ)์ด ๋ฉ๋๋ค.
- bisect.bisect_right : ์ ๋ ฌ๋ ์์๋ฅผ ์ ์งํ๋๋ก a์ x๋ฅผ ์ฝ์ ํ ์์น๋ฅผ ์ฐพ์ต๋๋ค. x๊ฐ a์ ์ด๋ฏธ ์์ผ๋ฉด, ์ฝ์ ์์น๋ ๊ธฐ์กด ํญ๋ชฉ ๋ค(์ค๋ฅธ์ชฝ)์ด ๋ฉ๋๋ค.
class Solution:
def searchRange(self, nums: List[int], target: int) -> List[int]:
if not nums: return [-1, -1]
left,right = bisect.bisect_left(nums, target), bisect.bisect_right(nums, target)
return [left, right - 1] if left < right else [-1, -1]
์๋ฌ์ผ์ด์ค
binary search๋ฅผ ์ค๋๋ง์ ์ง๋ค๋ณด๋.. ์ธ๋ฑ์ค ์ก๋ ๋ถ๋ถ์ด๋ ์ฃ์ง์ผ์ด์ค๋ฅผ ๊ณ ๋ ค ํ์ง ๋ชปํ ๋ถ๋ถ๋ค์ด ์์์ต๋๋ค.
์๋๋ ์ ๊ฐ ๋์ณค๋ ์๋ฌ์ผ์ด์ค๋ค์ ๋๋ค.
print(Solution().searchRange([2, 2], 3))
print(Solution().searchRange([2, 2], 2))
print(Solution().searchRange([], 0))
is vs ==
is๊ฐ ๊ฐ๋ ์ฑ์ด ์ข์ ๋ฌด์ง์ฑ(?)์ผ๋ก ์ฐ๊ณ ์์๋๋ฐ, ์ด ๋๋ฌธ์ ์ค๋ต์ด ๋๊ธฐ๋ ํ์ต๋๋ค.
- is๋ ๋ณ์๊ฐ ๊ฐ์ Object(๊ฐ์ฒด)๋ฅผ ๊ฐ๋ฆฌํค๋ฉด True
- ==๋ ๋ณ์๊ฐ ๊ฐ์ Value(๊ฐ)์ ๊ฐ์ง๋ฉด True
ํ์ด์ฌ์ -5~256 ๋ฒ์์ ์ซ์๋ฅผ ๋ฏธ๋ฆฌ ํ ๋นํด๋์ต๋๋ค.
๊ทธ๋์ ์ด ๋ฒ์์ ์ซ์๋ฅผ is ์ฐ์ฐ์ผ๋ก ๋น๊ตํ๋ฉด ๊ฐ์ Object๋ฅผ ๊ฐ๋ฆฌํค๋ฏ๋ก true์ด์ง๋ง,
์ด ๋ฒ์๋ฅผ ๋๋ ์ซ์์ ๋ํด์๋ ์ซ์๋ฅผ ์๋กํ ๋นํ์ฌ ์ฃผ์๊ฐ ๋ฌ๋ผ์ง๋ฏ๋ก, ๊ฐ์ ๊ฐ์ด๋ผ๋ is๋น๊ต ์ false๊ฐ ๋ฉ๋๋ค.
์๋๋ ๋ฌธ์ ๊ฐ ๋์๋ ์ฝ๋์ ์๋ฌ์ผ์ด์ค์ ๋๋ค.
class Solution:
def searchRange(self, nums: List[int], target: int) -> List[int]:
last_idx = len(nums)-1
if not nums: return [-1, -1]
# binary search
def bs(stIdx, edIdx, searchStart = True):
if stIdx > edIdx: return -1
md = int((stIdx+edIdx)/2)
if nums[md] < target: return bs(md+1, edIdx, searchStart)
if nums[md] > target: return bs(stIdx, md-1, searchStart)
if nums[md] is target:
if searchStart:
if md is 0 or nums[md-1] < target: return md
else: return bs(stIdx, md-1, searchStart)
else:
if md is last_idx or nums[md+1] > target: return md # [1]
else: return bs(md+1, edIdx, searchStart)
return [bs(0, last_idx), bs(0, last_idx, False)]
# print(Solution().searchRange([5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5], 5))
[1] ๋ฌธ์ ๊ฐ๋ ๋ถ๋ถ์ ๋๋ค. num์ ๊ธธ์ด๊ฐ ๋งค์ฐ ๊ธด ๋ฐฐ์ด์ด ๋ค์ด์ฌ ๊ฒฝ์ฐ md, last_idx ๊ฐ์ด 256 ์ด์์ด ๋ฉ๋๋ค. ์ด๋ฌ๋ฉด, is๋น๊ต์์ ์์์น๋ชปํ๊ฒ false๊ฐ ๋ฉ๋๋ค.
'์๊ณ ๋ฆฌ์ฆ > LEETCODE' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
Coin Change | LeetCode 809 | Python3 ๐ (0) | 2022.03.11 |
---|---|
Merge Intervals | LeetCode 803 | Python3 ๐ (0) | 2022.03.10 |
Sort Colors | LeetCode 798 | Python3 ๐ (0) | 2022.03.06 |
Permutations, Subsets | LeetCode | Python3 ๐ (0) | 2022.03.05 |
Generate Parentheses | LeetCode 780 | Python3 ๐ (0) | 2022.03.02 |