function getSequence(source) {
const len = source.length;
if (len === 0) return [];
// tails[i] = 索引,表示长度为 i+1 的递增子序列的最小末尾元素在 source 中的位置
const tails = [0];
// p[i] 记录 source[i] 在 LIS 中的前一个元素的索引
const p = new Array(len).fill(-1);
let size = 1; // 当前 LIS 长度
for (let i = 1; i < len; i++) {
if (source[i] < 0) continue;
const lastTailIndex = tails[size - 1];
if (source[lastTailIndex] < source[i]) {
// 可以延长 LIS
p[i] = lastTailIndex;
tails[size] = i;
size++;
} else {
// 二分查找:找到第一个 >= source[i] 的位置
let left = 0;
let right = size - 1;
while (left < right) {
const mid = (left + right) >> 1;
if (source[tails[mid]] < source[i]) {
left = mid + 1;
} else {
right = mid;
}
}
// 替换
if (source[i] < source[tails[left]]) {
if (left > 0) {
p[i] = tails[left - 1];
}
tails[left] = i;
}
}
}
// 回溯构造 LIS 的索引序列
const seq = new Array(size);
let k = tails[size - 1];
for (let i = size - 1; i >= 0; i--) {
seq[i] = k;
k = p[k];
}
return seq;
}
console.log(getSequence([1, 4, 2, 0]));
// 输出: [0, 2] ✅
console.log(getSequence([2, 1, 3, 4]));
// 输出: [1, 2, 3] ✅ (对应值 [1,3,4])
console.log(getSequence([5, 4, 3, 2, 1]));
// 输出: [4] ✅ (任意一个都行,LIS 长度为 1)
console.log(getSequence([1, 2, 3, 4]));
// 输出: [0, 1, 2, 3] ✅
console