Ngày Được Tự Do
Senior Member
sao lại nghĩ ra dùng heap vậy fenTiếp tục chuyên mục mỗi ngày một leetcode. 4 bài mình làm ngày hôm nay:
#371. (Medium) https://leetcode.com/problems/sum-of-two-integers/
#372. (Medium) https://leetcode.com/problems/super-pow/
#373. (Medium) https://leetcode.com/problems/find-k-pairs-with-smallest-sums/
#374. (Easy) https://leetcode.com/problems/guess-number-higher-or-lower/
Mình sẽ share về bài Find K Pairs with Smallest Sums:
#373. (Medium) https://leetcode.com/problems/find-k-pairs-with-smallest-sums/
Phân tích bài toán:
Solution:
- 1 <= nums1.length, nums2.length <= 10^4: Độ phức tạp kì vọng có lẽ là O(nlogn)
- Dữ liệu đã sắp xếp sẵn nên không cần sắp xếp lại
- Đề bài yêu cầu lấy ra k cặp số có tổng nhỏ nhất, từ 2 mảng
- Dễ thấy cặp số nhỏ nhất chắc chắn là 2 phần tử đầu tiên của 2 mảng (nums1[0], nums2[0])
- Với cặp số thứ 2, đó có thể là (nums1[1], nums2[0]) hoặc (nums1[0], nums2[1]). Tùy theo cái nào nhỏ hơn.
- Với cặp số thứ 3, nó phụ thuộc vào cách ta chọn cặp số thứ 2, các khả năng có thể là
- (nums1[1], nums2[1]) và (nums1[0], nums2[2]). Nếu lần trước ta chọn cặp (nums1[0], nums2[1])
- (nums1[1], nums2[1]) và (nums1[2], nums2[0]). Nếu lần trước ta chọn cặp (nums1[1], nums2[0])
- Đến đây ta rút ra 2 kết luận:
- Nếu lần trước ta chọn cặp số thứ (nums1, nums1[j]). Thì tiếp theo sẽ phát sinh thêm 2 khả năng (nums1, nums2[j + 1]) hoặc (nums1[i + 1], nums2[j])
- Pattern ở đây là có một mảng các số (là tổng của cặp số), và ta liên tục lấy ra các số số nhỏ nhất, không quan tâm các số còn lại => Phù hợp với cấu trúc dữ liệu heap
- Khởi tạp heap với cặp đầu tiên là (0, 0)
- Lặp cho đến khi lấy được k kết quả, hoặc hết heap
- Lấy kết quả nhỏ nhất ra, cho và mảng output
- Thay thế nó bằng 2 khả năng mới là (i + 1, j) và (i, j + 1)
- Return về mảng output
Python:class Solution: def kSmallestPairs(self, nums1: List[int], nums2: List[int], k: int) -> List[List[int]]: j = [0] * len(nums1) h = [(nums1[0] + nums2[0], 0, 0)] visited = set() res = [] while h and len(res) < k: val, i, j = heappop(h) res.append([nums1[i], nums2[j]]) if i < len(nums1) - 1 and (i + 1, j) not in visited: heappush(h, (nums1[i + 1] + nums2[j], i + 1, j)) visited.add((i + 1, j)) if j < len(nums2) - 1 and (i, j + 1) not in visited: heappush(h, (nums1[i] + nums2[j + 1], i, j + 1)) visited.add((i, j + 1)) return res

