Pattern · Quy hoạch động 1 chiềuTrung bình
Dãy Con Tăng Dài NhấtLongest Increasing Subsequence
Hiểu bài
Cho mảng số nguyên nums. Tìm độ dài dãy con tăng nghiêm ngặt (strictly increasing subsequence) dài nhất. Dãy con không cần liên tiếp.
Ví dụ:
ts
nums = [10, 9, 2, 5, 3, 7, 101, 18]
output = 4 // dãy con: [2, 3, 7, 101] hoặc [2, 5, 7, 101]
nums = [0, 1, 0, 3, 2, 3]
output = 4 // dãy con: [0, 1, 2, 3]
nums = [7, 7, 7, 7]
output = 1 // chỉ 1 phần tử (tăng nghiêm ngặt, không có 2 phần tử bằng nhau)Điểm quan trọng: "dãy con" (subsequence) khác "dãy con liên tiếp" (subarray) — có thể bỏ qua phần tử giữa.
Cách cơ bản
O(n²) time, O(n) spacets
// DP O(n²) — kinh điển, đủ cho phỏng vấn
function lengthOfLIS(nums: number[]): number {
const n = nums.length
if (n === 0) return 0 // mảng rỗng → LIS = 0 (tránh Math.max(...[]) = -Infinity)
// dp[i] = độ dài LIS kết thúc tại vị trí i
const dp = new Array(n).fill(1)
for (let i = 1; i < n; i++) {
for (let j = 0; j < i; j++) {
if (nums[j] < nums[i]) {
// nums[i] có thể nối sau nums[j]
dp[i] = Math.max(dp[i], dp[j] + 1)
}
}
}
return Math.max(...dp)
}Vì sao cách này chậm:
Với mỗi vị trí i, xét tất cả j < i để tìm phần tử nhỏ hơn có thể đứng trước.
Đủ tốt cho n ≤ 2500, nhưng với n = 10⁵ cần O(n log n).
Mở khoá để xem lời giải tối ưu, chạy thử từng bước và câu hỏi liên quan
Xem đầy đủ chạy thử từng bước, Big-O, trường hợp biên và biến thể công ty Việt Nam.