Coding Interview Prep · บทเรียน

กักเก็บน้ำฝน: สแตกและตัวชี้สองตัว

แก้ปัญหาการกักเก็บน้ำฝนด้วยทั้งวิธีสแตกโมโนโทนิกที่คำนวณเป็นชั้นแนวนอน และวิธีตัวชี้สองตัวที่คำนวณเป็นคอลัมน์แนวตั้ง

บทเรียน 4 จาก 413 ขั้นตอน

กักเก็บน้ำฝน: สแตกและตัวชี้สองตัว เป็นบทเรียน Coding Interview Prep ฟรีบน CoddyKit นี่คือบทเรียนที่ 4 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Coding Interview Prep และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Coding Interview Prep มีบทเรียนทั้งหมด 4 บทเรียน

โจทย์: การกักเก็บน้ำฝน

การกักเก็บน้ำฝน (LeetCode 42) เป็นหนึ่งในโจทย์สัมภาษณ์ที่โด่งดังที่สุด เมื่อกำหนดจำนวนเต็มไม่ติดลบ n ตัวแทนแผนที่ระดับความสูง โดยแต่ละแท่งมีความกว้าง 1 ให้คำนวณว่าหลังฝนตกแล้วสามารถกักเก็บน้ำไว้ระหว่างแท่งได้มากเพียงใด น้ำจะเติมเต็มบริเวณแอ่งระหว่างแท่งที่สูงกว่าทั้งสองด้าน

สำหรับตำแหน่ง i แต่ละตำแหน่ง ระดับน้ำคือ min(max_left[i], max_right[i]) - height[i] หากค่านี้เป็นลบ จะไม่มีน้ำถูกกักเก็บ (แท่งสูงกว่าขอบเขตอย่างน้อยหนึ่งด้าน) มีสามวิธี ได้แก่ อาร์เรย์ที่คำนวณไว้ล่วงหน้า O(n)/O(n) วิธีสองพอยน์เตอร์ O(n)/O(1) และสแตกแบบโมโนโทน O(n)/O(n)

height = [0, 1, 0, 2, 1, 0, 1, 3, 2, 1, 2, 1]
# Water trapped at each position:
# pos 2: min(1,3)-0=1
# pos 4: min(2,3)-1=1
# pos 5: min(2,3)-0=2
# pos 6: min(2,3)-1=1
# pos 9: min(3,2)-1=1
# Total = 6
print('height:', height)
print('Expected trapped water: 6')

# Visualise
max_h = max(height)
for row in range(max_h, 0, -1):
    line = ''
    for h in height:
        line += '#' if h >= row else ' '
    print(line)

วิธีที่ 1: อาร์เรย์ค่าสูงสุดที่คำนวณไว้ล่วงหน้า

วิธีที่ตรงไปตรงมาซึ่งใช้เวลา O(n) และพื้นที่ O(n) จะคำนวณอาร์เรย์สองชุดไว้ล่วงหน้า: max_left[i] = ความสูงสูงสุดตั้งแต่ดัชนี 0 ถึง i และ max_right[i] = ความสูงสูงสุดตั้งแต่ดัชนี i ถึง n-1 ปริมาณน้ำที่ตำแหน่ง i คือ max(0, min(max_left[i], max_right[i]) - height[i])

การสร้าง max_left ต้องไล่ดูข้อมูลจากซ้ายไปขวาหนึ่งรอบ ส่วน max_right ต้องไล่ดูจากขวาไปซ้ายหนึ่งรอบ จากนั้นไล่ดูอีกรอบเพื่อรวมปริมาณน้ำ วิธีนี้สะอาดและอธิบายได้ง่าย แต่ใช้พื้นที่เพิ่มเติม O(n)

def trap_prefix(height):
    n = len(height)
    if n < 3:
        return 0

    max_left = [0] * n
    max_right = [0] * n

    max_left[0] = height[0]
    for i in range(1, n):
        max_left[i] = max(max_left[i-1], height[i])

    max_right[-1] = height[-1]
    for i in range(n-2, -1, -1):
        max_right[i] = max(max_right[i+1], height[i])

    water = 0
    for i in range(n):
        water += max(0, min(max_left[i], max_right[i]) - height[i])
    return water

print(trap_prefix([0,1,0,2,1,0,1,3,2,1,2,1]))  # 6
print(trap_prefix([4,2,0,3,2,5]))                # 9

วิธีที่ 2: สองพอยน์เตอร์ (พื้นที่ O(1))

วิธีสองพอยน์เตอร์ใช้เวลา O(n) และ พื้นที่ O(1) ใช้พอยน์เตอร์ซ้ายและขวาเริ่มต้นจากปลายทั้งสองด้าน รักษา max_left และ max_right ให้เป็นค่าสูงสุดสะสมที่พบจากแต่ละด้านจนถึงขณะนั้น

ในแต่ละขั้น ให้ประมวลผลด้านที่มีค่าสูงสุดสะสมเล็กกว่า เพราะด้านนั้นเป็นปัจจัยจำกัด หาก max_left < max_right ปริมาณน้ำที่พอยน์เตอร์ซ้ายคือ max_left - height[left] (ด้านขวาสูงเพียงพอ) จากนั้นเลื่อนพอยน์เตอร์ซ้ายเข้าด้านใน มิฉะนั้นให้ประมวลผลพอยน์เตอร์ขวาในลักษณะสมมาตร โดยไม่ต้องสร้างอาร์เรย์ไว้ล่วงหน้า

def trap_two_pointer(height):
    left, right = 0, len(height) - 1
    max_left = max_right = 0
    water = 0

    while left < right:
        if height[left] < height[right]:
            if height[left] >= max_left:
                max_left = height[left]    # new max on the left
            else:
                water += max_left - height[left]  # trapped by max_left
            left += 1
        else:
            if height[right] >= max_right:
                max_right = height[right]
            else:
                water += max_right - height[right]
            right -= 1
    return water

print(trap_two_pointer([0,1,0,2,1,0,1,3,2,1,2,1]))  # 6
print(trap_two_pointer([4,2,0,3,2,5]))                # 9
print(trap_two_pointer([3,0,3]))                      # 3

เหตุผลที่วิธีสองพอยน์เตอร์ใช้ได้: เงื่อนไขคงเดิม

ข้อสังเกตสำคัญคือ เมื่อประมวลผลพอยน์เตอร์ซ้ายเพราะ height[left] < height[right] เราทราบว่า max_right >= height[right] > height[left] ดังนั้นขอบเขตน้ำที่มีผลทางด้านขวาจึงมีค่าอย่างน้อย height[right] ซึ่งมากกว่า max_left อยู่แล้ว ดังนั้น min(max_left, effective_max_right) = max_left และสูตรปริมาณน้ำจึงย่อเหลือ max_left - height[left]

เราไม่จำเป็นต้องทราบค่า max_right ที่แน่นอน เพียงทราบว่าค่านั้นอย่างน้อยเท่ากับ height[right] > height[left] ก็เพียงพอที่จะใช้ max_left เป็นระดับน้ำได้ นี่คือเงื่อนไขคงเดมที่สง่างามซึ่งทำให้ใช้พื้นที่ O(1) ได้

# Trace two-pointer on [4, 2, 0, 3, 2, 5]
height = [4, 2, 0, 3, 2, 5]
left, right = 0, len(height) - 1
max_l = max_r = water = 0
print('height:', height)
print(f'{'Step':5} {'L':3} {'R':3} {'maxL':5} {'maxR':5} {'water':6} {'total':6}')
step = 0
while left < right:
    side = 'L' if height[left] < height[right] else 'R'
    if side == 'L':
        if height[left] >= max_l: max_l = height[left]
        else:
            w = max_l - height[left]; water += w
        left += 1
    else:
        if height[right] >= max_r: max_r = height[right]
        else:
            w = max_r - height[right]; water += w
        right -= 1
    step += 1
    print(f'{step:5} {left:3} {right:3} {max_l:5} {max_r:5} {water:6}')
print('Total trapped:', water)

แนวทางที่ 3: สแตกโมโนโทน (ชั้นแนวนอน)

แนวทางการใช้สแตกโมโนโทนคำนวณน้ำใน ชั้นแนวนอน ระหว่างแท่งที่อยู่ติดกัน ให้คงสแตกดัชนีที่เรียงลดลงแบบโมโนโทนไว้ เมื่อแท่ง i สูงกว่ายอดสแตก j จะเกิดแอ่งขึ้น: พื้นแอ่งคือ height[j] ผนังด้านซ้ายคือ height[stack[-1]] หลังนำ j ออก และผนังด้านขวาคือ height[i] น้ำจะเติมแอ่งขึ้นไปถึงระดับ min(left_wall, right_wall) - floor โดยมีความกว้าง i - stack[-1] - 1.

แต่ละ ‘แอ่ง’ จะถูกคำนวณเมื่อพบแท่งที่สูงกว่า วิธีนี้ประมวลผลน้ำเป็นส่วนรูปสี่เหลี่ยมที่มีขอบเขต จึงมีประโยชน์เมื่อจำเป็นต้องติดตามด้วยว่าแท่งใดมีส่วนช่วยสร้างระดับน้ำ

def trap_stack(height):
    stack = []   # monotonic decreasing indices
    water = 0

    for i in range(len(height)):
        while stack and height[stack[-1]] < height[i]:
            bottom_idx = stack.pop()        # the floor of the valley
            if not stack:
                break                       # no left wall, no water
            left_idx = stack[-1]
            floor = height[bottom_idx]
            water_height = min(height[left_idx], height[i]) - floor
            width = i - left_idx - 1
            water += water_height * width
        stack.append(i)
    return water

print(trap_stack([0,1,0,2,1,0,1,3,2,1,2,1]))  # 6
print(trap_stack([4,2,0,3,2,5]))                # 9

การไล่ตามสแตกโมโนโทน

ลองไล่ตาม [0,1,0,2,1,0,1,3,...] ด้วยแนวทางสแตก เมื่อพบแท่งที่ 3 (h=2) ที่ i=3: ยอดสแตกคือ i=2 (h=0) จึงนำออก ผนังด้านซ้ายคือ i=1 (h=1) และผนังด้านขวาคือ h=2 ระดับน้ำ = ค่าต่ำสุด(1,2)-0=1 ความกว้าง=3-1-1=1 พื้นที่=1 ต่อไปยอดสแตก i=1 (h=1) ไม่ได้น้อยกว่า 2 จึงหยุด แล้วใส่ 3 ลงในสแตก

วิธีใช้สแตกมีความซับซ้อนในการนำไปใช้มากกว่าตัวชี้สองตัว แต่แสดงให้เห็นว่าแท่งใดโดยเฉพาะที่ก่อให้เกิดช่องน้ำแต่ละช่อง ความเข้าใจนี้มีประโยชน์สำหรับคำถามต่อยอดเกี่ยวกับการสร้างผังการกักน้ำขึ้นใหม่หรือการนับแอ่งที่แตกต่างกัน

def trap_stack_trace(height):
    stack = []
    water = 0
    for i in range(len(height)):
        print(f'i={i} h={height[i]}: stack={[height[s] for s in stack]}')
        while stack and height[stack[-1]] < height[i]:
            bot = stack.pop()
            if not stack:
                print(f'  Pop {height[bot]}: no left wall, skip')
                break
            left = stack[-1]
            h = min(height[left], height[i]) - height[bot]
            w = i - left - 1
            water += h * w
            print(f'  Pop {height[bot]}: floor={height[bot]}, left_wall={height[left]}, right_wall={height[i]}, h={h}, w={w}, +{h*w}')
        stack.append(i)
    return water

result = trap_stack_trace([0,1,0,2,1,0,1,3,2,1,2,1])
print('Total:', result)

เปรียบเทียบแนวทางทั้งสามแบบ

สรุปแนวทางการกักน้ำฝนทั้งสามแบบ:

  • อาร์เรย์คำนำหน้า: เวลา O(n) พื้นที่หน่วยความจำ O(n) เข้าใจและตรวจสอบได้ง่ายที่สุด เหมาะสำหรับการสัมภาษณ์ที่ให้ความสำคัญกับความชัดเจนมากกว่าประสิทธิภาพด้านพื้นที่
  • ตัวชี้สองตัว: เวลา O(n) พื้นที่หน่วยความจำ O(1) เหมาะสมที่สุดทั้งด้านเวลาและพื้นที่ เหมาะสำหรับคำถามต่อยอดว่า ‘ทำให้ใช้พื้นที่ O(1) ได้หรือไม่’
  • สแตกโมโนโทน: เวลา O(n) พื้นที่หน่วยความจำ O(n) ประมวลผลน้ำเป็นชั้นแนวนอน เหมาะเมื่อจำเป็นต้องทราบว่าแท่งใดมีส่วนช่วยสร้างน้ำ หรือเมื่อปัญหานี้ปรากฏเป็นปัญหาย่อยในอัลกอริทึมขนาดใหญ่ที่ใช้สแตกเป็นพื้นฐาน
height = [0,1,0,2,1,0,1,3,2,1,2,1]

# All three methods — verify they agree
def trap_prefix(h):
    n = len(h)
    ml = [0]*n; mr = [0]*n; ml[0]=h[0]; mr[-1]=h[-1]
    for i in range(1,n): ml[i]=max(ml[i-1],h[i])
    for i in range(n-2,-1,-1): mr[i]=max(mr[i+1],h[i])
    return sum(max(0,min(ml[i],mr[i])-h[i]) for i in range(n))

def trap_two_ptr(h):
    l,r,ml,mr,w = 0,len(h)-1,0,0,0
    while l<r:
        if h[l]<h[r]:
            ml=max(ml,h[l]); w+=ml-h[l]; l+=1
        else:
            mr=max(mr,h[r]); w+=mr-h[r]; r-=1
    return w

def trap_stk(h):
    stk,w = [],[]
    for i in range(len(h)):
        while stk and h[stk[-1]]<h[i]:
            b=stk.pop()
            if not stk: break
            w.append(max(0,min(h[stk[-1]],h[i])-h[b])*(i-stk[-1]-1))
        stk.append(i)
    return sum(w)

for h in [height, [4,2,0,3,2,5], [3,0,3], [1,0,1]]:
    p=trap_prefix(h); t=trap_two_ptr(h); s=trap_stk(h)
    print(f'{h}: prefix={p}, two-ptr={t}, stack={s}, match={p==t==s}')

ภาชนะที่จุน้ำได้มากที่สุด

ภาชนะที่จุน้ำได้มากที่สุด (LeetCode 11) มักสับสนกับการกักน้ำฝน ในกรณีนี้ คุณจะเลือกแท่งสองแท่งพอดี และน้ำจะถูกจำกัดขอบเขตด้วยแท่งสองแท่งนั้นเท่านั้น (แท่งภายในไม่มีผล) จงทำให้พื้นที่ min(height[l], height[r]) × (r - l) มีค่าสูงสุด

ตัวชี้สองตัวแก้ปัญหานี้แบบละโมบ: เริ่มจากปลายทั้งสองด้าน (ความกว้างสูงสุด) แล้วเลื่อนตัวชี้ที่ชี้ไปยังแท่งที่สั้นกว่าเข้าด้านใน — การเลื่อนตัวชี้ที่ชี้ไปยังแท่งสูงกว่าจะทำให้พื้นที่ลดลงได้เท่านั้น วิธีนี้ใช้เวลา O(n) และพื้นที่หน่วยความจำ O(1) ซึ่งง่ายกว่าตัวชี้สองตัวสำหรับการกักน้ำฝน เพราะไม่จำเป็นต้องเก็บค่าสูงสุดสะสม

def max_water_container(height):
    left, right = 0, len(height) - 1
    max_area = 0

    while left < right:
        area = min(height[left], height[right]) * (right - left)
        max_area = max(max_area, area)
        # Move the shorter bar: moving taller bar can only reduce min
        if height[left] < height[right]:
            left += 1
        else:
            right -= 1
    return max_area

print(max_water_container([1,8,6,2,5,4,8,3,7]))  # 49: bars 8 and 7
print(max_water_container([1,1]))                  # 1
print(max_water_container([4,3,2,1,4]))            # 16

# Key difference from trapping rain water:
# Container: choose 2 bars, water fills freely between them (no internal barriers)
# Trapping:  water fills ALL valleys in the full elevation map

ขั้นสูง: การกักน้ำฝน II (สามมิติ)

การกักน้ำฝน II (LeetCode 407) ขยายปัญหาไปสู่เมทริกซ์ความสูงสองมิติ น้ำสามารถไหลได้ทั้งสี่ทิศทางและต้องไหลออกทางขอบ คำตอบใช้ ฮีพค่าต่ำสุด: เริ่มต้นฮีพด้วยเซลล์ทั้งหมดที่อยู่ตามขอบ จากนั้นขยายแบบ BFS ต่อไป ประมวลผลเซลล์ที่มีความสูงน้อยที่สุด — เพื่อนบ้านที่ต่ำกว่าจะต้องกักน้ำไว้สูงอย่างน้อยเท่ากับระดับของเซลล์ปัจจุบัน

นี่เป็นอัลกอริทึมที่แตกต่างจากกรณีหนึ่งมิติอย่างสิ้นเชิง และทดสอบทั้งการดำเนินการกับฮีพและการท่องผ่านแบบ BFS เคล็ดลับตัวชี้สองตัวสำหรับกรณีหนึ่งมิติไม่สามารถขยายใช้กับสองมิติได้ แต่แนวทางฮีพสามารถทำได้

import heapq

def trap_rain_water_2d(heightMap):
    if not heightMap or not heightMap[0]:
        return 0
    m, n = len(heightMap), len(heightMap[0])
    visited = [[False]*n for _ in range(m)]
    heap = []  # (height, row, col)

    # Add all border cells to the heap
    for i in range(m):
        for j in [0, n-1]:
            heapq.heappush(heap, (heightMap[i][j], i, j))
            visited[i][j] = True
    for j in range(n):
        for i in [0, m-1]:
            if not visited[i][j]:
                heapq.heappush(heap, (heightMap[i][j], i, j))
                visited[i][j] = True

    total = 0
    max_h = 0
    while heap:
        h, r, c = heapq.heappop(heap)
        max_h = max(max_h, h)
        for dr, dc in [(-1,0),(1,0),(0,-1),(0,1)]:
            nr, nc = r+dr, c+dc
            if 0<=nr<m and 0<=nc<n and not visited[nr][nc]:
                visited[nr][nc] = True
                total += max(0, max_h - heightMap[nr][nc])
                heapq.heappush(heap, (max(max_h, heightMap[nr][nc]), nr, nc))
    return total

map2d = [[1,4,3,1,3,2],[3,2,1,3,2,4],[2,3,3,2,3,1]]
print(trap_rain_water_2d(map2d))  # 4

เมื่อใดควรใช้แต่ละวิธีในการสัมภาษณ์

คู่มือการตัดสินใจสำหรับการสัมภาษณ์เรื่องการกักน้ำฝน:

  • เริ่มด้วย: อาร์เรย์คำนำหน้า — อธิบายง่าย เห็นภาพได้ชัด และถูกต้องอย่างชัดเจน
  • คำถามต่อยอดว่า ‘ใช้พื้นที่ O(1) ได้หรือไม่’: ตัวชี้สองตัว — อธิบายค่าคงที่ว่า ด้านที่เล็กกว่าคือคอขวด
  • หากผู้สัมภาษณ์ถามว่า ‘มีแนวทางอื่นไหม’: สแตกโมโนโทน — อธิบายการคำนวณน้ำเป็นชั้นแนวนอน

ควรเริ่มด้วยการกำหนดให้ชัดเจนเสมอว่าอะไรเป็นตัวกำหนดระดับน้ำในแต่ละตำแหน่ง (ค่าต่ำสุดของแท่งที่สูงที่สุดในแต่ละด้าน) ก่อนเริ่มเขียนโค้ด วิธีนี้แสดงให้เห็นว่าคุณเข้าใจปัญหา และทำให้อธิบายคำตอบได้ง่ายขึ้น

# Quick summary of all three approaches
approaches = [
    {
        'name': 'Prefix max arrays',
        'time': 'O(n)', 'space': 'O(n)',
        'description': '3 passes: build max_left, max_right, sum water column-by-column',
    },
    {
        'name': 'Two pointers',
        'time': 'O(n)', 'space': 'O(1)',
        'description': 'Process smaller side: its max is the limiting wall, no array needed',
    },
    {
        'name': 'Monotonic stack',
        'time': 'O(n)', 'space': 'O(n)',
        'description': 'Compute water in horizontal layers when a taller bar is encountered',
    },
]
for a in approaches:
    print(f'{a["name"]} [{a["time"]} / {a["space"]}]')
    print(f'  {a["description"]}')
    print()

กรณีขอบและข้อผิดพลาดที่พบบ่อย

ข้อผิดพลาดที่พบบ่อยในการกักน้ำฝน:

  • ลืมใช้ค่าต่ำสุด: ระดับน้ำคือ min(max_left, max_right) ไม่ใช่ค่าของด้านใดด้านหนึ่งเพียงด้านเดียว แท่งหนึ่งแท่งต้องมีผนังสูงทั้งด้านซ้ายและด้านขวา
  • น้ำติดลบ: ใช้ max(0, ...) เพื่อจำกัดค่าติดลบให้เป็น 0 เมื่อความสูงของตำแหน่งหนึ่งมากกว่าระดับน้ำ
  • ตำแหน่งปลายขอบ: แท่งซ้ายสุดและขวาสุดไม่สามารถกักน้ำได้เลย (ไม่มีผนังด้านหนึ่ง) แนวทางอาร์เรย์คำนำหน้าจัดการกรณีนี้ได้โดยธรรมชาติ เพราะ max_left[0] = height[0] ทำให้น้ำที่ดัชนี 0 เป็น 0 เสมอ
  • อาร์เรย์ว่างหรือมีขนาดเล็กมาก: คืนค่า 0 สำหรับอาร์เรย์ที่มีสมาชิกน้อยกว่า 3 ตัว
def trap(height):
    n = len(height)
    if n < 3:
        return 0   # need at least 3 bars to trap anything

    left, right = 0, n - 1
    max_l = max_r = water = 0
    while left < right:
        if height[left] <= height[right]:
            if height[left] >= max_l:
                max_l = height[left]
            else:
                water += max_l - height[left]  # never negative: max_l > height[left]
            left += 1
        else:
            if height[right] >= max_r:
                max_r = height[right]
            else:
                water += max_r - height[right]
            right -= 1
    return water

# Edge cases
print(trap([]))          # 0: empty
print(trap([1]))         # 0: single bar
print(trap([1,2]))       # 0: two bars
print(trap([3,0,3]))     # 3: simple valley
print(trap([3,3,3]))     # 0: flat top, no water

ตรวจสอบความเข้าใจอย่างรวดเร็ว

ทดสอบความเข้าใจแนวคิดโครงสร้างข้อมูล & อัลกอริทึม — การเตรียมตัวสัมภาษณ์การเขียนโค้ดจากบทเรียนนี้

สรุปบทเรียน

ในบทเรียนนี้ คุณได้เรียนรู้ว่า การกักน้ำฝนแก้ได้ด้วยการหาค่าต่ำสุดของผนังซ้ายและขวาที่สูงที่สุด ณ แต่ละตำแหน่ง แนวทางตัวชี้สองตัวที่ใช้พื้นที่ O(1) ทำงานได้เพราะค่าสูงสุดสะสมของด้านที่เล็กกว่าจะเป็นเงื่อนไขจำกัดที่มีผลเสมอ และ แนวทางสแตกโมโนโทนคำนวณน้ำเป็นชั้นแนวนอน จึงมีประโยชน์เมื่อนำไปใช้ร่วมกับตรรกะอื่นที่ใช้สแตกเป็นพื้นฐาน บทถัดไปเราจะเปลี่ยนไปเรียนแนวคิดการออกแบบระบบ โดยเริ่มจากกรอบงาน RADIO สำหรับคำตอบสัมภาษณ์อย่างเป็นระบบ

เริ่มต้นได้ฟรี

เรียนรู้ Coding Interview Prep ด้วย AI tutor — ฟรี

เขียนและเรียกใช้โค้ดจริงในเบราว์เซอร์ของคุณ รับความช่วยเหลือทันทีจาก AI tutor 24/7 และเรียนรู้ต่อจากที่คุณหยุดบนเว็บหรือในแอป

คอร์ส
90
บทเรียน
360

คำถามที่พบบ่อย

บทเรียน “กักเก็บน้ำฝน: สแตกและตัวชี้สองตัว” ฟรีหรือไม่

ใช่ — ข้อความเต็มของ “กักเก็บน้ำฝน: สแตกและตัวชี้สองตัว” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Coding Interview Prep ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Coding Interview Prep มีบทเรียนทั้งหมด 4 บทเรียน

คุณจะเรียนรู้อะไรในบทเรียน “กักเก็บน้ำฝน: สแตกและตัวชี้สองตัว”

แก้ปัญหาการกักเก็บน้ำฝนด้วยทั้งวิธีสแตกโมโนโทนิกที่คำนวณเป็นชั้นแนวนอน และวิธีตัวชี้สองตัวที่คำนวณเป็นคอลัมน์แนวตั้ง คุณปฏิบัติ Coding Interview Prep ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน

คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Coding Interview Prep หรือไม่

ไม่จำเป็นต้องมีประสบการณ์มาก่อน Coding Interview Prep บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 4 จากทั้งหมด 4 บทเรียน

บทเรียน “กักเก็บน้ำฝน: สแตกและตัวชี้สองตัว” ใช้เวลานานแค่ไหน

บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย

ฉันเขียนและรันโค้ดในบทเรียน Coding Interview Prep นี้ได้ไหม

ได้ บทเรียน Coding Interview Prep ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

บทเรียนทั้งหมดในหลักสูตรนี้

  1. สแตกโมโนโทนิก: เพิ่มขึ้นเทียบกับลดลง
  2. สี่เหลี่ยมผืนผ้าที่ใหญ่ที่สุดในฮิสโตแกรม
  3. ค่าสูงสุดในหน้าต่างเลื่อนด้วยคิวสองทางโมโนโทนิก
  4. กักเก็บน้ำฝน: สแตกและตัวชี้สองตัว
← กลับไปที่ Coding Interview Prep