Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> Python

Python - หาความยาวสับลิสต์ที่ยาวที่สุดที่ตรงตามเงื่อนไขช่วงค่า

โจทย์: กำหนดให้มีรายการตัวเลขชื่อ nums ต้องการหาความยาวของสับลิสต์ (Sublist/Subarray) ที่ยาวที่สุดที่ทำให้ 2 × (ค่าต่ำสุดของสับลิสต์) > (ค่าสูงสุดของสับลิสต์)

ตัวอย่าง

Input: nums = [10, 2, 6, 6, 4, 4]
Output: 4
เหตุผล: สับลิสต์ [6, 6, 4, 4] เป็นสับลิสต์ที่ยาวที่สุดที่ตรงเงื่อนไข (2×4) > 6 → 8 > 6 ✓

อัลกอริทึม: Sliding Window + Double-ended Queue (Deque)

ใช้เทคนิค Two Pointers (Two Pointers / Sliding Window) ร่วมกับ Deque สองอันเพื่อติดตามค่าต่ำสุดและค่าสูงสุดในหน้าต่างปัจจุบันอย่างมีประสิทธิภาพ O(n)

ขั้นตอนการทำงาน

  1. minq: Deque เก็บดัชนีของค่าต่ำสุด (ค่าจะเรียงจากน้อยไปมาก)
  2. maxq: Deque เก็บดัชนีของค่าสูงสุด (ค่าจะเรียงจากมากไปน้อย)
  3. ขยายหน้าต่างด้านขวา (r) และอัปเดต Deque ทั้งสอง
  4. หากเงื่อนไข nums[minq[0]] * 2 <= nums[maxq[0]] ถูกละเมิด ให้ย่อหน้าต่างด้านซ้าย (l)
  5. อัปเดตคำตอบสูงสุดตลอดเวลา

การใช้งาน Deque

  • minq: รักษาลำดับเพิ่มขึ้น (Increasing) - หัวคือค่าต่ำสุด
  • maxq: รักษาลำดับลดลง (Decreasing) - หัวคือค่าสูงสุด
  • เมื่อเพิ่มค่าใหม่ ให้ลบค่าที่ไม่เกี่ยวข้องออกจากท้าย Deque ก่อน

โค้ด Python

from collections import deque

def solve(nums):
    ret = 0
    minq, maxq = deque(), deque()
    l, r = 0, 0
    
    while r < len(nums):
        n = nums[r]
        
        # อัปเดต minq: รักษาลำดับเพิ่มขึ้น
        while minq and n < nums[minq[-1]]:
            minq.pop()
        minq.append(r)
        
        # อัปเดต maxq: รักษาลำดับลดลง
        while maxq and n > nums[maxq[-1]]:
            maxq.pop()
        maxq.append(r)
        
        r += 1
        
        # ย่อหน้าต่างหากเงื่อนไขถูกละเมิด
        while l < r and nums[minq[0]] * 2 <= nums[maxq[0]]:
            if minq[0] == l:
                minq.popleft()
            if maxq[0] == l:
                maxq.popleft()
            l += 1
        
        # อัปเดตคำตอบ
        ret = max(ret, r - l)
    
    return ret

# ทดสอบ
nums = [10, 2, 6, 6, 4, 4]
print(solve(nums))  # Output: 4

ความซับซ้อน

  • Time Complexity: O(n) - แต่ละองค์ประกอบถูกเพิ่มและลบจาก Deque สูงสุด 1 ครั้ง
  • Space Complexity: O(n) - สำหรับ Deque และตัวแปรช่วย

การทดสอบเพิ่มเติม

# ทดสอบกรณีต่างๆ
print(solve([1, 2, 3, 4, 5]))      # 2 (เช่น [1,2] หรือ [2,3] ฯลฯ)
print(solve([5, 4, 3, 2, 1]))      # 5 (ทั้งอาร์เรย์ 2*1 > 5? ไม่ 2*1=2 < 5... ต้องทดสอบจริง)
print(solve([10, 10, 10, 10]))     # 4 (2*10 > 10 ✓)
print(solve([]))                    # 0