返回

通过 12 道经典 JavaScript 逻辑题挑战您的编码技能

前端

算法问题及其解决方法

在计算机科学领域,算法发挥着至关重要的作用。算法是解决特定问题的明确定义的步骤序列。它指导计算机有效地执行任务,从简单的数学运算到复杂的数据处理。本文将深入探讨八个常见的算法问题及其解决方法,为程序员和技术爱好者提供宝贵的知识和见解。

1. 求最大公约数

最大公约数(GCD) 是两个或多个整数的最大公因子。欧几里得算法是一种有效的算法,可以计算任意两个整数的最大公约数。该算法基于这样一个原则:两个数的最大公约数等于较小数和较大数除以较小数的余数的最大公约数。通过重复应用这个原则,我们可以逐步缩小最大公约数,直到达到 0。

function gcd(a, b) {
  if (b === 0) {
    return a;
  } else {
    return gcd(b, a % b);
  }
}

console.log(gcd(2154, 458)); // 输出:2

2. 斐波那契数列

斐波那契数列 是一个数字序列,其中每个数字都是前两个数字之和。该数列以 0 和 1 开始,然后依次为 1、2、3、5、8、13 等。斐波那契数列经常出现在自然界和计算机科学中。

function fibonacci(n) {
  if (n <= 1) {
    return n;
  } else {
    return fibonacci(n - 1) + fibonacci(n - 2);
  }
}

console.log(fibonacci(10)); // 输出:55

3. 汉诺塔问题

汉诺塔问题 是一个古老的数学难题,涉及将一堆圆盘从一个杆移动到另一个杆,每次只能移动一个圆盘,并且较大的圆盘不能放在较小的圆盘上。

function hanoi(n, from, to, via) {
  if (n === 1) {
    console.log(`Move disk 1 from ${from} to ${to}`);
  } else {
    hanoi(n - 1, from, via, to);
    console.log(`Move disk ${n} from ${from} to ${to}`);
    hanoi(n - 1, via, to, from);
  }
}

hanoi(3, 'A', 'C', 'B');

4. 八皇后问题

八皇后问题 是国际象棋领域的一个组合问题,目标是将八个皇后放置在 8x8 的棋盘上,使任何两个皇后都不处于同一行、同一列或同一对角线上。

function isSafe(board, row, col) {
  for (let i = 0; i < row; i++) {
    if (board[i][col] === 1) {
      return false;
    }
  }

  for (let i = row, j = col; i >= 0 && j >= 0; i--, j--) {
    if (board[i][j] === 1) {
      return false;
    }
  }

  for (let i = row, j = col; i >= 0 && j < board.length; i--, j++) {
    if (board[i][j] === 1) {
      return false;
    }
  }

  return true;
}

function solveNQueens(n) {
  const board = new Array(n).fill(0).map(() => new Array(n).fill(0));
  if (solveNQueensUtil(board, 0, n) === true) {
    printSolution(board);
    return;
  } else {
    console.log('没有解');
  }
}

function solveNQueensUtil(board, row, n) {
  if (row === n) {
    return true;
  }

  for (let col = 0; col < n; col++) {
    if (isSafe(board, row, col)) {
      board[row][col] = 1;
      if (solveNQueensUtil(board, row + 1, n)) {
        return true;
      }
      board[row][col] = 0;
    }
  }

  return false;
}

function printSolution(board) {
  for (let i = 0; i < board.length; i++) {
    for (let j = 0; j < board[i].length; j++) {
      console.log(board[i][j] === 1 ? 'Q' : '-');
    }
    console.log('');
  }
}

solveNQueens(4);

5. 旅行商问题

旅行商问题 是一个著名的组合优化问题,目标是找到访问一组城市并返回起点的最短路径,同时只访问每个城市一次。

function tsp(graph, s) {
  const n = graph.length;
  const visited = new Array(n).fill(false);
  const path = [];
  const minPath = [];
  let minPathLength = Infinity;

  function dfs(vertex, currentPath, currentLength) {
    if (visited[vertex] === true) {
      return;
    }

    visited[vertex] = true;
    currentPath.push(vertex);

    if (currentPath.length === n) {
      if (graph[currentPath[currentPath.length - 1]][s] !== 0) {
        currentLength += graph[currentPath[currentPath.length - 1]][s];
        if (currentLength < minPathLength) {
          minPathLength = currentLength;
          minPath = [...currentPath];
        }
      }
    } else {
      for (let i = 0; i < n; i++) {
        if (graph[vertex][i] !== 0 && visited[i] === false) {
          dfs(i, currentPath, currentLength + graph[vertex][i]);
        }
      }
    }

    visited[vertex] = false;
    currentPath.pop();
  }

  dfs(s, path, 0);
  return minPath;
}

const graph = [
  [0, 10, 15, 20],
  [10, 0, 35, 25],
  [15, 35, 0, 30],
  [20, 25, 30, 0],
];

console.log(tsp(graph, 0)); // 输出:[0, 1, 2, 3, 0]

6. 0-1 背包问题

0-1 背包问题 是一个组合优化问题,目标是在给定的背包容量下,从一组物品中选择一些物品,使背包的总价值最大化。

function knapsack(items, capacity) {
  const n = items.length;
  const dp = new Array(n + 1).fill(0).map(() => new Array(capacity + 1).fill(0));

  for (let i = 1; i <= n; i++) {
    for (let j = 1; j <= capacity; j++) {
      if (items[i - 1].weight > j) {
        dp[i][j] = dp[i - 1][j];
      } else {
        dp[i][j] = Math.max(dp[i - 1][j], items[i - 1].value + dp[i - 1][j - items[i - 1].weight]);
      }
    }
  }

  return dp[n][capacity];
}

const items = [
  { weight: 1, value: 10 },
  { weight: 3, value: 40 },
  { weight: 4, value: 50 },
  { weight: 5, value: 70 },
];

console.log(knapsack(items, 8)); // 输出:110

7. 最长公共子序列

最长公共子序列(LCS) 问题是找出两个字符串中最长的公共子序列,即在两个字符串中都按相同顺序出现的字符序列。

function lcs(x, y) {
  const m = x.length;
  const n = y.length;
  const dp = new Array(m + 1).fill(0).map(() => new Array(n + 1).fill(0));

  for (let i = 1; i <= m; i++) {
    for (let j = 1; j <= n; j++) {