本周学习总结(原生+算法)

Button

 button{
    width: 100px;
    height: 50px;
    border-radius:25px;
    color:#000;
    border:2px solid blue;
    background-color: transparent;
  }

overflow:scroll

出现滚动条

记忆函数

const add = () => {
  let a = {}
  return num => {
    const result=num+10
    a[num]=result
    console.log(a)
    if (num in a) {
      return a[num]
    }else{
      return result
    }
  }
}
let a = add()
console.log(a(20))
console.log(a(10))

import 和require

import 命令是编译阶段执行的,在代码运行之前,就是意味着被导入的模块会先运行,而导入模块的文件会后运行

require() 运行代码时候再运行

BigInt(新的基础类型)

BigInt 数据类型的目的是比Number 属性类型支持的范围更大的整数值,主要用于大于Number 数据类型支持的范围

要创建BigInt ,只需在整数的尾数追加n即可

或者BigInt("9007199254740995")

9007199254740995n

console.log(typeof 10n);    // → bigint
10n==10  //true
与`BigInt`操作数一起使用时,算术运算符应该返回`BigInt` 值,因此,除法运算符的结果会自动向下舍入到最接近的整数
25n/10n;   // 2n
不能对混合使用`number`和`BigInt`  操作数执行算术操作
可以通过转化进行操作
BigInt(10)+10n
10+Number(10)

VDOM

VDOM就是一个数据结构

从逻辑上vdom就是用来抽象DOM的,底层上vdom普遍实现是基于哈希表这种数据结构

{
    type:'div',
    props:{
        name:'lucifer'
    },
    children:[{
        type:'span',
        props:{},
        children:[]
    }]    
}

所以我们从面向DOM编程,切换到面向VDOM编程,由于VDOM又是由数据驱动的,所以也就是数据驱动

DOM dif算法

AST

AST(抽象语法树) 是前端编译(转义)的理论基础

AST厉害就厉害在它本身不涉及到任何语法,因此你只要编写相应的转义规则,就可以将任何语法转义到任何语法,这就是babel,PostCSS,prettier,typescript 等的原理,除此之外,还有很多应用场景,比如编辑器

Lodash源码分析

_.chunk (不怎么理解)

_.chunk(['a', 'b', 'c', 'd'], 2);
// => [['a', 'b'], ['c', 'd']]

console.log([1, 2, 3, 4].reduce((acc, val, i) => {
  return [...acc,[val]]
},[]))
//[[1],[2],[3],[4]]
i%2
输入: 0 1 2 3 4
输出: 0 1 0 1 0

const chunk = (arr, size) => {
  return arr.reduce((acc, val, index) => {
    if (index % size === 0) {
      return [...acc, [val]]
    } else {
      //[[1,2],[3,4],[5]]
      return [...acc.slice(0, -1), [...acc.slice(-1)[0], val]]
      //[[1,2],[3,4],[5,6]]
    }
  }, [])
}
console.log(chunk([0,1,2,3,4,5,6], 2));
//[ [ 0, 1 ], [ 2, 3 ], [ 4, 5 ], [ 6 ] ]

找到二维数组中不同的数

let arrays = [[1, 2, 3, 4, 5], [5, 2, 10]];
console.log(arrays.reduce((a, b) => a.filter(c => !b.includes(c))));
//a=>[1,2,3,4,5]
//b=>[5,2,10]
console.log([[1, 2, 3, 4, 5], [1, 2, 4]]
  .reduce((acc, val) => {
    //return val //[1,2,4]   
    return acc //[1,2,3,4,5]
  }))
// output: [1, 3, 4]

深度降维

const flattenDeep = (arr) => Array.isArray(arr)
  ? arr.reduce( (a, b) => a.concat(flattenDeep(b)) , [])
  : [arr]

求多维数组的交集

let arrays = [[1, 2, 3,10], [101, 1, 10], [2, 1,10]];
console.log(arrays.reduce((acc, val) => acc.filter(item => val.includes(item))))

根据数组的个数,排成一个对象

console.log(['one', 'two', 'three'].reduce((acc, val, index, array, k = val.length) => {
  (acc[k] || (acc[k] = [])).push(val)
  return acc
}, {}))
//{ '3': [ 'one', 'two' ], '5': [ 'three' ] }

函数式编程

函数式编程中的函数指的是数学中的函数,而不是javascript中的函数

纯函数就是给定输入,输出总是相同的函数

柯里化
const add=x=>y=>x+y
add(1)(2)   //3

const g = x => x + 20
const f = x => x * 2
const compose = (f, g) => x => f(g(x))
console.log(compose(f, g)(10))  //40

**bind**
const add = (x, y, z) => x + y + z
const plus = add.bind(null, 10)
console.log(plus(10, 10))//30
console.log(plus(20, 20))//50

//[1, 2, 3]   =>   { 1: 1, 2: 4, 3: 9 }
const mapObject = (arr, fn) => {
  let itemArr = arr.map(fn);
  return arr.reduce((acc, val, index) => 
    (acc[val] = itemArr[index], acc), {})
}

//求最小值,最大值
const over=(...fns)=>(...args)=>fns.map(val=>val.apply(null,args))
over(Math.min, Math.max)(1, 2, 3, 4)

//输入(9,3)   输出 [81,6]   也就是第一个参数**2   第二个参数*2
//简单版
const over1 = (first, last) => [first ** 2, last * 2]
 console.log(over1(9, 3))//[81,6]
//封装版
const overArg=(fn,fns)=>(...args)=>args.map((val,i)=>fns[i](val))
console.log(overArg( [x => x ** 2, x => x * 2])(4,6)) //[ 16, 12 ]

//高阶函数
//自执行函数
(function (s) {
  return s*2
})(2);//4
(x => x * 2)(2);//4
//高阶
const add=fn=>x=>fn(x);
add(x => x + 2)(2)//4

隔行变色

  li:nth-child(2n) {
    background-color: red;
  }
  li:nth-of-type(2n-1) {
    background-color: gold;
  }

超过一行省略号...

.aaa{
   width: 200px;
   overflow:hidden;
   white-space:nowrap;
   text-overflow:ellipsis;
}

伪元素

.aaa{
    position:relative;
}
.aaa:after{
    content:'';
   	position:absolute;
    right:0;
    bottom:0;
}

undefined

未为变量赋值时默认值为undefined

当访问未初始化的变量,不存在的对象属性,不存在的数组元素等时,将接收一个undefined的值

1138

U

D

L

R

! 几个

输入:target = "leet"
输出:"DDR!UURRR!!DDD!"

输入:target = "code"
输出:"RR!DDRR!UUL!R!"

const alphabet = target => {
  let res = '';
  let x = 0,
    y = 0;
  for (let item of target) {
    let x1 = Math.floor((item.charCodeAt() - 97) / 5),
      y1 = (item.charCodeAt() - 97) % 5;
    //当前的位置l  x轴的位置  c是y轴的位置
    let l = x1 - x;
    c = y1 - y;
      //记得x轴=>c   y轴=>l
    /*上*/
    if (l < 0) {
      for (let i = 0; i < -l; i++) {
        res += 'U'
      }
    }
    /*下*/
    if (l > 0) {
      for (let i = 0; i < l; i++) {
        res += 'D'
      }
    }
    /*左*/
    if (c < 0) {
      for (let i = 0; i < -c; i++) {
        res += 'L'
      }
    }
    /*右*/
    if (c > 0) {
      for (let i = 0; i < c; i++) {
        res += 'R'
      }
    }
    res += '!';
    x = x1, y = y1;

  }
  return res
}
console.log(alphabet('kb'))

LeetCode1128

求多米诺骨牌的数量

dominoes[i] = [a, b] 和 dominoes[j] = [c, d]

等价的前提是 ac 且 bd,或是 ad 且 bc

也就是[1,2],[2,1]或者是[1,2],[1,2]

例如

输入[[1, 2], [2, 1], [3, 4], [3, 4],[6,5], [5, 6]]

输出 3

var numEquivDominoPairs = function (dominoes) {
  let arr = Array.from({ length: 100 }, v => 0);
  let res = 0;
  for (let item of dominoes) {
    //*10,是为了 [2,5]或者[3,4]不是相等的
    res += arr[Math.min(item[0], item[1])*10 + Math.max(item[0], item[1])]++
  }
  return res;
};
console.log(numEquivDominoPairs([[1, 2], [2, 1], [3, 4],[2,5],[6,5], [5, 6]]))
//3

724寻找数组的中心索引

我们是这样定义数组中心索引的:数组中心索引的左侧所有元素相加的和等于右侧所有元素相加的和。

如果数组不存在中心索引,那么我们应该返回 -1。如果数组有多个中心索引,那么我们应该返回最靠近左边的那一个。

左边的和等于右边的和
简化为: 总和-右边的和-中间数=左边的和
const Solution = nums => {
  let sum = 0;
  leftSum = 0;
  sum = nums.reduce((acc, val) => acc + val)
  for (let i = 0; i < nums.length; i++) {
    if (leftSum == sum - leftSum - nums[i]) {
      return i;
    }
    leftSum += nums[i]
  }
  return -1
}
console.log(Solution([1,2,3,6,2,3,1]))

747 至少是其他数字两倍的最大数

在一个给定的数组nums中,总是存在一个最大元素 。

查找数组中最大元素是否至少是数组中每个其他数字的两倍

如果是,返回最大的索引,否则返回-1

实例1

输入:nums=[3,6,1,0]

输出:1

思路:6大于数组中其他元素的两倍。6的索引是1, 所以我们返回1

实例2

输入: nums = [1, 2, 3, 4]
输出: -1
解释: 4没有超过3的两倍大, 所以我们返回 -1.

找到最大和第二大的元素,看最大的是不是第二大的2倍,若不是直接返回-1,在数组中找到索引
const Solution = nums => {
  if (nums.length == 1) {
    return 0
  }
  //最大值
  let max = 0;
  //第二大的值
  let second = 0;
  //索引
  let index = 0;
  for (let i = 0; i < nums.length; i++) {
    if (max < nums[i]) {
      max = nums[i]
      index = i;
    }
  }
  for (let item of nums) {
    if (item < max && second < item) {
      second = item
    }
  }
  console.log(max, second)
  if (second * 2 <= max) {
    return index
  }
  return -1
}
console.log(Solution([1, 2, 3, 4, 9]))

283 移动零

把一个数组里所有的0都移到后面,不能改变非零数的相对位置关系,而且不能拷贝额外的数组。

举例

输入:[0,1,0,3,5,0]

输出:[1,3,5,0,0,0]

//双指针
const Solution = nums => {
  let index = 0;
  for (let i = 0; i < nums.length; i++) {
    if (nums[i] != 0) {
      nums[index++] = nums[i]
    }
  }
  while (index < nums.length) {
    nums[index++] = 0;
  }
  return nums
}
console.log(Solution([0, 1, 1, 2, 3, 0, 0, 21]))
//[ 1, 1, 2, 3, 21, 0, 0, 0 ]

LeetCode 389找不同

输入:
s = "abcd"
t = "abcde"

输出:

'e'

运算性质:
A^B^B=A

//第一种位运算
const findThe = (s, t) => {
  let t1 = 0
  let index = 0;
  while (index < s.length) {
    t1 ^= s.charCodeAt(index)
    index++
  }
  let b = 0;
  while (b < t.length) {
    t1 ^= t.charCodeAt(b)
    b++
  }
  return String.fromCharCode(t1)
}
console.log(findThe('abc', 'bc'))
//'a'

//桶排序
const findThe = (s, t) => {
  const ans = Array.from({ length: 26 }, v => 0)
  let i = 0,
    j = 0,
    k = 0;
  while (i < s.length) {
    ans[s.charCodeAt(i) - 97]++
    i++
  }
  while (j < t.length) {
    ans[t.charCodeAt(j) - 97]++
    j++
  }
  while (k < ans.length) {
    if (ans[k] == 1) {
     return String.fromCharCode(k + 97)
    }
    k++
  }
  return -1

}

leetCode 455分发饼干

你的目标是尽可能满足越多数量的孩子,并输出这个最大数值

实例一

输入:[1,2,3],[1,1]

输出:1

解释:
你有三个孩子和两块小饼干,3个孩子的胃口值分别是:1,2,3。
虽然你有两块小饼干,由于他们的尺寸都是1,你只能让胃口值是1的孩子满足。
所以你应该输出1。

实例二

输入: [1,2], [1,2,3]

输出: 2

解释:
你有两个孩子和三块小饼干,2个孩子的胃口值分别是1,2。
你拥有的饼干数量和尺寸都足以让所有孩子满足。
所以你应该输出2.

const findCount = (g, s) => {
  g.sort()
  s.sort()
  let i = 0,
    j = 0;
  while (i < g.length && j < s.length) {
    //满足就是s[j]>=g[i]
    //如果满足,饼干j++,结束判断后换个孩子(i++)
    if (s[j] >= g[i]) {
      j++
    }
    i++
  }
  return i
}
console.log(findCount([1, 2], [1,2,3]))
//满足2个孩子

48 旋转矩阵

/*
* Given input matrix =
[
  [1,2,3],
  [4,5,6],
  [7,8,9]
],
rotate the input matrix in-place such that it becomes:
[
  [7,4,1],
  [8,5,2],
  [9,6,3]
]
*/
const rotate = (matrix) => {
  let arr = Array.from({ length: matrix.length }, v => [])
  for (let i = 0; i < matrix.length; i++) {
    for (let j = 0; j < matrix[i].length; j++) {
      arr[i][j]=matrix[matrix.length-1-j][i]
    }
  }
  return arr
}
let array1=[
    [1,2,3],
    [4,5,6],
    [7,8,9]
  ];
console.log(rotate(array1))

136 只出现一次的数

[1, 2, 3, 1, 1, 10, 2].filter(
  (val, index, array) =>
    array.indexOf(val) == array.lastIndexOf(val))


// 5^5=0  0^5=5
var singleNumber = function (nums) {
  let result=0;
  for (let i = 0; i < nums.length; i++) {
    result^=nums[i]
  }
  return result
};

const singleNumber = function (nums) {
  let set = new Set();
  for (let i = 0; i < nums.length; i++) {
    if (set.has(nums[i])) {
      set.delete(nums[i])
    } else {
      set.add(nums[i])
    }
  }
  return Array.from(set)
};

//2*(去重的数组的和)-原数组的和
//只考虑重复一次
const singleNumber = function (nums) {
  let set = new Set(nums);
  return Array.from(set).reduce((acc,val)=>acc+val)*2-nums.reduce((acc,val)=>acc+val)
};
console.log(singleNumber([1, 2, 4,1,2]))

79单词搜索

给定一个二维网格和一个单词,找出该单词是否存在于网格中。

单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母不允许被重复使用。

board =
[
  ['A','B','C','E'],
  ['S','F','C','S'],
  ['A','D','E','E']
]

给定 word = "ABCCED", 返回 true.
给定 word = "SEE", 返回 true.
给定 word = "ABCB", 返回 false.

[
    ['A', 'B', 'C'],
    ['D', 'A', 'A'], 
    ['G', 'C', 'D']
]
'ABCAD'
// 要走的数组,给定的路径数组
//原路径,新路径
const exist = (thePath, newPath) => {
  for (let y = 0; y < thePath.length; y++) {
    for (let x = 0; x < thePath[0].length; x++) {
      //d是走了几步
      if (finds(thePath, newPath, y, x, d=0)) {
        return true
      }
    }
  }
return false
}
const finds = (thePath, newPath, y, x, d) => {
  //走的长度等于要走的数组的长度
  if (d == newPath.length) return true;
  //x,y不能大于数据的长度,也不能少于0
  if (y < 0 || x < 0 || y == thePath.length || x == thePath.length) return fasle;
  //开始比较
  if (thePath[y][x] != newPath[d]) return false;
  //记录走过上一步的位置
  let temp = thePath[y][x]
  thePath[y][x]='*'
  //是否可以走下一步
  /*右*/
  let exist = finds(thePath, newPath, y, x + 1, d + 1)
    /*左*/
    || finds(thePath, newPath, y, x - 1, d + 1)
    /*下*/
    || finds(thePath, newPath, y + 1, x, d + 1)
    /*上*/
    || finds(thePath, newPath, y - 1, x, d + 1)
  //移动到上一步走的位置
  thePath[y][x]=temp
  return exist
}
console.log(exist([['A', 'B', 'C'], ['D', 'A', 'A'], ['G', 'C', 'D']], 'ABC'))

41 缺失的第一个正数

给定一个未排序的整数数组,找出其中没有出现的最小的正整数。

示例 1:

输入: [1,2,0]
输出: 3

示例 2:

输入: [3,4,-1,1]
输出: 2

示例 3:

输入: [7,8,9,11,12]
输出: 1
const Solution=nums=>{
  let i=1;
  while (i) {
    if (nums.indexOf(i) < 0) {
      return i
    }
    i++
  }
}

var firstMissingPositive = function (nums) {
  let set = new Set();
  for (let i = 0; i < nums.length; i++) {
    //nums[i]>=1  且  每个数小于数组的个数
    if (nums[i] >= 1 && nums[i] <= nums.length) {
      set.add(nums[i])
    }
  }
  for (let i = 1; i <= nums.length; i++) {
    if (!set.has(i)) {
      return i
    }
  }
  return nums.length + 1
};
console.log(firstMissingPositive([3, 4, -1, 1]))
posted @ 2019-08-03 00:37  猫神甜辣酱  阅读(488)  评论(0编辑  收藏  举报