SOURCE

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 命令行工具 X clear

                    
>
console