用JS表示双端队列类,且练习用deque实现回文检测

994 阅读3分钟

夯下数据结构和算法基础,JS 里没有栈、队列、链表巴拉巴拉明显的结构,只能用类去伪造,不然做算法题真的费劲。

这次造双端队列类吧,这边底层使用数组,当然有空的话,你也可以试试对象。

基本概念

双端队列是一种允许我们可以同时从前端和后端添加和移除元素的特殊队列。(普通队列是先进先出)

基本方法

  • addFront(element(s)) 在双端队列前端添加新的元素。
  • addBack(element(s)) 在双端队列后端添加新的元素。
  • removeFront() 从双端队列前端移除第一个元素。
  • removeBack() 从双端队列后端移除第一个元素。
  • front() 返回双端队列前端的第一个元素——最先被添加,也将是最先被移除的元素。双端队列不做任何变动(不移除元素,只返回元素信息)。
  • back() 返回双端队列后端的第一个元素——最先被添加,也将是最先被移除的元素。双端队列不做任何变动(不移除元素,只返回元素信息)。
  • size() 返回双端队列包含的元素个数,与数组的 length 属性类似。
  • isEmpty() 如果双端队列中不包含任何元素,返回 true,否则返回 false。
  • clear() 移除双端队列里的所有元素。
class Deque {
  deque: any[];
  constructor() {
    this.deque = [];
  }
  addFront(value: any) {
    this.deque.unshift(value);
  }
  addBack(value: any) {
    this.deque.push(value);
  }
  removeFront() {
    return this.deque.shift();
  }
  removeBack() {
    return this.deque.pop();
  }

  front() {
    return this.deque[0];
  }

  back() {
    return this.deque[this.deque.length - 1];
  }
  size() {
    return this.deque.length;
  }
  isEmpty() {
    return this.size() === 0;
  }
  clear() {
    this.deque = [];
  }
}

可以头上顶个注释,就容易调用方法了

/**
 * 双端队列是一种允许我们同时从前端和后端添加和移除元素的特殊队列。
 *
 * @class Deque
 * @constructor
 * @method addFront(element(s)) 在双端队列前端添加新的元素。
 * @method addBack(element(s)) 在双端队列后端添加新的元素。
 * @method removeFront() 从双端队列前端移除第一个元素。
 * @method removeBack() 从双端队列后端移除第一个元素。
 * @method front() 返回双端队列前端的第一个元素——最先被添加,也将是最先被移除的元素。双端队列不做任何变动(不移除元素,只返回元素信息)。
 * @method back() 返回双端队列后端的第一个元素——最先被添加,也将是最先被移除的元素。双端队列不做任何变动(不移除元素,只返回元素信息)。
 * @method size() 返回双端队列包含的元素个数,与数组的 length 属性类似。
 * @method isEmpty() 如果双端队列中不包含任何元素,返回 true,否则返回 false。
 * @method clear() 移除双端队列里的所有元素。
 * @example
 * const q = new Deque()
 * q.addFront(1)
 * q.addFront(2)
 * q.addBack(3)
 * q.addBack(4)
 * q.removeFront() // 2
 * q.removeBack() // 4
 * q.front() // 1
 * q.back() // 3
 * q.size() // 2
 * q.isEmpty() // false
 * q.clear()
 * q.isEmpty() // true
 *
 */

练习:实现回文检测器

回文,就是正读反读都一样的字符串,比如 'level'、'noon'、'a'、'a b'、'a b c b a'。

可以用双端队列来检测一个字符串是不是回文

主要逻辑:

  • 字符串入队列
  • 队列头尾同时抛出一个元素,且比较两个元素是否一致,一致继续抛,不一致则表示不是回文,直到队列长度小于等于 1 停止(两头同时抛,就是双端队列的威力了,核心逻辑)
  • 如果循环结束,说明肯定是回文
function palindromeChecker(aString: string) {
  if (!aString) {
    return false;
  }
  const deque = new Deque();
  // 统一处理字符串:字母小写,去除空格
  const lowerString = aString.toLocaleLowerCase().split(' ').join('');
  // 字符串一个个放进队列
  for (let i = 0; i < lowerString.length; i++) {
    deque.addBack(lowerString[i]);
  }
  // 队列只要长度>1,就一直比较队首和队尾
  while (deque.size() > 1) {
    // 队首和队尾不相等,就不是回文,且队首和队尾出队
    if (deque.removeFront() !== deque.removeBack()) {
      return false;
    }
  }
  // 队列长度为1,或者队列为空,就是回文
  return true;
}

加上注释的话

/**
 * 回文检查器
 * 回文:正读反读都一样的字符串,比如 'level'、'noon'、'a'、'a b'、'a b c b a'
 * @param {string} aString
 * @returns {boolean}
 * @example
 * palindromeChecker('') // false
 * palindromeChecker('a') // true
 * palindromeChecker('a b') // true
 * palindromeChecker('a b c') // false
 * palindromeChecker('a b c b a') // true
 */

引用

  • 《JavaScript 数据结构与算法》(希望我能看完)