You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

递增整数序列模式识别与后续元素生成的JavaScript算法实现咨询

分享一个我之前实现的JavaScript解决方案,专门用来处理这类短递增序列的预测问题,尽可能覆盖常见的序列模式,还能根据输入长度自动筛选最靠谱的模式生成后续元素。

核心思路

因为输入是短序列,我们需要先枚举所有可能符合当前序列的数学模式,然后根据模式的“精确性”排序(比如需要更多输入项才能验证的模式,优先级更高,因为它的假设更具体),最后用优先级最高的模式生成后续10个元素。如果有多个等效优先级的模式,会同时生成多种可能的结果。

支持的常见序列模式

我实现了以下几种最常用的模式,覆盖大部分面试场景:

  • 等差数列:所有相邻元素的差值相等(比如4,14,24,差值10)
  • 线性递推序列:满足current = a * previous + b,当序列长度≥3时可以解出唯一的a和b(比如4,14,34,符合current = 2*prev +6
  • 斐波那契类序列:当前项等于前两项之和(比如1,1,2,3,5
  • 二级等差数列:相邻元素的差值构成等差数列(比如1,3,6,10,差值为2,3,4
  • 等比数列:所有相邻元素的比值相等(比如2,4,8,16,比值2)
  • 平方/立方序列:每个元素是某个整数的平方或立方(比如1,4,9,16是平方序列,1,8,27是立方序列)
JavaScript代码实现
// 解析输入字符串为整数数组
function parseInput(inputStr) {
  return inputStr.split(' ').map(Number).filter(num => !isNaN(num));
}

// 检测等差数列:返回是否匹配,以及生成下一项的函数
function checkArithmetic(seq) {
  if (seq.length < 2) return { match: false };
  const diff = seq[1] - seq[0];
  for (let i = 2; i < seq.length; i++) {
    if (seq[i] - seq[i-1] !== diff) {
      return { match: false };
    }
  }
  return {
    match: true,
    name: '等差数列',
    nextFn: (last) => last + diff
  };
}

// 检测线性递推序列(current = a*prev + b)
function checkLinearRecurrence(seq) {
  if (seq.length < 2) return { match: false };
  // 序列长度为2时,返回两种常见的线性递推解
  if (seq.length === 2) {
    const diff = seq[1] - seq[0];
    return [
      {
        match: true,
        name: `线性递推(${seq[1]} = 1*${seq[0]} + ${diff})`,
        nextFn: (last) => last + diff
      },
      {
        match: true,
        name: `线性递推(${seq[1]} = 2*${seq[0]} + ${seq[1]-2*seq[0]})`,
        nextFn: (last) => 2 * last + (seq[1] - 2 * seq[0])
      }
    ];
  }
  // 序列长度≥3时,解方程组验证唯一的a和b
  const a = (seq[2] - seq[1]) / (seq[1] - seq[0]);
  if (!Number.isInteger(a)) return { match: false };
  const b = seq[1] - a * seq[0];
  for (let i = 2; i < seq.length; i++) {
    if (seq[i] !== a * seq[i-1] + b) {
      return { match: false };
    }
  }
  return {
    match: true,
    name: `线性递推(current = ${a}*prev + ${b})`,
    nextFn: (last) => a * last + b
  };
}

// 检测斐波那契类序列(当前项=前两项之和)
function checkFibonacci(seq) {
  if (seq.length < 3) return { match: false };
  for (let i = 2; i < seq.length; i++) {
    if (seq[i] !== seq[i-1] + seq[i-2]) {
      return { match: false };
    }
  }
  return {
    match: true,
    name: '斐波那契类序列(前两项之和)',
    nextFn: (last, secondLast) => last + secondLast
  };
}

// 检测二级等差数列
function checkSecondOrderArithmetic(seq) {
  if (seq.length < 3) return { match: false };
  const diffs = [];
  for (let i = 1; i < seq.length; i++) {
    diffs.push(seq[i] - seq[i-1]);
  }
  const arithmeticCheck = checkArithmetic(diffs);
  if (!arithmeticCheck.match) return { match: false };
  return {
    match: true,
    name: '二级等差数列',
    nextFn: (last) => {
      const lastDiff = diffs[diffs.length - 1];
      const nextDiff = arithmeticCheck.nextFn(lastDiff);
      return last + nextDiff;
    }
  };
}

// 检测等比数列
function checkGeometric(seq) {
  if (seq.length < 2) return { match: false };
  const ratio = seq[1] / seq[0];
  if (!Number.isInteger(ratio)) return { match: false };
  for (let i = 2; i < seq.length; i++) {
    if (seq[i] / seq[i-1] !== ratio) {
      return { match: false };
    }
  }
  return {
    match: true,
    name: `等比数列(比值${ratio})`,
    nextFn: (last) => last * ratio
  };
}

// 检测平方/立方序列
function checkPowerSequence(seq) {
  const possiblePowers = [];
  // 检查平方序列
  const squareRoots = seq.map(num => Math.sqrt(num));
  if (squareRoots.every(root => Number.isInteger(root))) {
    const lastRoot = squareRoots[squareRoots.length - 1];
    possiblePowers.push({
      match: true,
      name: '平方序列',
      nextFn: () => (lastRoot + 1) ** 2
    });
  }
  // 检查立方序列
  const cubeRoots = seq.map(num => Math.cbrt(num));
  if (cubeRoots.every(root => Math.abs(root - Math.round(root)) < 1e-9)) {
    const lastRoot = Math.round(cubeRoots[cubeRoots.length - 1]);
    possiblePowers.push({
      match: true,
      name: '立方序列',
      nextFn: () => (lastRoot + 1) ** 3
    });
  }
  return possiblePowers.length > 0 ? possiblePowers : { match: false };
}

// 收集所有匹配的模式并去重
function getAllMatchingPatterns(seq) {
  const patterns = [];
  // 逐个检查每种模式
  const arithmetic = checkArithmetic(seq);
  if (arithmetic.match) patterns.push(arithmetic);
  
  const linear = checkLinearRecurrence(seq);
  if (Array.isArray(linear)) {
    linear.filter(p => p.match).forEach(p => patterns.push(p));
  } else if (linear.match) {
    patterns.push(linear);
  }
  
  const fibonacci = checkFibonacci(seq);
  if (fibonacci.match) patterns.push(fibonacci);
  
  const secondOrder = checkSecondOrderArithmetic(seq);
  if (secondOrder.match) patterns.push(secondOrder);
  
  const geometric = checkGeometric(seq);
  if (geometric.match) patterns.push(geometric);
  
  const power = checkPowerSequence(seq);
  if (Array.isArray(power)) {
    power.forEach(p => patterns.push(p));
  } else if (power.match) {
    patterns.push(power);
  }
  
  // 去重避免重复模式
  return Array.from(new Map(patterns.map(p => [p.name, p])).values());
}

// 根据模式生成后续n个元素
function generateFromPattern(seq, pattern, count) {
  const result = [...seq];
  for (let i = 0; i < count; i++) {
    let next;
    if (pattern.name.includes('斐波那契')) {
      next = pattern.nextFn(result[result.length-1], result[result.length-2]);
    } else {
      next = pattern.nextFn(result[result.length-1]);
    }
    result.push(next);
  }
  return result.slice(seq.length);
}

// 生成后续元素的主函数
function generateNextElements(seq, count = 10) {
  const patterns = getAllMatchingPatterns(seq);
  if (patterns.length === 0) {
    // 无匹配模式时,默认使用最后一个差值的等差模式
    const diff = seq.length >=2 ? seq[seq.length-1] - seq[seq.length-2] : 1;
    const defaultPattern = {
      name: '默认等差模式',
      nextFn: (last) => last + diff
    };
    return [{
      patternName: defaultPattern.name,
      nextElements: generateFromPattern(seq, defaultPattern, count)
    }];
  }
  
  // 按模式优先级排序:需要更多输入项的模式优先级更高
  const priorityOrder = {
    '二级等差数列': 5,
    '斐波那契类序列(前两项之和)': 4,
    '线性递推(current = a*prev + b)': 3,
    '等比数列(比值a)': 2,
    '平方序列': 2,
    '立方序列': 2,
    '等差数列': 1,
    '默认等差模式': 0
  };
  patterns.sort((a, b) => (priorityOrder[b.name] || 0) - (priorityOrder[a.name] || 0));
  
  // 提取所有最高优先级的模式
  const highestPriority = priorityOrder[patterns[0].name] || 0;
  const topPatterns = patterns.filter(p => (priorityOrder[p.name] || 0) === highestPriority);
  
  return topPatterns.map(pattern => ({
    patternName: pattern.name,
    nextElements: generateFromPattern(seq, pattern, count)
  }));
}

// 示例调用函数
function runExample(inputStr) {
  const seq = parseInput(inputStr);
  console.log(`输入序列: ${seq.join(', ')}`);
  const results = generateNextElements(seq);
  results.forEach(res => {
    console.log(`根据【${res.patternName}】生成的后续10个元素: ${res.nextElements.join(', ')}`);
  });
  console.log('---');
}

// 测试示例
runExample("4 14");
runExample("4 14 34");
runExample("1 1 2 3");
runExample("1 3 6 10");
runExample("2 4 8 16");
runExample("1 4 9 16");
测试结果说明
  • 输入4 14:会匹配等差数列和两种线性递推模式,生成两种可能的后续序列(24,34,44,...34,74,154,...
  • 输入4 14 34:只有线性递推模式匹配(current=2*prev+6),生成74, 154, 314, 634, 1274, 2554, 5114, 10234, 20474, 40954
  • 输入1 1 2 3:匹配斐波那契类序列,生成5,8,13,21,34,55,89,144,233,377
  • 输入1 3 6 10:匹配二级等差数列,生成15,21,28,36,45,55,66,78,91,105

内容的提问来源于stack exchange,提问作者Development Flow

火山引擎 最新活动