zoukankan      html  css  js  c++  java
  • 牛客网前端挑战编程题解


    title: 牛客网前端挑战编程题解
    toc: true
    date: 2018-09-20 14:33:15
    categories:

    • Web

    tags:

    • JavaScript

    OJ链接:https://www.nowcoder.com/ta/front-end

    注意:在牛客不能用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 中的参数

    1. 指定参数名称,返回该参数的值 或者 空字符串
    2. 不指定参数名称,返回全部的参数对象 或者 {}
    3. 如果存在多个同名参数,则返回数组

    输入

    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 匹配数字

    •  匹配单词的开始或结束

    • ^ 匹配字符串的开始

    • $ 匹配字符串的结束

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

    颜色字符串转换

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

    1. rgb 中每个 , 后面的空格数量不固定
    2. 十六进制表达式使用六位小写字母
    3. 如果输入不符合 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 驼峰格式,请完成此转换功能

    1. 以 - 为分隔符,将第二个起的非空单词首字母转为大写
    2. -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 为出现频率

    1. 不限制 key 的顺序
    2. 输入的字符串参数不会为空
    3. 忽略空白字符

    输入

    '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了解还是太少。。。

  • 相关阅读:
    C# DataGridView导出到Excel
    面试时,怎样“谈薪”?
    7月11号 列表类型的内置方法及应用
    6月1号 字符编码
    文件相关知识
    Django框架之第二篇app注册、静态文件配置、form表单提交、pycharm链接数据库、Django使用mysql数据库、表字段的增删改查、表数据的增删改查
    函数相关知识
    Django框架之第三篇(路由层)有名/无名分组、反向解析、路由分发、名称空间、伪静态、图书管理系统表设计
    初识Django
    Django框架之第五篇(模型层)单表操作(增删改查)、单表查询和必知必会13条、单表查询之双下划线、Django ORM常用字段和字段参数和关系字段
  • 原文地址:https://www.cnblogs.com/zmj97/p/10180763.html
Copyright © 2011-2022 走看看