最近在刷算法題時,又遇到了一道非常經典的貪心題目:給定若干閉區間,求最少需要多少個點,使得每個區間至少包含一個點。這道題看似簡單,卻完美展現了貪心策略的用處。

問題描述

輸入:
\(n\) 個閉區間 \([l_i, r_i]\)(\(1 \le i \le n\))

輸出:
最少需要放置多少個點,使得每個區間都至少包含一個點。

例如:

區間:[1,3], [2,5], [4,6]
答案:2(比如在點3和點6處放置)

我的解法:右端點優先,貪心選點

核心思想:
把所有區間按右端點從小到大排序,然後儘可能“晚”地放點——也就是放在當前區間的右端點上。

為什麼這樣做?

你希望一個點能覆蓋儘可能多的後續區間。那麼,越靠右放,越容易“錯過”後面的區間;而越靠左放,又可能浪費了覆蓋能力。
但如果我們在當前未被覆蓋的區間中,選擇右端點最小的那個,並把點放在它的右端點上,就能保證這個點“剛好”覆蓋它,同時最大化對後續區間的潛在覆蓋能力。

代碼實現(C++)

#include <bits/stdc++.h>
using namespace std;

struct Interval {
	int left, right;
};

bool cmp(const Interval& a, const Interval& b) {
	return a.right < b.right; // 按右端點升序
}

int main() {
	int n;
	cin >> n;
	vector<Interval> intervals(n);
	for (int i = 0; i < n; ++i) {
		cin >> intervals[i].left >> intervals[i].right;
	}

	sort(intervals.begin(), intervals.end(), cmp);

	int pointCount = 0;
	int lastPoint = -1; // 上一個放置的點

	for (int i = 0; i < n; ++i) {
	// 如果當前點沒被覆蓋
		if (lastPoint < intervals[i].left) {
			lastPoint = intervals[i].right; // 在右端點放新點
			pointCount++;
		}
	}

	cout << pointCount << endl;
	return 0;
}

💡 小提示:判斷條件只需 lastPoint < left 即可。因為 lastPoint 始終是非遞減的(我們總是往右放點),不可能出現 lastPoint > right 的情況。

為什麼貪心是對的?

要證明貪心算法的正確性,通常需要兩個關鍵性質:

  1. 貪心選擇性質(Greedy Choice Property)
    存在一個最優解,其中第一個點就放在右端點最小的區間的右端點上。
    證明思路
    假設最優解中第一個點 \(p\) 覆蓋了第一個區間 \([l_1, r_1]\),那麼 \(p \in [l_1, r_1]\)。
    如果我們把 \(p\) 改成 \(r_1\),會發生什麼?
    它依然覆蓋 \([l_1, r_1]\);
    對於其他被 \(p\) 覆蓋的區間 \([l_j, r_j]\),由於我們按 \(r\) 排序,有 \(r_j \ge r_1\);
    又因為 \(p \ge l_j\) 且 \(p \le r_1\),所以 \(l_j \le r_1 \le r_j\),即 \(r_1\)

因此,把點移到 \(r_1\)

  1. 最優子結構(Optimal Substructure)

一旦我們在 \(r_1\) 放了一個點,所有包含 \(r_1\)

複雜度分析

排序:\(O(n \log n)\)
遍歷選點:\(O(n)\)
總時間複雜度:\(O(n \log n)\)
空間複雜度:\(O(n)\)(存儲區間)

效率非常高,適用於大規模數據。

我對貪心算法的理解

貪心算法常常被初學者誤解為“隨便選看起來好的”,但實際上,貪心是一種需要嚴格證明的策略。

它的魅力在於簡潔高效——沒有回溯、沒有狀態記憶,一步到位;直覺友好——很多貪心策略符合人類的“局部最優”直覺;適用性強——在區間問題、圖論(如最小生成樹)、編碼(霍夫曼)等領域大放異彩。

比如本題如果按左端點排序,或者在左端點放點,就可能得到次優解。貪心的正確性必須通過數學證明來支撐,而不是靠測試樣例“蒙對”。

總結

區間選點問題是一個經典的貪心模型;
關鍵策略:按右端點排序 + 在右端點放點;
正確性由貪心選擇性質和最優子結構共同保證;
時間複雜度 \(O(n \log n)\),實用且優雅。