【JS】一些特别棒的面试题[4]

【JS】一些特别棒的面试题[4]

原文地址:一些特别棒的面试题[4]

最近面试了一些公司,拿了一些offer,不记录概念题目,仅记录coding类题目。
小伙伴们空闲时间可以做这些题目练练手。

  • 只出现一次的数字
  • 汇总区间
  • 实现红绿灯效果
  • 数组去重
  • 返回 excel 表格列名
  • 检测空对象
  • 实现a+a+a打印'abc'
  • 实现一个Event模块
  • 大整数相加
  • SuperPerson继承Person
  • 字符串隐藏部分内容

只出现一次的数字

给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。
示例 1:

输入: [2,2,1]
输出: 1
示例 2:

输入: [4,1,2,1,2]
输出: 4
这是一道leetcode 简单难度的题。
题目:leetcode 136 只出现一次的数字
题解:136 只出现一次的数字

/**

* @param {number[]} nums

* @return {number}

*/

var singleNumber = function (nums) {

/** 解法1:暴力遍历

* 性能:704ms 40.5MB

*/

let numsSet = Array.from(new Set(nums));

let numsMap = numsSet.map((num) => ({

num,

count: 0,

}));

nums.forEach((num, i) => {

numsMap.forEach((numM, j) => {

if (numM.num === num) {

numM.count++;

}

});

});

let filterArr = numsMap.filter((num) => num.count === 1);

return filterArr[0].num;

/** 解法2:Set 首次出现add 二次出现delete

* 性能: 72 ms 38MB

*/

let numsSet = new Set();

for (let i = 0; i < nums.length; i++) {

if (!numsSet.has(nums[i])) {

numsSet.add(nums[i]);

} else {

numsSet.delete(nums[i]);

}

}

return [...numsSet][0];

};

汇总区间

给定一个乱序整形数组[0,1,7,13,15,16,2,4,5],找出其中连续出现的数字区间为如下:["0->2", "4->5", "7", "13", "15->16"]
这是一道leetcode 中等难度的题。
题目:leetcode 228 汇总区间
题解:228汇总区间(Summary Ranges)

function continuous(arr) {

arr.sort((a, b) => a - b);

let stack = [];

let result = [];

for (let i = 0; i < arr.length; i++) {

if (stack.length === 0 || arr[i] - stack[stack.length - 1] === 1) {

stack.push(arr[i]);

} else {

if (stack.length > 1) {

result.push(`${stack[0]}->${stack[stack.length - 1]}`);

} else {

result.push(`${stack[0]}`);

}

stack = [];

stack.push(arr[i]);

}

if (i === arr.length - 1) {

if (stack.length > 1) {

result.push(`${stack[0]}->${stack[stack.length - 1]}`);

} else {

result.push(`${stack[0]}`);

}

}

}

return result;

}

console.log(continuous([0, 1, 7, 13, 15, 16, 2, 4, 5]));

实现红绿灯效果,使用console 输出 “红”、“绿”、“黄”示意,等待时间分别为 3s、2s、1s

function trafficCtrl() {

// timeline 红0~2 绿3~4 黄5

const borders = { red: 3, green: 5, yellow: 6 };

let current = 0;

setInterval(() => {

if (current >= 0 && current <= 2) {

console.log('红', borders.red - current);

} else if (current >= 3 && current <= 4) {

console.log('绿', borders.green - current);

} else {

console.log('黄', borders.yellow - current);

}

current++;

if (current > 5) {

current = 0;

}

}, 1000);

}

trafficCtrl();

红 3
红 2
红 1
绿 2
绿 1
黄 1
红 3
红 2

数组去重

输入:
['1', '2', '3', 1, '2', undefined, undefined, null, null, 1, 'a','b','b'];
输出:
["1", "2", "3", 1, undefined, null, "a", "b"]

// 解法1:includes

function removeDuplicate(arr) {

const result = [];

for(const item of arr){

if(!result.includes(item)) result.push(item);

}

return result;

}

// 解法2:Map

function removeDuplicate(arr) {

const map = new Map();

for(const item of arr){

if(!map.has(item)) map.set(item, true);

}

const result = [...map.keys()];

return result;

}

// 解法3:对撞指针

function removeDuplicate(arr) {

const map = new Map();

let i = 0;

let j = arr.length - 1;

while(i<=j){

if(!map.has(arr[i])) map.set(arr[i], true);

if(!map.has(arr[j])) map.set(arr[j], true);

i++;

j--;

}

const result = [...map.keys()];

return result;

}

// 解法4:filter

function removeDuplicate(arr) {

return arr.filter((item, i)=> arr.indexOf(item) === i)

}

写一个函数返回 excel 表格列名

输入:1 输出:A
输入:2 输出:B
输入:26 输出:Z
输入:27 输出:AA
输入:52 输出:AZ

这是一道leetcode 简单难度的题。
题目:leetcode 168 Excel表列名称
题解:168 Excel表列名称

function getExcelColumn(column) {

    const obj = {};

    let i = 0;

    const startCode = "A".charCodeAt();

    while (i < 26) {

        obj[i + 1] = String.fromCharCode(startCode + i);

        i++;

    }

    if (column <= 26) {

        return obj[column]

    }

    const stack = [];

    const left = column % 26;

    const floor = Math.floor(column / 26);

    if (left) {

        stack.unshift(obj[left])

        stack.unshift(obj[floor]);

    } else {

        stack.unshift('Z')

        stack.unshift(obj[floor - 1]);

    }

    const result = stack.join("");

    return result;

}

如何检测一个空对象

// 解法1: Object.prototype.toString.call和JSON.stringify

function isObjEmpty(obj){

return Object.prototype.toString.call(obj)==="[Object object]" && JSON.stringify({}) === "{}";

}

// 解法2: Object.keys() Object.values()

function isObjEmpty(obj){

return Object.keys(obj).length === 0 || Object.values(obj).length === 0;

}

// 解法3:for...in

function isObjEmpty(obj){

for(key in obj){

if(key) return false

}

return true;

}

实现a+a+a打印'abc'

console.log(a + a + a); // 打印'abc'

// 题目一

/*

console.log(a + a + a); // 打印'abc'

*/

/**

* 解法1: Object.defineProperty() 外部变量

*/

let value = "a";

Object.defineProperty(this, "a", {

get() {

let result = value;

if (value === "a") {

value = "b";

} else if (value === "b") {

value = "c";

}

return result;

},

});

console.log(a + a + a);

/**

* 解法1(优化版):Object.defineProperty() 内部变量

*/

Object.defineProperty(this, "a", {

get() {

this._v = this._v || "a";

if (this._v === "a") {

this._v = "b";

return "a";

} else if (this._v === "b") {

this._v = "c";

return "b";

} else {

return this._v;

}

},

});

console.log(a + a + a);

/**

* 解法2: Object.prototpye.valueOf()

*/

let index = 0;

let a = {

value: "a",

valueOf() {

return ["a", "b", "c"][index++];

},

};

console.log(a + a + a);

/**

* 解法3:charCodeAt,charFromCode

*/

let code = "a".charCodeAt(0);

let count = 0;

Object.defineProperty(this, "a", {

get() {

let char = String.fromCharCode(code + count);

count++;

return char;

},

});

console.log(a + a + a); // 'abc'

/**

* 解法3(优化版一):内部变量this._count和_code

*/

Object.defineProperty(this, "a", {

get() {

let _code = "a".charCodeAt(0);

this._count = this._count || 0;

let char = String.fromCharCode(_code + this._count);

this._count++;

return char;

},

});

console.log(a + a + a); // 'abc'

/**

* 解法3(优化版二):内部变量this._code

*/

Object.defineProperty(this, "a", {

get() {

this._code = this._code || "a".charCodeAt(0);

let char = String.fromCharCode(this._code);

this._code++;

return char;

},

});

console.log(a + a + a); // 'abc'

/*

题目扩展: 打印`a...z`

a+a+a; //'abc'

a+a+a+a; //'abcd'

*/

/**

* charCodeAt,charFromCode

*/

let code = "a".charCodeAt(0);

let count = 0;

Object.defineProperty(this, "a", {

get() {

let char = String.fromCharCode(code + count);

if (count >= 26) {

return "";

}

count++;

return char;

},

});

// 打印‘abc’

console.log(a + a + a); // 'abc'

// 打印‘abcd’

let code = "a".charCodeAt(0);

let count = 0;

// {...定义a...}

console.log(a + a + a); // 'abcd'

// 打印‘abcdefghijklmnopqrstuvwxyz’

let code = "a".charCodeAt(0);

let count = 0;

// {...定义a...}

let str = "";

for (let i = 0; i < 27; i++) {

str += a;

}

console.log(str); // "abcdefghijklmnopqrstuvwxyz"

/*

题目扩展(优化版): 打印`a...z`

a+a+a; //'abc'

a+a+a+a; //'abcd'

*/

Object.defineProperty(this, "a", {

get() {

this._code = this._code || "a".charCodeAt(0);

let char = String.fromCharCode(this._code);

if (this._code >= "a".charCodeAt(0) + 26) {

return "";

}

this._code++;

return char;

},

});

// 打印‘abc’

console.log(a + a + a); // 'abc'

实现一个Event模块

/**

* 说明:简单实现一个事件订阅机制,具有监听on和触发emit方法

* 示例:

* on(event, func){ ... }

* emit(event, ...args){ ... }

* once(event, func){ ... }

* off(event, func){ ... }

* const event = new EventEmitter();

* event.on('someEvent', (...args) => {

* console.log('some_event triggered', ...args);

* });

* event.emit('someEvent', 'abc', '123');

* event.once('someEvent', (...args) => {

* console.log('some_event triggered', ...args);

* });

* event.off('someEvent', callbackPointer); // callbackPointer为回调指针,不能是匿名函数

*/

class EventEmitter {

constructor() {

this.listeners = [];

}

on(event, func) {

const callback = () => (listener) => listener.name === event;

const idx = this.listeners.findIndex(callback);

if (idx === -1) {

this.listeners.push({

name: event,

callbacks: [func],

});

} else {

this.listeners[idx].callbacks.push(func);

}

}

emit(event, ...args) {

if (this.listeners.length === 0) return;

const callback = () => (listener) => listener.name === event;

const idx = this.listeners.findIndex(callback);

this.listeners[idx].callbacks.forEach((cb) => {

cb(...args);

});

}

once(event, func) {

const callback = () => (listener) => listener.name === event;

let idx = this.listeners.findIndex(callback);

if (idx === -1) {

this.listeners.push({

name: event,

callbacks: [func],

});

}

}

off(event, func) {

if (this.listeners.length === 0) return;

const callback = () => (listener) => listener.name === event;

let idx = this.listeners.findIndex(callback);

if (idx !== -1) {

let callbacks = this.listeners[idx].callbacks;

for (let i = 0; i < callbacks.length; i++) {

if (callbacks[i] === func) {

callbacks.splice(i, 1);

break;

}

}

}

}

}

// let event = new EventEmitter();

// let onceCallback = (...args) => {

// console.log("once_event triggered", ...args);

// };

// let onceCallback1 = (...args) => {

// console.log("once_event 1 triggered", ...args);

// };

// // once仅监听一次

// event.once("onceEvent", onceCallback);

// event.once("onceEvent", onceCallback1);

// event.emit("onceEvent", "abc", "123");

// // off销毁指定回调

// let onCallback = (...args) => {

// console.log("on_event triggered", ...args);

// };

// let onCallback1 = (...args) => {

// console.log("on_event 1 triggered", ...args);

// };

// event.on("onEvent", onCallback);

// event.on("onEvent", onCallback1);

// event.emit("onEvent", "abc", "123");

// event.off("onEvent", onCallback);

// event.emit("onEvent", "abc", "123");

大整数相加

/**

* 请通过代码实现大整数(可能比Number.MAX_VALUE大)相加运算

* var bigint1 = new BigInt('1231230');

* var bigint2 = new BigInt('12323123999999999999999999999999999999999999999999999991');

* console.log(bigint1.plus(bigint2))

*/

function BigInt(value) {

this.value = value;

}

BigInt.prototype.plus = function (bigint) {

let aArr = this.value.split("");

let bArr = bigint.value.split("");

let stack = [];

let count = 0;

while (aArr.length !== 0 || bArr.length !== 0) {

let aPop = aArr.pop() || 0;

let bPop = bArr.pop() || 0;

let stackBottom = 0;

if (stack.length > count) {

stackBottom = stack.shift();

}

let sum = parseInt(aPop) + parseInt(bPop) + parseInt(stackBottom);

if (sum < 10) {

stack.unshift(sum);

} else if (sum >= 10) {

stack.unshift(sum - 10);

stack.unshift(1);

}

count++;

}

return stack.join("");

};

SuperPerson继承Person

//写一个类Person,拥有属性age和name,拥有方法say(something)

//再写一个类Superman,继承Person,拥有自己的属性power,拥有自己的方法fly(height) ES5方式

function Person(age, name){

this.age = age;

this.name = name;

}

Person.prototype.say = function(something) {

// ...

}

function Superman(age, name, power){

Person.call(this, age, name, power);

this.power = power;

}

Superman.prototype = Object.create(Person.prototype);

Superman.prototype.constructor = Superman;

Superman.prototype.fly = function(height) {

// ...

}

let superman = new Superman(25, 'GaoKai', 'span');

// class方式

class Person {

constructor(age, name){

this.age = age;

this.name = name;

}

say(something){

// ...

console.log("say");

}

}

class Superman extends Person{

constructor(age, name, power){

super(age, name)

this.power = power;

}

fly(height){

// ...

console.log("fly");

}

}

let superman = new Superman(25, 'GaoKai', 'span');

字符串隐藏部分内容

/**

* 字符串隐藏部分内容

* 说明:实现一个方法,接收一个字符串和一个符号,将字符串中间四位按指定符号隐藏

* 1. 符号无指定时使用星号(*)

* 2. 接收的字符串小于或等于四位时,返回同样长度的符号串,等同于全隐藏,如 123,隐藏后是 ***

* 3. 字符串长度是大于四位的奇数时,如 123456789,隐藏后是 12****789,奇数多出来的一位在末尾

* 示例:

* mask('blibaba', '#'); // b####ba

* mask('05716666'); // 05****66

* mask('hello'); // ****o

* mask('abc', '?'); // ???

* mask('哔里巴巴集团', '?'); // 哔????团

*/

function mask(str, char = "*") {

if(str.length<=4) return char.repeat(str.length);

/* 代码实现 */

let result = "";

let i = Math.floor(str.length / 2) - 1;

let j = Math.floor(str.length / 2);

while(result.length!==str.length){

if(j - i <= 4){

result = char + result;

result += char ;

} else {

result = (str[i] || "") + result;

result += str[j] ;

}

i--;

j++;

}

return result;

}

【JS】一些特别棒的面试题[4]

以上是 【JS】一些特别棒的面试题[4] 的全部内容, 来源链接: utcz.com/a/89012.html

回到顶部