Skip to content

Latest commit

 

History

History
557 lines (355 loc) · 16 KB

做题笔记.md

File metadata and controls

557 lines (355 loc) · 16 KB

刷题的时候遇到的一些问题:

1. js 中二维数组的初始化-奇安信笔试-最短路径问题

  • 方法一、直接定义并且初始化,这种情况适用于数量和值已知的数组:
var arr=[["0-1","0-2"],["1-1","1-2"],["2-1","2-2"]];
  • 方法二、动态创建并初始化:
var arr=new Array();             //声明一维数组        
for(var x=0;x<i;x++){
      arr[x]=new Array();        //声明二维数组
      for(var y=0;y<i;y++){
           arr[x][y]=0;          //数组初始化为0
      }
}

PS: 做最短路径问题的时候,光是初始化邻接矩阵就花了好长时间。

2.知识点: ’==‘ VS ‘===’

console.log([] == ![]) // true
console.log({} == !{}) // false

3.递归调用没有 return 导致返回 undefined - LeetCode 字符串解码

https://blog.csdn.net/Libertied/article/details/108071583

问题是在做 LeetCode-394-字符串解码 的时候遇到的

先抛开函数递归本身,如果一个函数体内没有返回值,那么执行一个函数的时候,默认返回值是undefined

递归函数实质上就是不断的调用同一个函数,然后在条件判断下退出执行,然后再做相应的操作

而return a(), 就是在a函数中返回了a函数调用后的结果,不断的返回,直到time >= 100

没有return语句,返回值都没有,怎么递归函数...

4. parseInt 无法返回字符串中间的数字

parseInt 无法返回字符串中间的数字,如 parseInt('ab123ab') 返回的是 NaN

5.判断某个字符是否数字 ,可以用 isNaN

if (!isNaN(char)) { }

6.逐字符扫描字符串

  for (const char of sting) {  

    // 逐字符扫描 
  }

7. Set 使用

因为 Set 结构的值是唯一的,我们可以很轻松的实现以下

// 数组去重
let arr = [1, 1, 2, 3];
let unique = [... new Set(arr)];

let a = new Set([1, 2, 3]);
let b = new Set([4, 3, 2]);
  
// 并集
let union = [...new Set([...a, ...b])]; // [1,2,3,4]
  
// 交集
let intersect = [...new Set([...a].filter(x => b.has(x)))];  // [2,3]
  
// 差集
let difference = Array.from(new Set([...a].filter(x => !b.has(x)))); // [1]

8. Number.prototype.toString() \ parseInt 进制转换

numObj.toString([radix])  
// 指定要用于数字到字符串的转换的基数(从2到36)。如果未指定 radix 参数,则默认值为 10。
var count = 10;

console.log(count.toString());    // 输出 '10'
console.log((17).toString());     // 输出 '17'
console.log((17.2).toString());   // 输出 '17.2'

var x = 6;

console.log(x.toString(2));       // 输出 '110'
console.log((254).toString(16));  // 输出 'fe'

console.log((-10).toString(2));   // 输出 '-1010'
console.log((-0xff).toString(2)); // 输出 '-11111111'

parseInt(string, radix) 解析一个字符串并返回指定基数的十进制整数, radix 是2-36之间的整数,表示被解析字符串的基数。

以下例子均返回15:

parseInt("0xF", 16);
parseInt("F", 16);
parseInt("17", 8);
parseInt(021, 8);
parseInt("015", 10);   // parseInt(015, 8); 返回 13
parseInt(15.99, 10);
parseInt("15,123", 10);
parseInt("FXX123", 16);
parseInt("1111", 2);
parseInt("15 * 3", 10);
parseInt("15e2", 10);
parseInt("15px", 10);
parseInt("12", 13);

9.使用 Number 转换数字字符串为数字

Number('123')     // 123
Number('12.3')    // 12.3
Number('12.00')   // 12
Number('123e-1')  // 12.3
Number('')        // 0
Number(null)      // 0
Number('0x11')    // 17
Number('0b11')    // 3
Number('0o11')    // 9
Number('foo')     // NaN 
Number('100a')    // NaN 需要注意,只能是单纯数字的字符串
Number('-Infinity') //-Infinity

10. map 方法会给原数组中的每个元素都按顺序调用一次 callback 函数。

callback 函数会被自动传入三个参数:数组元素,元素索引,原数组本身。

parseInt(string, radix)

所以以下调用就成了:parseInt(数组元素,元素索引)

[1,2,3,4].map(parseInt)  // [ 1, NaN, NaN, NaN ]
// 即为:
parseInt(1,0) // 传入 0 的时候注意
parseInt(2,1) 
parseInt(3,2)  // 二进制怎么可能会出现3呢!所以NaN
parseInt(4,3)

如果 radixundefined0或未指定的,JavaScript会假定以下情况:

  1. 如果输入的 string以 "0x"或 "0x"(一个0,后面是小写或大写的X)开头,那么radix被假定为16,字符串的其余部分被当做十六进制数去解析。
  2. 如果输入的 string以 "0"(0)开头, radix被假定为8(八进制)或10(十进制)。具体选择哪一个radix取决于实现。ECMAScript 5 澄清了应该使用 10 (十进制),但不是所有的浏览器都支持。因此,在使用 parseInt 时,一定要指定一个 radix
  3. 如果输入的 string 以任何其他值开头, radix10 (十进制)。

11. 二分查找注意事项 mid 取值

js二分查找的时候需要取整,毕竟没有整型数据类型。 let mid = left + parseInt((right - left) / 2) 或者用Math.floor

做:LeetCode 410

12. 整数转换为 32 位二进制表示( JZ11-二进制中1的个数.js )

JavaScript 将数字存储为 64 位浮点数,但所有按位运算都以 32 位二进制数执行。

在执行位运算之前,JavaScript 将数字转换为 32 位有符号整数。

1. 把十进制转换为二进制

function dec2bin(dec){
    return (dec >>> 0).toString(2);
}

2. 把二进制转换为十进制

function bin2dec(bin){
    return parseInt(bin, 2).toString(10);
}

13.写出一个正则来处理数字千分位

let b = a.toFixed(2).replace(/(\d)(?=(\d{3})+\.)/g, '$1,');

14.做树相关题目的注意事项

要养成一个习惯,对任何一个树节点进行访问时,一定要提前检测该节点是否为空

15. Array.prototype.fill()

fill() 方法用一个固定值填充一个数组中从起始索引到终止索引内的全部元素。不包括终止索引。

[1, 2, 3].fill(4);               // [4, 4, 4]
[1, 2, 3].fill(4, 1);            // [1, 4, 4]
[1, 2, 3].fill(4, 1, 2);         // [1, 4, 3]
[1, 2, 3].fill(4, 1, 1);         // [1, 2, 3]
[1, 2, 3].fill(4, 3, 3);         // [1, 2, 3]
[1, 2, 3].fill(4, -3, -2);       // [4, 2, 3]
[1, 2, 3].fill(4, NaN, NaN);     // [1, 2, 3]
[1, 2, 3].fill(4, 3, 5);         // [1, 2, 3]
Array(3).fill(4);                // [4, 4, 4]
[].fill.call({ length: 3 }, 4);  // {0: 4, 1: 4, 2: 4, length: 3}

// Objects by reference.
var arr = Array(3).fill({}) // [{}, {}, {}];
// 需要注意如果fill的参数为引用类型,会导致都执行都一个引用类型
// 如 arr[0] === arr[1] 为true
arr[0].hi = "hi"; // [{ hi: "hi" }, { hi: "hi" }, { hi: "hi" }]

16. NaN !== NaN , {} === {}

indexOf 底层还是使用 === 进行判断,因为 NaN === NaN的结果为 false,所以使用 indexOf 查找不到 NaN 元素

let a = {};
a === a; // true
let b = {};
b === a; // false

let b = NaN;
b === b; // false

// JavaScript专题之数组去重
// https://github.com/mqyqingfeng/Blog/issues/27

17.数组去重

数组中含有对象的时候,去重的方法就基本不能用了。

小小去重也是真不容易啊

参见文章:

mqyqingfeng/Blog#27

// 最为全面的方法
function unique(array) {
    var obj = {};
    return array.filter(function(item, index, array) {
        // console.log(typeof item + JSON.stringify(item))
        return obj.hasOwnProperty(typeof item + JSON.stringify(item)) ? false : (obj[typeof item + JSON.stringify(item)] = true)
    })
}

let arr = [true, false, null, undefined, NaN, 0, 1, {}, {}, 'a', 'a', NaN];
console.log(unique(arr));

// JSON.stringify({})   {}
// JSON.stringify(/a/) 正则表达式的话也是 {}
var array = [{}, {}, /a/, /a/];
// 结果 [ {} ]

// 为了解决这个特别的情况,自己改写了一下。。。。
function unique(array) {
    var obj = {};
    return array.filter(function(item, index, array) {
        if (JSON.stringify(item) === '{}') {
            return obj.hasOwnProperty(typeof item + JSON.stringify(item) + item.toString()) ? false : (obj[typeof item + JSON.stringify(item) + item.toString()] = true)
        } else {
            console.log(typeof item + JSON.stringify(item));
            return obj.hasOwnProperty(typeof item + JSON.stringify(item)) ? false : (obj[typeof item + JSON.stringify(item)] = true)
        }
    })
}

整理了一个列表,我们重点关注下对象和 NaN 的去重情况:

方法 结果 说明
for循环 [1, "1", null, undefined, String, String, /a/, /a/, NaN, NaN] 对象和 NaN 不去重
indexOf [1, "1", null, undefined, String, String, /a/, /a/, NaN, NaN] 对象和 NaN 不去重
sort [/a/, /a/, "1", 1, String, 1, String, NaN, NaN, null, undefined] 对象和 NaN 不去重 数字 1 也不去重
filter + indexOf [1, "1", null, undefined, String, String, /a/, /a/] 对象不去重 NaN 会被忽略掉
filter + sort [/a/, /a/, "1", 1, String, 1, String, NaN, NaN, null, undefined] 对象和 NaN 不去重 数字 1 不去重
优化后的键值对方法 [1, "1", null, undefined, String, /a/, NaN] 全部去重
Set [1, "1", null, undefined, String, String, /a/, /a/, NaN] 对象不去重 NaN 去重

想了解为什么会出现以上的结果,看两个 demo 便能明白:

// demo1
var arr = [1, 2, NaN];
arr.indexOf(NaN); // -1

indexOf 底层还是使用 === 进行判断,因为 NaN === NaN的结果为 false,所以使用 indexOf 查找不到 NaN 元素

// demo2
function unique(array) {
   return Array.from(new Set(array));
}
console.log(unique([NaN, NaN])) // [NaN]

Set 认为尽管 NaN === NaN 为 false,但是这两个元素是重复的。

18. sort 函数自定义比较函数

arr.sort([compareFunction])

compareFunction 可选

用来指定按某种顺序进行排列的函数。如果省略,元素按照转换为的字符串的各个字符的Unicode位点进行排序。

  • firstEl

    第一个用于比较的元素。

  • secondEl

    第二个用于比较的元素。

如果指明了 compareFunction ,那么数组会按照调用该函数的返回值排序。即 a 和 b 是两个将要被比较的元素:

  • 如果 compareFunction(a, b) 小于 0 ,那么 a 会被排列到 b 之前;

  • 如果 compareFunction(a, b) 等于 0 , a 和 b 的相对位置不变。备注: ECMAScript 标准并不保证这一行为,而且也不是所有浏览器都会遵守(例如 Mozilla 在 2003 年之前的版本);

  • 如果 compareFunction(a, b) 大于 0 , b 会被排列到 a 之前。

  • compareFunction(a, b) 必须总是对相同的输入返回相同的比较结果,否则排序的结果将是不确定的。

// 剑指offer-把数组排成最小的数
/* 
解题思路:
根据题目的要求,两个把数组排成最小的数能拼接成数字 mn 和 nm
如果 mn < nm, 那么我们应该打印出 mn, 也就是 m 应该排在 n 的前面,
我们定义此时 m 小于 n; 反之,则 n 小于 m 
由于把 m 和n 拼接起来得到 mn 和 nm,它们的位数一定是相同的,
因此比较它们的大小只需要按照字符串大小的比较规则就可以了. 
*/
function PrintMinNumber(numbers) {
    // 注意 返回值 是字符串
    let res = numbers.sort(compare);

    // 定义比较规则: 
    function compare(num1, num2) {
        if ('' + num1 + num2 < '' + num2 + num1) {
            return -1;
        }
    }
    return res.join('');
}

19. splice() 方法向/从数组中添加/删除项目

定义和用法

splice() 方法向/从数组中添加/删除项目,然后返回被删除的项目。

*注释:该方改变原始数组。

语法

arrayObject.splice(index,howmany,item1,.....,itemX)
参数 描述
index 必需。整数,规定添加/删除项目的位置,使用负数可从数组结尾处规定位置。
howmany 必需。要删除的项目数量。如果设置为 0,则不会删除项目。
item1, ..., itemX 可选。向数组添加的新项目。

20. undefined和null == 比较的情况

undefined和null与任何有意义的值比较返回的都是false,但是null与undefined之间互相比较返回的是true。

console.log(null == false);  // false
console.log(null == true);  // false
console.log(undefined == false);  // false
console.log(undefined == true);   // false
console.log(undefined == null);  // true
console.log(undefined == undefined);  // true
console.log(null == null);  // true

21. call () apply ()

call () 需要传递明确几个参数,写全,

apply() 可以接收一个数组作为参数,不管数组中有多少个元素

// var a = [1,4,5,2,9];
// 下面求a中最大值正确的是
Math.max.apply(null,a)
 call 的话
Math.max.call(null,...a);

22. js 的全局函数,全局属性

js的全局属性:Infinity、NAN、undefined

js的全局函数:decodeURI()、decodeURIcomponent()、

​ encodeURI、encodeURIcomponent()、

escape()、eval()、isFinite()、isNAN()、

​ Number()、parseFloat()、parseInt()、String()、unescape()。

注意:setTimeout 不是全局函数

23. 事件能否冒泡

24. 属性继承

继承就是指子节点默认使用父节点的样式属性。

不可继承的属性太多了不要背,记住可以继承的属性有哪些就行了。

可以继承的属性很少,只有颜色,文字,字体间距行高对齐方式,和列表的样式可以继承。

所有元素可继承:visibility和cursor。

内联元素可继承:letter-spacing、word-spacing、white-space、line-height、color、font、font-family、font-size、font-style、font-variant、font-weight、text-decoration、text-transform、direction。

终端块状元素可继承:text-indent和text-align。

列表元素可继承:list-style、list-style-type、list-style-position、list-style-image。

25.JSON 属性名称

属性名称必须是双引号括起来的字符串;最后一个属性后不能有逗号。

JSON 属性名称
属性名称必须是**双引号**括起来的字符串;最后一个属性后不能有逗号。

26.正则表达式替换字符串中所有的“多个空格”记得加 g 修饰符

let s = "a good   example";
s.trim().replace(/\s+/, ' ') // 没有加 g,输出为 :“a-good   example”,第二个空格没有被替换

s.trim().replace(/\s+/g, '-') // 加了 g ,输出为:“a-good-example”

27.split( ) 第一个参数可以是正则表达式

str.split([separator[, limit]])

separator 指定表示每个拆分应发生的点的字符串。separator 可以是一个字符串或正则表达式

var reverseWords = function(s) {
    // 自己的做法:
    return s.trim().replace(/\s+/g, ' ').split(' ').reverse().join(' ');
    // split 使用正则:
    return s.trim().split(/\s+/).reverse().join(' ');
};

28. Number(' ') 遇到空字符串的话结果是 0

console.log(Number('   ')); // 0
console.log(Number('')); // 0

Number('foo')     // NaN