Notes & software courses · Free to learn
Aph's Blog
On this page

ข้อ 51 · LC2542 Maximum Subsequence Score (คะแนน subsequence มากสุด) 🟡

👋 อ่านฟรีทั้งหมดบน Aph's Blog — เนื้อหาภาษาไทย ทำตามทีละหน้าใน sidebar ได้เลย หากมีข้อเสนอแนะหรืออยากให้เพิ่มหัวข้อไหน บอกได้เสมอ

score (คะแนน) = sum (ผลรวม) nums1 คูณ min ของ nums2 ตรึง min ไว้ด้วยการ sort แล้วใช้ min-heap maintain sum nums1 ให้มากสุด

โจทย์ (LC2542): กำหนด array จำนวนเต็ม nums1 และ nums2 ที่ยาวเท่ากัน n ตัว พร้อมจำนวนเต็มบวก k ให้เลือก index มา k ตำแหน่งจาก nums1 (แบบ subsequence) โดยนิยาม score (คะแนน) ของชุดที่เลือกคือ ผลรวมของค่า nums1 ที่ตำแหน่งที่เลือก คูณด้วยค่า minimum ของ nums2 ที่ตำแหน่งเดียวกันที่เลือก ให้ return score ที่มากที่สุดที่เป็นไปได้

Example 1
Input:
nums1 = [1, 3, 3, 2], nums2 = [2, 1, 3, 4], k = 3
Output:
12
Explanation:
เลือก index 0, 2, 3: ผลรวม nums1 = 1+3+2 = 6, min ของ nums2 ที่เลือก = min(2,3,4) = 2, คะแนน = 6*2 = 12 (ถ้าเลือก index 0,1,2 แทนจะได้แค่ (1+3+3)*min(2,1,3) = 7 ซึ่งน้อยกว่า)
Example 2
Input:
nums1 = [4, 2, 3, 1, 1], nums2 = [7, 5, 10, 9, 6], k = 1
Output:
30
Explanation:
k = 1 เลือกได้ตัวเดียว การเลือก index 2 ให้คะแนนดีที่สุด: nums1[2] * nums2[2] = 3 * 10 = 30
Constraints (ข้อจำกัด)
  • n == nums1.length == nums2.length
  • 1 <= n <= 10^5
  • 0 <= nums1[i], nums2[j] <= 10^5
  • 1 <= k <= n

แนวทาง — ต้องใช้อะไร & คิดยังไง

โครงสร้างที่ใช้: sort (เรียง) + min-heap ความยากของโจทย์คือ score ขึ้นกับสองอย่างพร้อมกัน: sum nums1 (ยิ่งมากยิ่งดี) กับ min ของ nums2 (ยิ่งมากยิ่งดี) การ handle สองตัวแปรพร้อมกันยาก เทคนิคคือ ตรึง (fix) ตัวหนึ่งไว้ก่อน

คิดแบบง่าย/ช้าก่อน: ลองทุก subset (สับเซ็ต) ขนาด k แล้วคิด score เป็น O(C(n,k)) ซึ่งระเบิดทันที เราจึง sort คู่ (nums1, nums2) ตาม nums2 จากมากไปน้อย แล้ว iterate ไปทีละตัว เมื่อถึงคู่ที่ nums2 = b เราตั้งให้ b เป็นตัว minimum ของกลุ่ม แปลว่าเลือกได้เฉพาะตัวที่มาก่อนหน้า (nums2 ใหญ่กว่าหรือเท่ากับ b) เท่านั้น

  1. จับคู่ zip(nums1, nums2) แล้ว sort ตาม nums2 จากมากไปน้อย
  2. iterate ทีละคู่ (a, b): push a เข้า min-heap และบวก a เข้าตัวแปร total
  3. ถ้า heap เกิน k ตัว ให้ pop ตัว nums1 ที่ minimum ออก พร้อมลบมันออกจาก total
  4. เมื่อ heap ครบ k ตัวพอดี b ตัวปัจจุบันคือ min ของ nums2 ในกลุ่ม compute total * b แล้ว track ค่ามากสุดไว้ใน best
จุดพลาดที่พบบ่อย

ลืม update total ตอน pop (ต้องลบค่าที่ pop ออกด้วย) หรือ compute score ตอนที่ heap ยังไม่ครบ k ตัว ต้องเช็ค len(heap) == k ก่อนคิด score เสมอ

ไล่ทีละสเต็ป

จำลอง nums1 = [1,3,3,2], nums2 = [2,1,3,4], k = 3 หลัง sort ตาม nums2 มากไปน้อยได้ pairs = [(2,4),(3,3),(1,2),(3,1)]:

คู่ (a,b)heap หลัง pushtotalเกิน k? (pop)คิด total*b เมื่อครบ k
(2,4)[2]2ไม่-
(3,3)[2,3]5ไม่-
(1,2)[1,3,2]6ไม่6*2 = 12
(3,1)[3,3,3]9→8ใช่ pop 18*1 = 8

best = max(12, 8) = 12

▶ เฉลยละเอียด (ลองเองก่อนนะ)
เฉลย (Python) — โค้ดนี้รันได้จริงpython
import heapq

def max_score(nums1, nums2, k):
    # จับคู่แล้วเรียงตาม nums2 จากมากไปน้อย
    pairs = sorted(zip(nums1, nums2), key=lambda p: -p[1])

    heap = []          # min-heap เก็บค่า nums1 ของตัวที่เลือกไว้
    total = 0          # ผลรวม nums1 ในกลุ่มที่เลือก
    best = 0
    for a, b in pairs:
        heapq.heappush(heap, a)
        total += a
        # ถ้าเลือกเกิน k ตัว ทิ้ง nums1 ที่น้อยสุดออก
        if len(heap) > k:
            total -= heapq.heappop(heap)
        # เมื่อครบ k ตัว: b ตัวปัจจุบันคือ min ของ nums2 ในกลุ่ม (เพราะเรียงลดหลั่น)
        if len(heap) == k:
            best = max(best, total * b)
    return best

print(max_score([1, 3, 3, 2], [2, 1, 3, 4], 3))  # 12
print(max_score([4, 2, 3, 1, 1], [7, 5, 10, 9, 6], 1))  # 30
Output
12
30

เมื่อเรา sort ตาม nums2 จากมากไปน้อย แล้ว iterate ไปทีละตัว ณ คู่ปัจจุบัน b คือ nums2 ที่เล็กที่สุดในบรรดาคู่ที่เห็นมาแล้ว (เพราะที่มาก่อนหน้าล้วนมี nums2 มากกว่าหรือเท่ากับ b) ดังนั้นถ้าเราเลือก k ตัวจากกลุ่มที่เห็นมาแล้วโดยรวม b ด้วย min ของ nums2 ในกลุ่มจะเป็น b พอดี

เมื่อ b ถูก fix เป็น min แล้ว เราแค่อยากให้ sum nums1 ของ k ตัวมากที่สุด จึงใช้ min-heap ขนาด k เก็บค่า nums1 พร้อมตัวแปร total ตาม sum ไว้ เมื่อ heap เกิน k ก็ evict nums1 ตัวเล็กสุดออก (พร้อมลบออกจาก total) ถ้าไม่ลบออกจาก total score จะเพี้ยนสูงเกินจริงทันที

Time O(n log n) จากการ sort บวกการ iterate push/pop heap อีก O(n log k) · Space O(n) สำหรับ array คู่ที่ sort แล้ว และ heap ขนาด k

💡 สรุป pattern

โจทย์ที่ score ขึ้นกับสอง factor (ปัจจัย) พร้อมกัน ให้ fix ปัจจัยหนึ่งด้วยการ sort (ตัวคูณ min/max) แล้วปล่อยให้ heap จัดการอีก factor (sum top-k) เป็น pattern ที่เจอบ่อยในโจทย์ optimize สองมิติ