刷题注意套路:
- 按照类型刷题;
- 通用套路;
- 时间复杂度和空间复杂度的优化
C1 数据结构和算法
数据结构:计算机存储、组织数据的方式
算法:一系列解决问题的清晰指令
程序 = 数据结构+算法
数据结构:
- 栈、队列、链表
- 集合、字典
- 树、堆、图
C2 时间、空间复杂度
时间复杂度:定性描述算法的运行时间
空间复杂度:算法在运行过程中临时占用存储空间大小的量度
C3 栈
简介
const stack = []
stack.push(1)
stack.push(2)
const item1 = stack.pop()
const item2 = stack.pop()
栈的应用场景
leetcode20 有效的括号
var isValid = function(s) {
if(s.length % 2 === 1) return false
let map = new Map()
let stack = [];
map.set('(',')');
map.set('[',']');
map.set('{','}');
for(let tmp of s){
if(map.has(tmp)){
stack.push(tmp)
}else if( map.get(stack.pop()) !== tmp ){
return false
}
}
return !stack.length
};
前端与栈:JS中的函数调用堆栈
总结
C4 队列
定义
应用场景
leetcode933 最近的请求次数
var RecentCounter = function() {
this.queue = []
};
/**
* @param {number} t
* @return {number}
*/
RecentCounter.prototype.ping = function(t) {
this.queue.push(t)
while(this.queue[0] < t-3000){
this.queue.shift()
}
return this.queue.length
};
/**
* Your RecentCounter object will be instantiated and called as such:
* var obj = new RecentCounter()
* var param_1 = obj.ping(t)
前端与队列:JS异步中的任务队列
总结
C5 链表
定义
const a = { val: 'a' }
const b = { val: 'b' }
const c = { val: 'c' }
const d = { val: 'd' }
a.next = b
b.next = c
c.next = d
//遍历
let p = a
while (p) {
console.log(p.val)
p = p.next
}
//增加
const e = { val: 'e' }
c.next = e
e.next = d
//删除
c.next = d
LeetCode237.删除列表中的节点
/**
* Definition for singly-linked list.
* function ListNode(val) {
* this.val = val;
* this.next = null;
* }
*/
/**
* @param {ListNode} node
* @return {void} Do not return anything, modify node in-place instead.
*/
var deleteNode = function(node) {
node.val = node.next.val
node.next = node.next.next
};
LeetCode206.反转链表
- 双指针
- 遍历边界
/**
* Definition for singly-linked list.
* function ListNode(val, next) {
* this.val = (val===undefined ? 0 : val)
* this.next = (next===undefined ? null : next)
* }
*/
/**
* @param {ListNode} head
* @return {ListNode}
*/
var reverseList = function(head) {
let p1 = null,p2 = head;
while(p2){
let tmp = p2.next
p2.next = p1
p1 = p2
p2 = tmp
}
return p1
};
LeetCode2.两数相加
/**
* Definition for singly-linked list.
* function ListNode(val, next) {
* this.val = (val===undefined ? 0 : val)
* this.next = (next===undefined ? null : next)
* }
*/
/**
* @param {ListNode} l1
* @param {ListNode} l2
* @return {ListNode}
*/
var addTwoNumbers = function(l1, l2) {
let l3 = new ListNode()
let p1 = l1,p2 = l2,p3 = l3
let flag = 0
while(p1 || p2){
let val1 = p1? p1.val:0
let val2 = p2? p2.val:0
let val3 = val1 + val2 + flag
flag = Math.floor(val3 /10)
p3.next = new ListNode(val3 % 10)
if(p1) p1 = p1.next
if(p2) p2 = p2.next
p3 = p3.next
if(flag) p3.next = new ListNode(flag)
}
return l3.next
};
LeetCode83.删除排序列表中的重复元素
/**
* Definition for singly-linked list.
* function ListNode(val, next) {
* this.val = (val===undefined ? 0 : val)
* this.next = (next===undefined ? null : next)
* }
*/
/**
* @param {ListNode} head
* @return {ListNode}
*/
var deleteDuplicates = function(head) {
let p = head
while(p && p.next){
if(p.val === p.next.val){
p.next = p.next.next
}else{
p = p.next
}
}
return head
};
LeetCode141.环形链表
/**
* Definition for singly-linked list.
* function ListNode(val) {
* this.val = val;
* this.next = null;
* }
*/
/**
* @param {ListNode} head
* @return {boolean}
*/
var hasCycle = function(head) {
let set = new Set()
while(head){
if(set.has(head)){
return true
}else{
set.add(head)
head = head.next
}
}
return false
};
前端与链表:JS中的原型链
const instanceOf = (A, B) => {
let p = A
while (p) {
if (p === B.prototype) {
return true
}
p = p.__proto__
}
return false
}
console.log(instanceOf([], Array))
前端与链表:使用链表指针获取JSON的节点值
const json = {
a: { b: { c: 1 } },
d: { e: 2 },
}
const path = ['a', 'b', 'c']
let p = json
path.forEach((k) => {
p = p[k]
})
总结
C6 集合
简介
//去重
const arr = [1, 1, 2, 2]
const arr2 = [...new Set(arr)]
//判断元素是否在集合中
const set = new Set(arr)
const has = set.has(3)
//求交集
const set2 = new Set([2, 3])
const set3 = new Set([...set].filter((item) => set2.has(item)))
LeetCode349:两个数组的交集
/**
* @param {number[]} nums1
* @param {number[]} nums2
* @return {number[]}
*/
var intersection = function(nums1, nums2) {
return [...new Set(nums1)].filter(item =>nums2.includes(item) )
};
//时间复杂度O(MN)
//空间复杂度O(M)
前端与集合:使用ES6的set
章节总结
C7 字典
字典
LeetCode349 两个数组的交集
/**
* @param {number[]} nums1
* @param {number[]} nums2
* @return {number[]}
*/
var intersection = function(nums1, nums2) {
// return [...new Set(nums1)].filter(item =>nums2.includes(item) )
let map = new Map()
let res = []
nums1.forEach((item)=>{
map.set(item,true)
})
nums2.forEach((item)=>{
if(map.get(item)){
res.push(item)
map.delete(item)
}
})
return res
};
LeetCode20 有效的括号
LeetCode1 两数之和
注意到方法一的时间复杂度较高的原因是寻找 target - x 的时间复杂度过高。因此,我们需要一种更优秀的方法,能够快速寻找数组中是否存在目标元素。如果存在,我们需要找出它的索引。
使用哈希表,可以将寻找 target - x 的时间复杂度降低到从 O(N) 降低到 O(1)。
/**
* @param {number[]} nums
* @param {number} target
* @return {number[]}
*/
var twoSum = function(nums, target) {
// let res = []
// for(let i = 0;i<nums.length-1;i++){
// for(let j = 1;j<nums.length;j++){
// if((nums[i] + nums[j]) === target){
// res.push(i)
// res.push(j)
// }
// }
// }
// return res
let map = new Map()
for(let i = 0;i<nums.length;i++){
if(map.has(target-nums[i])){
return new Array(i,map.get(target-nums[i]))
}
map.set(nums[i],i)
}
};
*LeetCode3 无重复字符的最长子串
/**
* @param {string} s
* @return {number}
*/
//滑动窗口+双指针
var lengthOfLongestSubstring = function(s) {
if(s.length <= 1) return s.length
let res = 0
let left = 0,right = 0
let set = new Set()
while(right < s.length){
if(!set.has(s[right])){
set.add(s[right])
res = Math.max(res,set.size)
right++
}else{
set.delete(s[left])
left++
}
}
return res
};
LeetCode76 最小覆盖子串(困难)
总结
C8 树
简介
树的深度优先遍历和广度优先遍历
CODE PART
在这里插入代码片
CODE PART
在这里插入代码片
C9 回溯算法
let backtracking=(路径,选择列表) =>{
if (满足结束条件)) {
存放路径;
return;
}
for (选择:路径,选择列表) {
做出选择;
backtracking(路径,选择列表); // 递归
回溯,撤销处理结果
}
}