Skip to content

LeetCode 1438: Longest Continuous Subarray With Absolute Diff Less Than or Equal to Limit

Updated: at ์˜ค์ „ 01:34

Table of contents

Open Table of contents

๋“ค์–ด๊ฐ€๋ฉฐ

๊ฑธ๋ฆฐ ์‹œ๊ฐ„: 50๋ถ„ (์ž๋ ฅ์œผ๋กœ ํ’€์ง€ ๋ชปํ•˜๊ณ , ์†”๋ฃจ์…˜์„ ์ฐพ์•„์„œ ๋ณด๊ณ  ์ฐธ๊ณ ํ•ด์„œ ํ’€์—ˆ์Šต๋‹ˆ๋‹ค.)

์ฒ˜์Œ ๋ฌธ์ œ๋ฅผ ์ฝ๊ณ , subarray๋ฅผ ๋ชจ๋‘ ๊ฒฐ์ •์ง“๋Š” ๊ฒฝ์šฐ์˜ ์ˆ˜๋ฅผ ์ƒ๊ฐํ•ด ๋ดค์Šต๋‹ˆ๋‹ค.
๊ฒฐ์ •์ง“๋Š” ๊ฒฝ์šฐ์˜ ์ˆ˜๋Š” ๊ฐ„๋‹จํ•ฉ๋‹ˆ๋‹ค.
subarray์˜ ์‹œ์ž‘ index s์™€ ๋ index e์˜ ์ˆœ์„œ์Œ (s, e)๋ฅผ ๊ตฌํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.
์ฆ‰ nC2_{n}C_2 ์ž…๋‹ˆ๋‹ค.
์ด ๋ฌธ์ œ์—์„œ๋Š”์š”, ์ฃผ์–ด์ง„ array์˜ ๊ธธ์ด์˜ ์ตœ๋Œ€๊ฐ€ 10510^5 ์ด์–ด์„œ, n=105n=10^5 ์ด๊ฒŒ ๋˜๊ณ , ์‹œ๊ฐ„ ์ดˆ๊ณผ๊ฐ€ ๋‚˜์˜ค๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

์ ‘๊ทผ

๊ทธ๋ž˜์„œ ์ €๋Š” ๋ฌธ์ œ์˜ ๋ชฉํ‘œ๋ฅผ ๋‹ค์‹œ ๋ช…ํ™•ํžˆ ํ•ด๋ดค์Šต๋‹ˆ๋‹ค.

๋ชฉํ‘œ: nums์˜ subarray๋“ค ์ค‘์—์„œ, subarray๋‚ด |์ตœ๋Œ€ ์›์†Œ์˜ ๊ฐ’ - ์ตœ์†Œ ์›์†Œ์˜ ๊ฐ’| <= limit์„ ๋งŒ์กฑํ•˜๋Š” subarray๋ฅผ ๊ตฌํ•œ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๊ทธ subarray๋“ค ์ค‘์—์„œ |subarray| (์ฆ‰, len(subarray))๊ฐ€ ๊ฐ€์žฅ ํฐ ๊ฐ’์„ ๊ตฌํ•˜์—ฌ๋ผ.

O(N2)O(N^2)์„ O(N)O(N)์œผ๋กœ ๊ฐœ์„ ํ•˜๋ฉด ์–ด๋–จ๊นŒ๋ผ๋Š” ์ƒ๊ฐ์ด ๋“ค์—ˆ๊ณ , ์ด ๋ฌธ์ œ์—์„œ๋Š” ํˆฌํฌ์ธํ„ฐ๋ฅผ ์“ฐ๋ฉด ๊ฐœ์„ ์„ ํ•  ์ˆ˜ ์žˆ๊ฒ ๋‹ค๋ผ๋Š” ์ƒ๊ฐ์ด ๋“ค์—ˆ์Šต๋‹ˆ๋‹ค.
๊ทธ๋ž˜์„œ l, r์„ ๋‘๊ณ  ํˆฌํฌ์ธํ„ฐ ํ…Œํฌ๋‹‰์„ ์จ์„œ, l, r์„ ์š”๋ฆฌ์กฐ๋ฆฌ ์˜ฎ๊ฒจ ๋‹ค๋‹ˆ๊ฒŒ ํ–ˆ์Šต๋‹ˆ๋‹ค.
์ฒ˜์Œ ๋‘ ํฌ์ธํ„ฐ์˜ ์ดˆ๊ธฐ๊ฐ’์€ 0์œผ๋กœ ๋‘๊ณ , |max - min|๊ฐ’์ด limit๋ณด๋‹ค ์ž‘์œผ๋ฉด, r += 1์„ ํ•ด์ฃผ๊ณ , |max - min|์ด l += 1์„ ํ•ด์ฃผ์–ด์„œ, ๊ธฐ์กด์˜ O(N^2)์„ O(N)์œผ๋กœ ๊ฐœ์„ ํ•˜๊ฒŒ ํ–ˆ์Šต๋‹ˆ๋‹ค.
๊ทธ๋Ÿฐ๋ฐโ€ฆ

max - min|๊ฐ’์ด limit๋ณด๋‹ค ์ž‘์œผ๋ฉด, r += 1์„ ํ•ด์ฃผ๊ณ , |max - min|์ด l += 1์„ ํ•ด์ฃผ์–ด์„œ

๋ฅผ ํ•  ์ˆ˜ ์žˆ๋Š” ๊ทผ๊ฑฐ๋Š” ๋ญ๋ƒ๋ผ๊ณ  ๋ฌผ์œผ์‹ ๋‹ค๋ฉด์š”โ€ฆ ์„ธ ๊ฐ€์ง€์˜ ๊ฐ•๋ ฅํ•œ ๊ด€์ฐฐ์„ ๋ฐ”ํƒ•์œผ๋กœ ๋„์ถœํ•ด๋ƒˆ์Šต๋‹ˆ๋‹ค.

  1. l์ด ์ฆ๊ฐ€ํ•จ์— ๋”ฐ๋ผ max(subarray) - min(subarray) > limit์ด ๋˜๋Š” ์ตœ์ดˆ์˜ r ์ง€์ ์€ ์ฆ๊ฐ€ํ•œ๋‹ค.
  2. ๊ฐ l์—๋Œ€ํ•ด max(subarray) - min(subarray) > limit์ด ๋˜๋Š” ์ตœ์ดˆ์˜ r ์ง€์ ์„ ์ฐพ์€ ์ดํ›„์—๋Š” ๋”์ด์ƒ nums[r + 1], nums[r + 2]โ€ฆ๋ฅผ ํƒ์ƒ‰ํ•  ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. ์™œ๋ƒ๋ฉด ์ž„์˜์˜ ์•„๋ฌด ์ˆซ์ž๋ฅผ subarray์— ๋ฐ›์•„๋“ค์—ฌ์ค€๋“ค max(subarray) - min(subarray)๋Š” ์ปค์ง€๊ธฐ๋งŒ ํ•ฉ๋‹ˆ๋‹ค.
  3. max(subarray) - min(subarray) <= limit๊ฐ€ ๋˜๋Š” ์ตœ์ดˆ์˜ r ์ง€์ ์„ ํƒ์ƒ‰ํ•ด๋‚ธ ๋‹ค์Œ์—๋Š” r์„ ๊ณ„์† ์ฆ๊ฐ€ํ•ด๋„ ๋ฉ๋‹ˆ๋‹ค. ์™œ๋ƒ๋ฉด 2๋ฒˆ์—์„œ ๋งํ•œ ๋Œ€๋กœ, ์ž„์˜์˜ ์•„๋ฌด ์ˆซ์ž๋ฅผ subarray์— ๋ฐ›์•„๋“ค์—ฌ ์ฃผ๋ฉด max(subarray) - min(subarray)๋Š” ์ปค์ง€๊ธฐ๋งŒ ํ•  ์ˆ˜ ์žˆ์ง€, ์ ˆ๋Œ€ ์ž‘์•„์งˆ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

๊ตฌํ˜„ (TLE ๋ฐ›์Œ)

class Solution:

    def longestSubarray(self, nums: List[int], limit: int) -> int:
        def OOB(cur_l, cur_r):
            if cur_l < 0 or cur_l >= n:
                return True
            if cur_r < 0 or cur_r >= n:
                return True
            return False

        n = len(nums)
        # print(f"n: {n}")
        l = r = 0
        max_num = min_num = nums[0]
        li = [nums[0]]
        ans = 0
        while not OOB(l, r) and l <= r:
            max_abs = max_num - min_num
            # print(f"l: {l}, r: {r}, max_abs: {max_abs}")
            if max_abs <= limit:
                ans = max(ans, r - l + 1)
                r += 1
                # find a new num
                if OOB(l, r):
                    continue
                li.append(nums[r])
                max_num = max(max_num, nums[r])
                min_num = min(min_num, nums[r])

            else:
                l += 1
                del li[0]
                max_num = max(li)
                min_num = min(li)
        return ans

์œ„ ์ฝ”๋“œ๋Š” ์•„์ฃผ ํฐ input์— ๋Œ€ํ•ด TLE๋ฅผ ๋ฐ›์•˜์Šต๋‹ˆ๋‹ค.
์‚ฌ์‹ค ๊ตฌํ˜„ํ•˜๋ฉด์„œ๋„

       else:
                l += 1
                del li[0]
                max_num = max(li)
                min_num = min(li)

์ด ๋ถ€๋ถ„์—์„œ ์‹œ๊ฐ„ ๋ณต์žก๋„ ์ƒ์—์„œ ํฐ ๋ฌธ์ œ๊ฐ€ ์žˆ๊ฒ ๊ตฌ๋‚˜๋ฅผ ์ง๊ฐํ–ˆ์Šต๋‹ˆ๋‹ค. (๊ฒฐ๊ตญ O(N^2)์ด ๋˜๋„ค์š”โ€ฆ)
๊ทธ๋Ÿฌ๋ฉด, ํˆฌ ํฌ์ธํ„ฐ์—์„œ ์™ผ์ชฝ ํฌ์ธํ„ฐ๋ฅผ ์ฆ๊ฐ€ํ•˜๊ณ  ๋‚˜์„œ, O(1)๋งŒ์— ํˆฌ ํฌ์ธํ„ฐ ๊ตฌ๊ฐ„ ๋‚ด์—์„œ max์™€ min์„ ๋ฝ‘๋Š” ๋ฒ•์ด ๋ญ๊ฐ€ ์žˆ์„์ง€ ๊ณ ๋ฏผ์„ ํ–ˆ๊ณ , ๊ฒฐ๊ตญ ์ธํ„ฐ๋„ท์—์„œ approach๋ฅผ ์ฐพ์•„ ๋ดค์Šต๋‹ˆ๋‹ค.

๊ตฌํ˜„ (Monotonic Queue ํ…Œํฌ๋‹‰)

from collections import deque
class Solution:

    def longestSubarray(self, nums: List[int], limit: int) -> int:
        def OOB(cur_l, cur_r):
            if cur_l < 0 or cur_l >= n:
                return True
            if cur_r < 0 or cur_r >= n:
                return True
            return False

        n = len(nums)
        # print(f"n: {n}")
        l = r = 0

        dec_dq = deque()
        inc_dq = deque()

        dec_dq.append(0)
        inc_dq.append(0)
        ans = 0
        while not OOB(l, r) and l <= r:
            max_abs = nums[dec_dq[0]] - nums[inc_dq[0]]
            # print(f"l: {l}, r: {r}, max_abs: {max_abs}")
            if max_abs <= limit:
                ans = max(ans, r - l + 1)
                r += 1
                # find a new num
                if OOB(l, r):
                    continue

                while dec_dq and nums[dec_dq[-1]] < nums[r]:
                    dec_dq.pop()

                while inc_dq and nums[inc_dq[-1]] > nums[r]:
                    inc_dq.pop()

                dec_dq.append(r)
                inc_dq.append(r)

            else:
                l += 1
                if dec_dq[0] < l:
                    dec_dq.popleft()
                if inc_dq[0] < l:
                    inc_dq.popleft()
        return ans

ํŠน์ • ๊ตฌ๊ฐ„์—์„œ ์ƒ์ˆ˜ ์‹œ๊ฐ„๋งŒ์— max์™€ min์„ ๋ฝ‘์•„๋‚ด๋Š” ํ…Œํฌ๋‹‰์œผ๋กœ Monotonic Queue๋ผ๋Š” ํ…Œํฌ๋‹‰์„ ์“ฐ๋ฉด ๋œ๋‹ค๋Š” ๊ฑธ ์•Œ๊ฒŒ ๋์Šต๋‹ˆ๋‹ค.
๊ฐ„๋‹จํžˆ ์„ค๋ช…ํ•˜์ž๋ฉด ๋‹จ์กฐ๊ฐ์†Œ ํ์™€ ๋‹จ์กฐ์ฆ๊ฐ€ ํ๋ฅผ ๋‘ก๋‹ˆ๋‹ค.

  1. ๋‹จ์กฐ๊ฐ์†Œํ๋Š” ๋‹จ์กฐ๊ฐ์†Œ๊ฐ€ ํ•ญ์ƒ ์ด๋ค„์ง€๊ฒŒ ํ์— ์›์†Œ๋ฅผ ๋„ฃ์œผ๋ฉด ๋ฉ๋‹ˆ๋‹ค. ๋งŒ์•ฝ ๋‹จ์กฐ๊ฐ์†Œ๊ฐ€ ๊นจ์งˆ ๊ฑฐ ๊ฐ™๋‹ค? ๊ทธ๋Ÿฌ๋ฉด ์ด๋ฏธ ๋“ค์–ด๊ฐ„ ์›์†Œ๋“ค์„ ๋ชจ์กฐ๋ฆฌ popleftํ•ด์ค๋‹ˆ๋‹ค.
  2. ๋‹จ์กฐ์ฆ๊ฐ€ํ๋Š” ๋‹จ์กฐ์ฆ๊ฐ€๊ฐ€ ํ•ญ์ƒ ์ด๋ค„์ง€๊ฒŒ ํ์— ์›์†Œ๋ฅผ ๋„ฃ์œผ๋ฉด ๋ฉ๋‹ˆ๋‹ค. ๋งŒ์•ฝ ๋‹จ์กฐ์ฆ๊ฐ€๊ฐ€ ๊นจ์งˆ ๊ฑฐ ๊ฐ™๋‹ค? ๊ทธ๋Ÿฌ๋ฉด ์ด๋ฏธ ๋“ค์–ด๊ฐ„ ์›์†Œ๋“ค์„ ๋ชจ์กฐ๋ฆฌ popleftํ•ด์ค๋‹ˆ๋‹ค.

Monotonic Queue๋Š” Queue์˜ Top์„ peekํ•ด์„œ ๋‹จ์กฐ์ฆ๊ฐ์ด ๊นจ์งˆ ๊ฑฐ ๊ฐ™์€์ง€๋ฅผ ํŒŒ์•…ํ•ด์•ผ ๋˜๊ธฐ ๋•Œ๋ฌธ์—, Deque ์ž๋ฃŒ๊ตฌ์กฐ๋ฅผ ์ด์šฉํ•ด์„œ ๊ตฌํ˜„ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
๊ทธ๋ฆฌ๊ณ  ์ค‘์š”ํ•œ ์ !! Queue์—๋Š” Index๋ฅผ ๋„ฃ์–ด์•ผ ๋ฉ๋‹ˆ๋‹ค.

๋‹จ์กฐ๊ฐ์†Œํ์˜ ๊ฐ€์žฅ ์•ž์„ ๋ณด๋ฉด ์ตœ๋Œ€๊ฐ’์ด ๋‚˜์˜ค๊ณ , ๋‹จ์กฐ์ฆ๊ฐ€ํ์˜ ๊ฐ€์žฅ ์•ž์„ ๋ณด๋ฉด ์ตœ์†Œ๊ฐ’์ด ๋‚˜์˜ต๋‹ˆ๋‹ค!