LeetCode 面试题 03.06. 动物收容所
题目
“最老”可以用编号来比较,编号越小,代表越老,题目已经给了动物编号,如果没有需要自己创建编号或者记录时间戳。
"dequeueAny" 是要 dequeue 猫和狗中最老的。
解题
解题一
var AnimalShelf = function() {
this.queueAnimal = [];
};
AnimalShelf.prototype.enqueue = function(animal) {
this.queueAnimal.push(animal);
};
AnimalShelf.prototype.dequeueAny = function() {
let ret = [-1, -1];
if (this.queueAnimal.length !== 0) {
ret = this.queueAnimal.shift();
}
return ret;
};
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;
};
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]。
解题二
var AnimalShelf = function() {
this.cat = [];
this.dog = [];
};
AnimalShelf.prototype.enqueue = function(animal) {
if (animal[1] === 0) {
this.cat.push(animal);
}
else {
this.dog.push(animal);
}
};
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();
}
};
AnimalShelf.prototype.dequeueDog = function() {
if (this.dog.length === 0) return [-1, -1];
return this.dog.shift();
};
AnimalShelf.prototype.dequeueCat = function() {
if (this.cat.length === 0) return [-1, -1];
return this.cat.shift();
};
记录下面的写法纯粹是为了熟悉 array of arrays 的操作:
var AnimalShelf = function() {
this.queueAnimal = [[], []];
};
AnimalShelf.prototype.enqueue = function(animal) {
let [order, group] = animal;
this.queueAnimal[group].push(order);
};
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();
}
};
AnimalShelf.prototype.dequeueDog = function() {
let ret = [-1, -1];
let [ , queueDog] = this.queueAnimal;
if (queueDog.length !== 0) {
ret = [queueDog.shift(), 1];
}
return ret;
};
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 的方法。
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);
};
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;
}
};
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();
}
};
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;
if (this.dogHead.next === null) {
this.dogTail = this.dogHead;
}
}
return ret;
};
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。
|