学习js数据结构与算法-双端队列

116 阅读2分钟

「这是我参与2022首次更文挑战的第10天,活动详情查看:2022首次更文挑战」。

个人觉得要想进大厂,就必须学习了解算法和数据结构,经历了多次面试之后,也知道了算法和数据结构的重要性,所以,我也打算从今天开始,进入学习,下载了一下电子书,边看书,边跟着书的例子来敲一下代码,下面就开始总结一下对算法和数据结构的学习吧。

第十天:开始了解双端队列

双端队列

允许我们同时从前端和后端添加和移除元素的特殊队列

双端队列在现实生活中的例子也有,比如买路边摊烧烤,在排队。举个例子,我已经买好了烧烤,但我只是想要简单的加个酱,就可以直接回到最前面,让老板加个酱。排在末尾的人,如果突然有事,不想等那么久了,就可以直接离开队伍。

需要有的方法

  • addFront(element):该方法在双端队列前端添加新的元素。
  • addBack(element):该方法在双端队列后端添加新的元素(实现方法和 Queue 类中的 enqueue 方法相同)。\
  • removeFront():该方法会从双端队列前端移除第一个元素(实现方法和 Queue 类中的 dequeue 方法相同)。\
  • removeBack():该方法会从双端队列后端移除第一个元素(实现方法和 Stack 类中的 pop 方法一样)。\
  • peekFront():该方法返回双端队列前端的第一个元素(实现方法和 Queue 类中的 peek 方法一样)。\
  • peekBack():该方法返回双端队列后端的第一个元素(实现方法和 Stack 类中的 peek 方法一样)。
创建双端队列
class Deque {
    constructor() {
        this.items = {}
        this.count = 0
        this.lowerCount = 0
    }
    size() {
        return this.count - this.lowerCount
    }
    isEmpty() {
        return this.size() === 0
    }

    addBack(element) {
        this.items[this.count] = element
        this.count++
    }
    addFront(element) {
        if (this.isEmpty()) {
            this.addBack(element)
        } else if (this.lowerCount > 0) {
            this.lowerCount--
            this.items[this.lowerCount] = element
        } else {
            for (let i = this.count; i > 0; i--) {
                this.items[i] = this.items[i - 1]
            }
            this.count++
            this.items[0] = element
        }
    }
    removeBack() {
        this.count--
        const result = this.items[this.count]
        delete this.items[this.count]
        return result
    }
    removeFront() {
        const result = this.items[this.lowerCount]
        delete this.items[this.lowerCount]
        this.lowerCount++
        return result
    }
    peekFront() {
        if (this.isEmpty()) return undefined
        return this.items[this.lowerCount]
    }
    peekBack() {
        if (this.isEmpty()) return undefined
        return this.items[this.count - 1]
    }
    toString() {
        if (this.isEmpty()) return ''
        let text = `${this.items[this.lowerCount]}`
        for (let i = this.lowerCount + 1; i < this.count; i++) {
            text += `,${this.items[i]}`
        }
        return text
    }
}
使用队列
const deque = new Deque();
console.log(deque.isEmpty()); // 输出true
deque.addBack('John'); 
deque.addBack('Jack');
console.log(deque.toString()); // John, Jack
deque.addBack('Camila');
console.log(deque.toString()); // John, Jack, Camila
console.log(deque.size()); // 输出3
console.log(deque.isEmpty()); // 输出false
deque.removeFront(); // 移除John
console.log(deque.toString()); // Jack, Camila
deque.removeBack(); // Camila 决定离开
console.log(deque.toString()); // Jack
deque.addFront('John'); // John 回来询问一些信息
console.log(deque.toString()); // John, Jack
用双端队列解决问题
  • 回文是正反都能读通的单词、词组、数或一系列字符的序列,例如 madam 或 racecar。
function palindromeChecker(aString) {
    if (aString === undefined || aString === null ||
        (aString !== null && aString.length === 0)) {
        return false;
    }
    const deque = new Deque()
    let text = aString.toLocaleLowerCase().split(' ').join('')
    let palindrome = true
    for (let i = 0; i < text.length; i++) {
        deque.addBack(text[i])
    }
    while (deque.size() > 1 && palindrome) {
        const front = deque.removeFront()
        const back = deque.removeBack()
        if (front !== back) palindrome = false
    }
    return palindrome
}
console.log('a', palindromeChecker('a')); // true
console.log('aa', palindromeChecker('aa')); // true
console.log('kayak', palindromeChecker('kayak')); // true
console.log('level', palindromeChecker('level')); // true
console.log('Was it a car or a cat I saw', palindromeChecker('Was it a car or a cat I saw')); // true
console.log('Step on no pets', palindromeChecker('Step on no pets')); // true
console.log('reqw', palindromeChecker('reqw')); // true