返回

算法精进系列之链表回文检测

前端

回文链表

回文链表是一种特殊的链表,它从左读和从右读都是一样的。例如,以下链表是一个回文链表:

1 -> 2 -> 3 -> 2 -> 1

这个链表从左读是1 -> 2 -> 3 -> 2 -> 1,从右读也是1 -> 2 -> 3 -> 2 -> 1。

判断回文链表的算法

判断回文链表的算法主要有以下几个步骤:

  1. 将链表分为两部分,前半部分和后半部分。
  2. 反转后半部分的链表。
  3. 比较前半部分和后半部分的链表,如果相等,则链表是回文链表,否则不是。

JavaScript代码示例

// 定义链表节点对象
function Node(data) {
  this.data = data;
  this.next = null;
}

// 定义链表类
function LinkedList() {
  this.head = null;
  this.tail = null;

  // 在链表尾部添加一个新节点
  this.add = function(data) {
    let newNode = new Node(data);

    if (this.head === null) {
      this.head = newNode;
      this.tail = newNode;
    } else {
      this.tail.next = newNode;
      this.tail = newNode;
    }
  };

  // 反转链表
  this.reverse = function() {
    let prev = null;
    let current = this.head;
    let next = null;

    while (current !== null) {
      next = current.next;
      current.next = prev;
      prev = current;
      current = next;
    }

    this.head = prev;
  };

  // 判断链表是否为回文链表
  this.isPalindrome = function() {
    // 将链表分为两部分
    let slow = this.head;
    let fast = this.head;

    while (fast !== null && fast.next !== null) {
      slow = slow.next;
      fast = fast.next.next;
    }

    // 反转后半部分的链表
    let後半部 = slow;
    後半部.reverse();

    // 比较前半部分和后半部分的链表
    let前半部 = this.head;
    while (後半部 !== null) {
      if (前半部.data !== 後半部.data) {
        return false;
      }
      前半部 = 前半部.next;
      後半部 = 後半部.next;
    }

    return true;
  };
}

// 创建一个回文链表
let linkedList = new LinkedList();
linkedList.add(1);
linkedList.add(2);
linkedList.add(3);
linkedList.add(2);
linkedList.add(1);

// 判断链表是否为回文链表
if (linkedList.isPalindrome()) {
  console.log("链表是回文链表");
} else {
  console.log("链表不是回文链表");
}

运行上面的代码,将在控制台输出"链表是回文链表",因为创建的链表是一个回文链表。如果将链表修改为1 -> 2 -> 3 -> 4 -> 5,然后运行代码,将在控制台输出"链表不是回文链表",因为修改后的链表不是回文链表。

总结

回文链表是一种特殊的链表,它从左读和从右读都是一样的。判断回文链表的算法主要有以下几个步骤:

  1. 将链表分为两部分,前半部分和后半部分。
  2. 反转后半部分的链表。
  3. 比较前半部分和后半部分的链表,如果相等,则链表是回文链表,否则不是。

本文提供了详细的JavaScript代码示例,帮助读者理解并掌握算法的实现原理。