๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ

์•Œ๊ณ ๋ฆฌ์ฆ˜/LEETCODE

Search for a Range | LeetCode 802 | Python3 ๐Ÿ

๋ฐ˜์‘ํ˜•

 

๐Ÿ“„ ๋ชฉ์ฐจ

     

     

    ๐Ÿค” ๋ฌธ์ œ : Longest Palindromic Substring | LeetCode 802

    ๋ฌธ์ œ: https://leetcode.com/explore/interview/card/top-interview-questions-medium/110/sorting-and-searching/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๊ฐ€ ๋ฉ๋‹ˆ๋‹ค. 

    ๋ฐ˜์‘ํ˜•