LeetCode《程序员面试金典》面试题 03.06. 动物收容所

LeetCode 面试题 03.06. 动物收容所

  • 题目
  • 解题
    • 解题一
    • 解题二
    • 解题三

题目

LeetCode《程序员面试金典》面试题 03.06. 动物收容所_第1张图片
“最老”可以用编号来比较,编号越小,代表越老,题目已经给了动物编号,如果没有需要自己创建编号或者记录时间戳。

"dequeueAny" 是要 dequeue 猫和狗中最老的。

解题

解题一

在这里插入图片描述

// javascript
var AnimalShelf = function() {
    this.queueAnimal = [];
};

/** 
 * @param {number[]} animal
 * @return {void}
 */
AnimalShelf.prototype.enqueue = function(animal) {
    this.queueAnimal.push(animal);
};

/**
 * @return {number[]}
 */
AnimalShelf.prototype.dequeueAny = function() {
    let ret = [-1, -1];
    if (this.queueAnimal.length !== 0) {
        ret = this.queueAnimal.shift();
    }
    return ret;
};

/**
 * @return {number[]}
 */
AnimalShelf.prototype.dequeueDog = function() {
    let ret = [-1, -1];
    for (let index = 0; index < this.queueAnimal.length; index++) {
        if (this.queueAnimal[index][1] === 1) {
            ret = this.queueAnimal.splice(index, 1)[0];
            break;
        }
    }
    return ret;
};

/**
 * @return {number[]}
 */
AnimalShelf.prototype.dequeueCat = function() {
    let ret = [-1, -1];
    for (let index = 0; index < this.queueAnimal.length; index++) {
        if (this.queueAnimal[index][1] === 0) {
            ret = this.queueAnimal.splice(index, 1)[0];
            break;
        }
    }
    return ret;
};

需要注意的是,JS 中 Array 的 splice 函数返回的是一个包含所有被删除元素的数组,本身这里存储的每个元素都是 [编号,猫或狗],所以获取被删除元素时要加索引 [0]。

解题二

在这里插入图片描述

// javascript
var AnimalShelf = function() {
    this.cat = [];
    this.dog = [];
};

/** 
 * @param {number[]} animal
 * @return {void}
 */
AnimalShelf.prototype.enqueue = function(animal) {
    if (animal[1] === 0) {
        this.cat.push(animal);
    }
    else {
        this.dog.push(animal);
    }
};

/**
 * @return {number[]}
 */
AnimalShelf.prototype.dequeueAny = function() {
    if (this.cat.length === 0) return this.dequeueDog();
    if (this.dog.length === 0) return this.dequeueCat();
    let catIdx = this.cat[0][0], dogIdx = this.dog[0][0];
    if (catIdx < dogIdx) {
        return this.dequeueCat();
    }
    else {
        return this.dequeueDog();
    }
};

/**
 * @return {number[]}
 */
AnimalShelf.prototype.dequeueDog = function() {
    if (this.dog.length === 0) return [-1, -1];
    return this.dog.shift();
};

/**
 * @return {number[]}
 */
AnimalShelf.prototype.dequeueCat = function() {
    if (this.cat.length === 0) return [-1, -1];
    return this.cat.shift();
};

记录下面的写法纯粹是为了熟悉 array of arrays 的操作:

// javascript
var AnimalShelf = function() {
    this.queueAnimal = [[], []];
};

/** 
 * @param {number[]} animal
 * @return {void}
 */
AnimalShelf.prototype.enqueue = function(animal) {
    let [order, group] = animal;
    this.queueAnimal[group].push(order);
};

/**
 * @return {number[]}
 */
AnimalShelf.prototype.dequeueAny = function() {
    let [queueCat, queueDog] = this.queueAnimal;
    if (queueDog.length === 0) return this.dequeueCat(); // 没有待领养的狗
    if (queueCat.length === 0) return this.dequeueDog(); // 没有待领养的猫
    const oldestDogIdx = queueDog[0], oldestCatIdx = queueCat[0];
    // 比较最老的狗和最老的猫谁更老
    if (oldestDogIdx < oldestCatIdx) {
        return this.dequeueDog();
    }
    else {
        return this.dequeueCat();
    }
};

/**
 * @return {number[]}
 */
AnimalShelf.prototype.dequeueDog = function() {
    let ret = [-1, -1];
    let [ , queueDog] = this.queueAnimal;
    if (queueDog.length !== 0) {
        ret = [queueDog.shift(), 1];
    }
    return ret;
};

/**
 * @return {number[]}
 */
AnimalShelf.prototype.dequeueCat = function() {
    let ret = [-1, -1];
    let [queueCat, ] = this.queueAnimal;
    if (queueCat.length !== 0) {
        ret = [queueCat.shift(), 0];
    }
    return ret;
};

上述解法有一个要学习的地方是 多赋有意义的变量名,因为 queueAnimal 数组里包含数组,属于 Array of arrays,如果想把编号和类型数组直接存进猫或狗的数组中,会变成 三层数组:queueAnimal 数组由 猫数组 和 狗数组 组成,猫 / 狗数组里的元素也是数组,语义不明显的话写起来容易错,别人读的时候光看见 [0][0][0],也不明白其中含义。

解题三

用数组做 shift 时会把剩余元素都前移一位,效率不高,自己写了一个 LinkedList 的方法。

// javascript
var ListNode = function (val) {
    this.val = val;
    this.next = null;
};

var AnimalShelf = function() {
    this.dogHead = this.dogTail = new ListNode(0);
    this.catHead = this.catTail = new ListNode(0);
};

/** 
 * @param {number[]} animal
 * @return {void}
 */
AnimalShelf.prototype.enqueue = function(animal) {
    let newNode = new ListNode(animal);
    if (animal[1] === 0) {
        this.catTail.next = newNode;
        this.catTail = this.catTail.next;
    }
    else {
        this.dogTail.next = newNode;
        this.dogTail = this.dogTail.next;
    }
};

/**
 * @return {number[]}
 */
AnimalShelf.prototype.dequeueAny = function() {
    if (this.dogHead.next === null) return this.dequeueCat();
    if (this.catHead.next === null) return this.dequeueDog();
    if (this.dogHead.next.val[0] < this.catHead.next.val[0]) {
        return this.dequeueDog();
    }
    else {
        return this.dequeueCat();
    }
};

/**
 * @return {number[]}
 */
AnimalShelf.prototype.dequeueDog = function() {
    let ret = [-1, -1];
    if (this.dogHead.next !== null) {
        ret = this.dogHead.next.val;
        this.dogHead.next = this.dogHead.next.next;
        // 如果 队列 空了(只剩下伪头节点),把 tail 指针重新指回 head
        if (this.dogHead.next === null) {
            this.dogTail = this.dogHead;
        }
    }
    return ret;
};

/**
 * @return {number[]}
 */
AnimalShelf.prototype.dequeueCat = function() {
    let ret = [-1, -1];
    if (this.catHead.next !== null) {
        ret = this.catHead.next.val;
        this.catHead.next = this.catHead.next.next;
        if (this.catHead.next === null) {
            this.catTail = this.catHead;
        }
    }
    return ret;
};

写的时候犯了些错误,一是注意 dequeue 中如果队列空了(只剩下伪头节点),要把 tail 指针重新指回 head,否则 tail 还指着被删除的节点,而 head.next 已经为 null,enqueue 时会往 tail 后面加新节点,head 再也找不到这些节点。

还有大概是脑子糊掉了,竟然写出 this.cat.head 这种鬼 T.T。

你可能感兴趣的:(程序员面试金典,leetcode,算法,数据结构,链表,stack)