判断作弊 牛客 编程_牛客网前端挑战编程题解

title: 牛客网前端挑战编程题解

toc: true

date: 2018-09-20 14:33:15

categories:

Web

tags:

JavaScript

注意:在牛客不能用ES6的东西!

修改this指向

封装函数 f,使 f 的 this 指向指定的对象

代码

function bindThis(f, oTarget) {

// 考虑浏览器兼容

if (f.bind) {

return f.bind(oTarget);

} else {

// apply()为立即执行函数,因此需要放在一个函数里,到需要使用的时候再立即执行

return function() {

// arguments不能省略,在执行f时可能会传入参数

return f.apply(oTarget, arguments);

}

}

}

获取url参数

获取 url 中的参数

指定参数名称,返回该参数的值 或者 空字符串

不指定参数名称,返回全部的参数对象 或者 {}

如果存在多个同名参数,则返回数组

输入

http://www.nowcoder.com?key=1&key=2&key=3&test=4#hehe

输出

[1, 2, 3]

代码

function getUrlParam(sUrl, sKey) {

var result = {};

// 先取?和#之间的字符串,然后按照&分割

var querys = ((sUrl.split('?')[1]).split('#')[0]).split('&');

for (var i = 0; i < querys.length; i++) {

var key = querys[i].split('=')[0];

var value = querys[i].split('=')[1];

// 如果result[key]未定义,则创建一个含有value的数组

if (result[key] == undefined) result[key] = [value];

else result[key].push(value);

}

// 不指定参数名称,返回全部的参数对象

if (sKey == undefined) return result;

if (result[sKey] == undefined) return "";

else if (result[sKey].length == 1) return result[sKey][0];

else return result[sKey];

}

还有大神的正则的方法...直接贴出来吧:

// 链接:https://www.nowcoder.com/questionTerminal/a3ded747e3884a3c86d09d88d1652e10

// 来源:牛客网

function getUrlParam(sUrl, sKey) {

var obj = {};

var reg = /[?&](\w+)=(\w+)/g;

while(reg.exec(sUrl))

obj[RegExp.$1] ? obj[RegExp.$1]=[].concat(obj[RegExp.$1],RegExp.$2) : obj[RegExp.$1]=RegExp.$2;

return sKey ? obj[sKey]||"" : obj;

}

dom节点查找

查找两个节点的最近的一个共同父节点,可以包括节点自身

输入描述

oNode1 和 oNode2 在同一文档中,且不会为相同的节点

代码

function commonParentNode(oNode1, oNode2) {

for (;oNode1;oNode1 = oNode1.parentNode) {

if (oNode1.contains(oNode2)) {

return oNode1;

}

}

}

还是对DOM的相关属性啊什么的不了解。。红宝书刚看到DOM。。。要加油鸭

根据包名,在指定空间中创建对象

输入描述

namespace({a: {test: 1, b: 2}}, 'a.b.c.d')

输出描述

{a: {test: 1, b: {c: {d: {}}}}}

代码

function namespace(oNamespace, sPackage) {

var tmpPoint = oNamespace;

var keys = sPackage.split('.');

for (var i = 0; i < keys.length; i++) {

if (tmpPoint[keys[i]] == undefined) tmpPoint[keys[i]] = {};

tmpPoint = tmpPoint[keys[i]];

}

return oNamespace;

}

记住,对象名就像是指针一样。

数组去重

为 Array 对象添加一个去除重复项的方法

输入

[false, true, undefined, null, NaN, 0, 1, {}, {}, 'a', 'a', NaN]

输出

[false, true, undefined, null, NaN, 0, 1, {}, {}, 'a']

代码

Array.prototype.uniq = function () {

var hasNaN = false;

for (var i = 0; i < this.length; i++) {

if ((hasNaN === false) && (this[i] != this[i])) {

hasNaN = true;

continue;

}

if (this.indexOf(this[i]) < i) this.splice(i--,1);

}

return this;

}

关于NaN的问题调试了好几次。。

使用this.indexOf(this[i]) < i判断的时候,

因为NaN和任何值都不相等,因此index是-1,因此在这里一定会被删掉,

因此需要先判断是不是已经遇到过NaN了,遇到过的话再次遇到就直接删掉,没有遇到的话遇到时就把hasNaN设为true,然后continue来跳过splice。

斐波那契数列

用 JavaScript 实现斐波那契数列函数,返回第n个斐波那契数。 f(1) = 1, f(2) = 1 等

emmmmm,不知道为什么会有斐波那契这种题。。。。

// 暴力递归

function fibonacci(n) {

if (n <= 0) return 0;

if (n == 1) return 1;

return fibonacci(n-1) + fibonacci(n-2);

}

// 本来想用callee,结果严格模式不让用。。。红宝书一直说callee多么多么好。。。搞得我不用好难受

// 循环

function fibonacci(n) {

if (n <= 0) return 0;

if (n == 1) return 1;

var a = 0, b = 1, c = 1;

for (var i = 2; i <= n; i++) {

c = a + b;

a = b;

b = c;

}

return c;

}

时间格式化输出

按所给的时间格式输出指定的时间

格式说明

对于 2014.09.05 13:14:20

yyyy: 年份,2014

yy: 年份,14

MM: 月份,补满两位,09

M: 月份, 9

dd: 日期,补满两位,05

d: 日期, 5

HH: 24制小时,补满两位,13

H: 24制小时,13

hh: 12制小时,补满两位,01

h: 12制小时,1

mm: 分钟,补满两位,14

m: 分钟,14

ss: 秒,补满两位,20

s: 秒,20

w: 星期,为 ['日', '一', '二', '三', '四', '五', '六'] 中的某一个,本 demo 结果为 五

输入

formatDate(new Date(1409894060000), 'yyyy-MM-dd HH:mm:ss 星期w')

输出

2014-09-05 13:14:20 星期五

代码

function formatDate(date, format) {

var myDate = {

yyyy: date.getFullYear(),

yy: date.getFullYear()%100,

MM: ("0" + (date.getMonth()+1)).slice(-2),

M: date.getMonth()+1,

dd: ("0" + (date.getDate())).slice(-2),

d: date.getDate(),

HH: ("0" + date.getHours()).slice(-2),

H: date.getHours(),

hh: ("0" + (date.getHours() % 12)).slice(-2),

h: date.getHours() % 12,

mm: ("0" + date.getMinutes()).slice(-2),

m: date.getMinutes(),

ss: ("0" + date.getSeconds()).slice(-2),

s: date.getSeconds(),

w: ['日', '一', '二', '三', '四', '五', '六'][date.getDay()]

}

return format.replace(/([a-z]+)/ig,function($1){return myDate[$1];});

}

参考了大神的代码。。。自己差点就十几个if了。。。

关于代码说明几点:

getFullYear()为年份四位表示

getMonth()为月份0-11

getDate()为日期1-31

getHours()为小时0-23

getMinutes()为分钟0-59

getSeconds()为秒数0-59

getDay()为0-6表示['日', '一', '二', '三', '四', '五', '六']

RegExp.$1...RegExp.$9表示用于存储第一、……第九个匹配的捕获组,至于什么是捕获组可以看下边这个例子:

var text = "this has been a short summer";

var pattern = /(..)or(.)/g;

if (pattern.exec(text)) {

alert(RegExp.$1); // "sh"

alert(RegExp.$2); // "t"

}

获取字符串长度

如果第二个参数 bUnicode255For1 === true,则所有字符长度为 1

否则如果字符 Unicode 编码 > 255 则长度为 2

输入

'hello world, 牛客', false

输出

17

代码

function strLength(s, bUnicode255For1) {

if (bUnicode255For1 === true) {

return s.length;

} else {

var result = 0;

for (var i = 0; i < s.length; i++) {

if (s.charCodeAt(i) > 255) result+=2;

else result+=1;

}

return result;

}

}

刚开始一直没看懂题。。。这道题应该有点问题,js默认utf-16编码,所以不是所有字符都长度为1,有的字符是长度为2的。。。忽略这个写这个题吧。。。

邮箱字符串判断

输入描述

邮箱字符串

输出描述

true表示格式正确

代码

function isAvailableEmail(sEmail) {

var reg = /^[\w\.]+@[\w\.]+\.[\w\.]+$/i;

return reg.test(sEmail);

}

\w 匹配字母或数字或下划线或汉字 等价于 '[^A-Za-z0-9_]'。

\s 匹配任意的空白符

\d 匹配数字

\b 匹配单词的开始或结束

^ 匹配字符串的开始

$ 匹配字符串的结束

\w能不能匹配汉字要视你的操作系统和你的应用环境而定

颜色字符串转换

将 rgb 颜色字符串转换为十六进制的形式,如 rgb(255, 255, 255) 转为 #ffffff

rgb 中每个 , 后面的空格数量不固定

十六进制表达式使用六位小写字母

如果输入不符合 rgb 格式,返回原始输入

输入

'rgb(255, 255, 255)'

输出

#ffffff

代码

function rgb2hex(sRGB) {

if(sRGB.slice(0,4)!=='rgb(' || sRGB.slice(-1)!==')') return sRGB;

var tmp = (sRGB.split('(')[1]).split(')')[0];

var colors = tmp.split(',');

if (colors.length != 3) return sRGB;

var re = "#";

for (var i = 0; i < colors.length; i++) {

var value = parseInt(colors[i].substring(colors[i].lastIndexOf(' ')));

if (value < 0 || value > 255) return sRGB;

re += ("0" + (value).toString(16)).slice(-2);

}

return re;

}

又使用了最水的办法。。。

看一下大佬的正则的方法:

//链接:https://www.nowcoder.com/questionTerminal/80b08802a833419f9c4ccc6e042c1cca

//来源:牛客网

function rgb2hex(sRGB) {

return sRGB.replace(/^rgb\((\d+)\s*\,\s*(\d+)\s*\,\s*(\d+)\)$/g, function(a, r, g, b){

return '#' + hex(r) + hex(g) + hex(b);

});

}

function hex(n){

return n < 16 ? '0' + (+n).toString(16) : (+n).toString(16);

}

a代表正则匹配的整个字符串, r ,g, b代表红绿蓝三个通道, 分别是正则中的三个括号匹配的字符串. 通常用的$0, $1, $2, $3。

但是吧,可能是用例不全,这个方法并没有判断是不是超出0-255也能AC。。

可以在hex函数里加个判断,如果规范才返回字符串,然后在replace里的那个函数里加个判断hex(r)、hex(g)、hex(b)是否为undefined,像这样:

function rgb2hex(sRGB) {

return sRGB.replace(/^rgb\((\d+)\s*\,\s*(\d+)\s*\,\s*(\d+)\)$/g, function(a, r, g, b){

if (hex(r) == undefined || hex(g) == undefined || hex(b) == undefined) return sRGB;

return '#' + hex(r) + hex(g) + hex(b);

});

}

function hex(n){

if (n > -1 && n < 256) {

return n < 16 ? '0' + (+n).toString(16) : (+n).toString(16);

}

}

这样就可以啦!

将字符串转换为驼峰模式

css 中经常有类似 background-image 这种通过 - 连接的字符,通过 javascript 设置样式的时候需要将这种样式转换成 backgroundImage 驼峰格式,请完成此转换功能

以 - 为分隔符,将第二个起的非空单词首字母转为大写

-webkit-border-image 转换后的结果为 webkitBorderImage

输入

'font-size'

输出

fontSize

代码

function cssStyle2DomStyle(sName) {

if (sName[0] == "-") sName = sName.slice(1);

var words = sName.split('-');

var re = words[0];

for (var i = 1; i < words.length; i++) {

re = re + words[i][0].toUpperCase() + words[i].slice(1);

}

return re;

}

大神的代码:

// 链接:https://www.nowcoder.com/questionTerminal/2ded24e34ec34325a62d42d0c8479bae

// 来源:牛客网

return sName.replace(/\-[a-z]/g , function(a, b){

return b == 0 ? a.replace('-','') : a.replace('-','').toUpperCase();

});

其中b是offset。

replace第二个参数函数的参数表:

变量名

代表的值

match

匹配的子串。(对应于上述的$&。)

p1,p2, ...

假如replace()方法的第一个参数是一个RegExp 对象,则代表第n个括号匹配的字符串。(对应于上述的$1,$2等。)

offset

匹配到的子字符串在原字符串中的偏移量。(比如,如果原字符串是“abcd”,匹配到的子字符串是“bc”,那么这个参数将是1)

string

被匹配的原字符串。

字符串字符统计

统计字符串中每个字符的出现频率,返回一个 Object,key 为统计字符,value 为出现频率

不限制 key 的顺序

输入的字符串参数不会为空

忽略空白字符

输入

'hello world'

输出

{h: 1, e: 1, l: 3, o: 2, w: 1, r: 1, d: 1}

大神的代码:

function count(str) {

var obj = {};

str.replace(/\S/g,function(s){

!obj[s]?obj[s]=1:obj[s]++;

})

return obj;

}

\S匹配非空字符串,function(s)里的s代表匹配到的每一项。

哎总结一句就是我好菜。。对JS了解还是太少。。。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值