LeetCode刷题笔记

1. 箭头函数

箭头函数

x => x * x

相当于:

function (x) {
    return x * x;
}

2. 数组排序:sort()方法

1)默认地,sort() 函数根据字符串Unicode码。

var fruits = ["Banana", "Orange", "Apple", "Mango"];
fruits.sort();            // 对 fruits 中的元素进行排序

该函数很适合字符串(“Apple” 会排在 “Banana” 之前)。

2)比较函数的目的是定义另一种排序顺序。

比较函数应该返回一个负,零或正值,这取决于参数。

升序排序:

var points = [40, 100, 1, 5, 25, 10];
points.sort(function(a, b){return a - b}); //可以写成points.sort((a,b) = > a-b);

降序排序:

var points = [40, 100, 1, 5, 25, 10];
points.sort(function(a, b){return b - a});

随机顺序排序:

var points = [40, 100, 1, 5, 25, 10];
points.sort(function(a, b){return 0.5 - Math.random()}); 

3. 数组去重

利用ES6的Set数据结构,Set类似数组,但里面的元素不重复

const numbers = [2,3,4,4,2,3,3,4,4,5,5,6,6,7,5,32,3,4,5]
// 用...(展开操作符)操作符将Set转换为Array
console.log([...new Set(numbers)])  
// 或者:Array.from(new Set(numbers));也可以实现将set对象转换成数组
// [2, 3, 4, 5, 6, 7, 32]

4. 数组

JavaScript的数组是一个拥有堆栈和队列自身优点的global对象。也就是说JavaScript数组可以表现的像栈(LIFO)和队列(FIFO)一样操作。

常用方法:
splice()slice()push()unshift()pop()shift()join()reverse()sort()concat()split()

push():向数组末尾添加一个或者多个元素,并返回新的长度
pop():删除数组的最后一个元素,把数组的长度减1,并且返回它被删除元素的值,如果数组变为空,则该方法不改变数组,返回undefine值
unshift():是向数组的开头添加一个或多个元素,并且返回新的长度
shift():用于把数组的第一个元素从其中删除,并返回被删除的值。如果数组是空的,shift()方法将不进行任何操作,返回undefined的值

join() :数组转字符串,方法只接收一个参数:即默认为逗号分隔符
reverse() (反转数组):方法用于颠倒数组中元素的顺序
concat() :用于连接两个或多个数组
slice():arr.slice(start , end); 数组截取,返回一个新的数组,包含从 start 到 end (不包括该元素)的 arr 中的元素
indexOf() :返回某个指定的字符串值在字符串中首次出现的位置
split() :用于把一个字符串分割成字符串数组

参考博客:js数组常用方法

类比:字符串String方法

    obj.charAt(index)
        返回index位置的字符
    obj.charCodeAt()
        返回index位置的字符编码
    obj.indexOf("str")
        顺序搜索str,返回其位置,未找到返回-1
    obj.lastIndexOf("str")
        倒序搜索str,返回其位置,未找到返回-1
    slice(start,end):同数组
    substring(start,end):同上,区别在于参数为负数时自动转换为0,并且较小的数为起始位
    substr(start,len):同上,len 表示截取的长度

补充:Date对象的方法

getDate() 	获得以数值计(1-31)的日
getDay() 	或者以数值计(0-6)的周
getFullYear() 	获得四位的年(yyyy)
getHours() 	获得时(0-23getMilliseconds() 	获得毫秒(0-999getMinutes() 	获得分钟(0-59getMonth() 	获得月(0-11getSeconds() 	获得秒(0-59getTime() 	获得时间(197011 日以来的毫秒)

5. 输出空格

  • 使用输出html标签 来解决
document.write("  "+"1"+"    "+"23");
 结果:  1    23
  • 使用CSS样式来解决
 document.write("<span style='white-space:pre;'>"+"  1        2    3    "+"</span>");
 结果:  1       2     3    

在输出时添加“white-space:pre;”样式属性。这个样式表示"空白会被浏览器保留"

6. confirm 消息对话框、prompt 消息对话框、打开新窗口(window.open)、关闭窗口(window.close)

参考博客:JavaScript入门篇 (看后半部分)

还包括一些DOM的基本操作,比如:

document.getElementById(“id”)

改变元素内容Object.innerHTML

修改HTML样式(比如background、color等,还包括显示或隐藏效果display)Object.style.fontsize=20

修改类名object.className = classname

7. 二叉搜索树的中序遍历

    function inOrder(root){ // 中序遍历得到有序数组(递增)
        if(!root){
            return false;  // 此处判断root是否为空必须要加上
        }
        inOrder(root.left);
        
        // 中序遍历的关键点,进而pushpush每一个元素得到递增数组
        numbers.push(root.val);  //push()函数用于向当前数组的添加一个或多个元素,并返回新的数组长度。
        
        inOrder(root.right);
    }
    inOrder(root);

8. 展开运算符(…)

可以合并多个数组。

类数组对象变成数组。

9. 广度优先搜索BFS

var levelOrder = function(root) {
    if(!root) return [];
    let queue = [root];  // 队列,记录当前层的结点
    let result = [];
    let step = 0;

    // 广度优先搜索(Breadth First Search)(其实是二叉树的层次遍历),又叫宽度优先搜索或横向优先搜索,是从根结点开始沿着树的宽度搜索遍历
    while(queue.length){
        result[step] = [];
        let len = queue.length;

        while(len){
            // shift()用于把数组的第一个元素从其中删除,并返回被删除的值。如果数组是空的,shift()方法将不进行任何操作,返回undefined的值
            let first = queue.shift();
            result[step].push(first.val);
            // console.log(first)
            if(first.left) queue.push(first.left);
            if(first.right) queue.push(first.right);
            len--;
        }
        step++;
        // console.log(queue)
    }
    return result;
};

10. 深度优先搜索DFS

var levelOrder = function(root) {
    if(!root) return [];
    let result = [];  // 存放结果
    // 深度优先搜索(Depth First Search)(其实是二叉树的先序遍历)是沿着树的深度遍历树的节点,尽可能深的搜索树的分支。
    dfs(root,0,result);
    return result;
};

function dfs(root,step,result){
    if(root){
        if(!result[step]) result[step] = [];  // 此判断必须这样写,result[step] ==== null 无效
        result[step].push(root.val);  // 用来记录每一层的节点
        dfs(root.left, step + 1, result);
        dfs(root.right, step + 1, result);
    } 
}

11. 双指针

// 标签:数组遍历
// 首先对数组进行排序,排序后固定一个数 nums[i],再使用左右指针指向 nums[i]后面的两端,数字分别为 nums[L] 和 nums[R],计算三个数的和 sum 判断是否满足为0,满足则添加进结果集
// 如果 nums[i]大于 0,则三数之和必然无法等于 0,结束循环
// 如果 nums[i] == nums[i−1],则说明该数字重复,会导致结果重复,所以应该跳过
// 当 sum == 0 时,nums[L] == nums[L+1] 则会导致结果重复,应该跳过,L++
// 当 sum == 0 时,nums[R] == nums[R−1] 则会导致结果重复,应该跳过,R−−
// 时间复杂度:O(n2),n 为数组长度

var threeSum = function(nums) {
    let ans = [];
    nums.sort((a,b) => a-b);  // 升序排序,箭头函数
    for(let i = 0;i<nums.length-2;i++){
        if(nums[i] > 0) break;  // 如果 nums[i]大于 0,则三数之和必然无法等于 0,结束循环
        if(nums[i] == nums[i-1] && i>0){  // 如果 nums[i] == nums[i−1],则说明该数字重复,会导致结果重复,所以应该跳过
            continue;
        }

        // 双指针
        let start = i+1;
        let end = nums.length-1;
        while(start < end){
            let sum = nums[start] + nums[end] + nums[i];
            if(sum == 0){
                if(start-1>i && nums[start] == nums[start-1]){ // 或者:nums[start] == nums[start+1]
                    start++;
                    continue;
                }
                if(end+1<nums.length-1 && nums[end] == nums[end+1]){ // nums[end] == nums[end−1]
                    end--;
                    continue;
                }
                // while (nums[start] == nums[start+1]) start++; // 去重
                // while (nums[end] == nums[end-1]) end--; // 去重

                ans.push([nums[i],nums[start],nums[end]]); // JavaScript的数组是一个拥有堆栈和队列自身优点的global对象。
                start++;
                end--;            
            }
            else if(sum < 0) start++;
            else end--;
        }
    }
    return ans;
};

12. 哈希表

剑指 Offer 52. 两个链表的第一个公共节点

// 哈希表
// Map是一组键值对的结构,具有极快的查找速度
var getIntersectionNode = function(headA, headB) {
    let map = new Map();
    let node = headA;
    while(node){
        map.set(node,true); // 添加新的键值对,并对每一个node节点赋真值true
        node = node.next;
    }

    node = headB;
    while(node){
        if(map.has(node)) return node; // 判断是否存在键“node”
        node = node.next;
    }

    return null;
};
//哈希表是基于键值对的一种数据存储结构,key值不可以重复,value可以重复,后面添加的重复的key值的时候,会把之前key值对应的value给覆盖掉,JavaScript中的对象具有天然的哈希特性。

//使用一层循环,每遍历到一个元素就计算该元素与 target 之间的差值 dif,然后以 dif 为下标到数组temp中寻找,如果 temp[dif] 有值(即不是undefined),则返回两个元素在数组 nums 的下标,如果没有找到,则将当前元素存入数组temp 中。
//时间复杂度:O(n)。

//var声明的变量只能是全局的或者是整个函数块的;let则允许声明一个作用域被限制在块级中的变量、语句或者表达式

var twoSum = function(nums, target) {
    let temp = []
    for (let i = 0; i < nums.length; i++) {
        let dif = target-nums[i]
        if (temp[dif] !== undefined) {
            return [temp[dif], i]
        }
        temp[nums[i]] = i;//记录数组nums对应每一个元素的下标
    }
};

13. 循环遍历数组

1)for循环

var array = [1,2,3,4,5,6,7];  
    for (var i = 0; i < array.length; i) {  
        console.log(i,array[i]);  
    }  

2)for in

 for(let index in array) {  
        console.log(index,array[index]);  
    };  

3)for of

for(let v of array) {  
        console.log(v);  
    }; 

4)forEach

array.forEach(v=>{  
    console.log(v);  
});

【补充】

for in总是得到对像的key或数组,字符串的下标,而for of和forEach一样,是直接得到值。

14. N叉树的前序遍历

// 二N叉树的前序遍历就是先遍历根节点,然后依次递归遍历每个子树。
var preorder = function(root) {
    if(!root) return [];
    let result = [];
    function order(root){
        if(root){
            result.push(root.val);
            // forEach循环遍历数组,得到的是值
            root.children.forEach(child => {
                order(child);
            })
        }
    }
    order(root);
    return result;
};

15. 二叉树的三序遍历(迭代法)

  • 前序遍历:根-左-右
  • 中序遍历:左-根-右
  • 后续遍历:左-右-根

栈:先进后出

前序遍历:

var preorderTraversal = function(root) {
    let res = [];
    if(!root){
        return res;
    }
    
    // 对任意一个节点附加一个标识:

    // true:表示当前节点是三序遍历中相应顺序的根节点,碰到需要加入结果集
    // false:表示此节点属于三序遍历中的左、右子树的操作,需要压入栈中

    let stack = [[root,false]];
    while(stack.length > 0){
        let node = stack.pop();
        let curr = node[0];
        let isTrue = node[1];
        if(isTrue){
            res.push(curr.val);
        }else{
            if(curr.right){
                stack.push([curr.right,false]);
            }
            if(curr.left){
                stack.push([curr.left,false]);
            }
            stack.push([curr,true]);
        }
    }
    return res;
};

参考:二叉树的三序遍历

16. Map和Set集合

Map:

Map是一组键值对的结构,具有极快的查找速度。

初始化Map需要一个二维数组,或者直接初始化一个空Map。Map具有以下方法:

var m = new Map(); // 空Map
2 m.set('Adam', 67); // 添加新的key-value
3 m.set('Bob', 59);
4 m.has('Adam'); // 是否存在key 'Adam': true
5 m.get('Adam'); // 67
6 m.delete('Adam'); // 删除key 'Adam'
7 m.get('Adam'); // undefined 

举例:

1 var m = new Map([['Michael', 95], ['Bob', 75], ['Tracy', 85]]);
2 m.get('Michael'); // 95 
Set:

Set和Map类似,也是一组key的集合,但不存储value。由于key不能重复,所以,在Set中,没有重复的key。

要创建一个Set,需要提供一个Array作为输入,或者直接创建一个空Set:

var s1 = new Set(); // 空Set
var s2 = new Set([1, 2, 3]); // 含1, 2, 3 

17. 回溯算法

经典问题:八皇后问题

常用场景:排列组合

剑指 Offer 38. 字符串的排列

/**
 * @param {string} s
 * @return {string[]}
 */
var permutation = function(s) {
    let res = new Set();
    let visit = [];

    // 深度优先搜索
    function dfs(path){
        // console.log("已调用dfs")
        if(path.length === s.length) res.add(path);
        for(let i = 0; i < s.length; i++){
            if(visit[i]) continue;
            visit[i] = true;
            dfs(path + s[i]);
            visit[i] = false;
        }
    }

    dfs('');
    return [...res];
};

22. 括号生成

/**
 * @param {number} n
 * @return {string[]}
 */

// 时间复杂度:O()  空间复杂度:O()

// 用dfs进行遍历,找出所有解,这个过程叫回溯。
// 在回溯的过程中,对一些条件进行限制,使得更可能快地找到最优解,这个过程叫剪枝。
// 简单来说,回溯其实是一种递归。
// ①如果当前正在构建的字符串的长度curr.length===2*n,则构建完成,存放到结果集result;
// ②如果左括号的数量leftNum>0,则可以将(加入curr中;
// ③如果左括号的数量leftNum<右括号的数量rightNum,则可以将)加入curr中;
var generateParenthesis = function(n) {
    let result = [];
    function dfs(leftNum,rightNum,curr){
        if(curr.length === 2*n) result.push(curr); // 剪枝
        if(leftNum>0) dfs(leftNum-1,rightNum,curr+'('); // 剪枝
        if(leftNum<rightNum) dfs(leftNum,rightNum-1,curr+')'); // 剪枝
    }
    dfs(n,n,'');
    return result;
};

18. 滑动窗口算法

剑指 Offer 57 - II. 和为s的连续正数序列

/**
 * @param {number} target
 * @return {number[][]}
 */

// 滑动窗口算法
// 发现本题中所有输出结果都是按着顺序从小到大排列的
var findContinuousSequence = function(target) {
    let index = target%2 === 0 ? target/2 : parseInt(target/2) + 1;
    let res = [];
    let temp = [];
    let sum = 0;

    for(let i = 1; i <= index; i++){
        temp.push(i);
        sum += i;

        // 当sum > target时,删除temp中第一个元素,相应的sum应减掉第一个数组元素,直到sum <= target再执行下一步代码
        while (sum > target){
            // let _shift = temp.shift();
            sum -= temp.shift();  // shift():用于把数组的第一个元素从其中删除,并返回被删除的值
        }

        if(sum === target && temp.length >= 2){
            // console.log(temp)
            res.push([...temp]);  // 此处必须使用扩展运算符...temp
            // console.log(res)
        }
    }
    return res;
};

19. js取整数、取余数的方法

取整

1)取整

// 丢弃小数部分,保留整数部分
parseInt(5/2)  // 2

2)向上取整

// 向上取整,有小数就整数部分加1
Math.ceil(5/2)  // 3

3)向下取整

// 向下取整,丢弃小数部分
Math.floor(5/2)  // 2

4)四舍五入

// 四舍五入
Math.round(5/2)  // 3

取余

// 取余
6%4  // 2

20. 分治算法(归并排序)

js算法-归并排序(merge_sort)

剑指 Offer 25. 合并两个排序的链表

21. 平衡二叉树

剑指 Offer 55 - II. 平衡二叉树

22. Math对象

Math.min()用于确定一组数值中的最小值;

Math.max()用于确定一组数值中的最大值;

Math.ceil()执行向上舍入,即它总是将数值向上舍入为最接近的整数;

Math.floor()执行向下舍入,即它总是将数值向下舍入为最接近的整数;

Math.round()执行标准舍入,即它总是将数值四舍五入为最接近的整数;

Math.random()方法返回介于01之间一个随机数,不包括01;

Math.pow()获取一个值的多少次幂; // 例如:Math.pow(10,2) = 100;

Math.sqrt()对数值开方;

Math.PI 获取圆周率π 的值;

Math.abs()取绝对值。

23. 正则表达式

参考博客:添加链接描述js正则表达式语法正则表达式详解

正则验证代码如下:

验证字母:/^[a-zA-Z]+$/
验证长度为3的字符:/^.{3}$/
验证由26个英文字母组成的字符串:/^[A-Za-z]+$/
验证日期YYYY-MM-DD/^(\d{1,4})(-|\/)(\d{1,2})\2(\d{1,2})$/
验证邮编:/^\d{6}$/
验证日期格式YYYY-MM-DD hh:mm:ss:/^(\d{1,4})(-|\/)(\d{1,2})\2(\d{1,2}) (\d{1,2}):(\d{1,2}):(\d{1,2})$/
验证整数:/^[-+]?\d*$/
验证小数:/^[-\+]?\d+(\.\d+)?$/
验证中文:/^[\u0391-\uFFE5]+$/
验证邮箱:/^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/
验证手机号:/^1[3456789]\d{9}$/
验证身份证:/^\d{6}(18|19|20)?\d{2}(0[1-9]|1[12])(0[1-9]|[12]\d|3[01])\d{3}(\d|X)$/

在线测试工具:https://regexr.com/

24. 递归与迭代

递归,程序反复调用自身即是递归。

做题方法,思考以下几点:

  • 终止条件
  • 返回值是什么
  • 本级递归需要干什么

博客讲解:三道题套路解决递归问题

力扣题目:24. 两两交换链表中的节点101. 对称二叉树110. 平衡二叉树104. 二叉树的最大深度剑指 Offer 55 - I. 二叉树的深度111. 二叉树的最小深度

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值