数组
1. 剑指 Offer 03. 数组中重复的数字
/**
* @param {number[]} nums
* @return {number}
*/
var findRepeatNumber = function(nums) {
//对象属性的方法
// let mapList = {}
// for(let i = 0;i<nums.length;i++){
// if(!mapList.hasOwnProperty(nums[i])){
// mapList[nums[i]] = 1
// }else{
// return nums[i]
// }
// }
//map方法
let mapList =new Map()
for(let i of nums){
if(!mapList.has(i)){
mapList.set(i,1)
}else{
return i
}
}
return null
};
2. 剑指 Offer 04. 二维数组中的查找
/**
1. @param {number[][]} matrix
2. @param {number} target
3. @return {boolean}
*/
var findNumberIn2DArray = function(matrix, target) {
if(matrix.length == 0) return false
let row = matrix.length
let col = matrix[0].length
let i = 0
let j = col-1
while(i<row&&j>=0){
if(matrix[i][j] == target){
return true
}else if(matrix[i][j] > target){
j--
}else{
i++
}
}
return false
};
3. 剑指 Offer 29. 顺时针打印矩阵
<script>
var spiralOrder = function (matrix) {
let res = []
if (matrix.length === 0) return res
let row = matrix.length,
col = matrix[0].length,
len = row * col
let flag = []
for (let i = 0; i < row; i++) {
flag[i] = []
for (let j = 0; j < col; j++) {
flag[i][j] = false
}
}
let i = 0,
j = 0
flag[i][j] = true
res.push(matrix[i][j])
while (res.length < len) {
while (j + 1 < col && flag[i][j + 1] === false) {
j++
flag[i][j] = true
res.push(matrix[i][j])
}
while (i + 1 < row && flag[i + 1][j] === false) {
i++
flag[i][j] = true
res.push(matrix[i][j])
}
while (j - 1 >= 0 && flag[i][j - 1] === false) {
j--
flag[i][j] = true
res.push(matrix[i][j])
}
while (i - 1 >= 0 && flag[i - 1][j] === false) {
i--
flag[i][j] = true
res.push(matrix[i][j])
}
}
return res
}
var matrix = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9],
]
var res = spiralOrder(matrix)
console.log(res)
</script>
4. 剑指 Offer 53 - I. 在排序数组中查找数字 I
var search = function(nums, target) {
if (
nums.length === 0 ||
nums[0] > target ||
nums[nums.length - 1] < target
)
return 0
//寻找左下限
let i = 0
j = nums.length - 1
while (i <= j) {
let mid = Math.floor((i + j) / 2)
if (nums[mid] < target) i = mid + 1 //<= 和 <的区别
else j = mid - 1
}
let left_index = i
//寻找右下限
var m = 0,
n = nums.length - 1
while (m <= n) {
let mid = Math.floor((m + n) / 2)
if (nums[mid] <= target) m = mid + 1
else n = mid - 1
}
let right_index = n
return right_index - left_index + 1
};
6. 剑指 Offer 53 - II. 0~n-1中缺失的数字
var missingNumber = function (nums) {
if (
(nums[0] === 0 && nums.length === 1) ||
(nums[0] === 0 && nums[nums.length - 1] === nums.length - 1)
)
return nums.length
let i = 0,
j = nums.length - 1
while (i < j) {
let mid = Math.floor((i + j) / 2)
if (nums[mid] === mid) i = mid + 1
else j = mid
}
return i
}
7. 剑指 Offer 56 - II. 数组中数字出现的次数 II
/**
* @param {number[]} nums
* @return {number}
*/
var singleNumber = function (nums) {
let map = new Map()
let res = 0
nums.forEach((ele) => {
if (!map.has(ele)) {
map.set(ele, true)
} else {
map.set(ele, false)
}
})
map.forEach((val, key, map) => {
if (val) {
res = key
}
})
return res
}
字符串
1. 剑指 Offer 58 - II. 左旋转字符串
var reverseLeftWords = function(s, n) {
let str1 = s.substring(0,n)
let str2 = s.substring(n,s.length)
return str2.concat('',str1)
};
2. 剑指 Offer 58 - I. 翻转单词顺序
var reverseWords = function(s) {
let arr = s.split(' ')
let res = ''
for (let i = arr.length - 1; i >= 0; i--) {
if (arr[i].trim() !== '') {
res = res.concat('', arr[i].trim() + ' ')
}
}
return res.trim()
//方法二
return s.trim().split(/\s+/).reverse().join(' ')
};
3. 剑指 Offer 67. 把字符串转换成整数
var strToInt = function(str) {
const regexp = /^[+-]?\d+/
let res = str.trim().match(regexp)
if (!res) return 0
else {
res = res[0].trim()
const max = Math.pow(2, 31) - 1
const min = Math.pow(-2, 31)
if (res > max) return max
else if (res < min) return min
else return res
}
};
链表
1. 剑指 Offer 22. 链表中倒数第k个节点
var getKthFromEnd = function(head, k) {
let first = head ,second = head
for(let i =0;i<k;i++){
second = second.next
}
while(second !== null){
first = first.next
second = second.next
}
return first
};
2. 剑指 Offer 06. 从尾到头打印链表
var reversePrint = function(head) {
var res = []
while(head){
res.push(head.val)
head = head.next
}
return res.reverse()
};
//栈先进后出,用unshift模拟
var reversePrint = function(head) {
var res = []
while(head){
res.unshift(head.val)
head = head.next
}
return res
};
3. 剑指 Offer 24. 反转链表
var reverseList = function(head) {
if (head === null) return null
let first = head,second = head.next
first.next = null //注意这里
while(second){
let tmp = second.next
second.next = first
first = second
second = tmp
}
return first
};
4. 剑指 Offer 52. 两个链表的第一个公共节点
var getIntersectionNode = function(headA, headB) {
let pa = headA,pb = headB
while(pa !== pb){
pa = pa === null? headB:pa.next
pb = pb === null? headA:pb.next
}
return pa
};
5. 剑指 Offer 18. 删除链表的节点
var deleteNode = function(head, val) {
if(head.val === val) return head.next
let first = head
while(head.next.val !== val) head = head.next
head.next = head.next.next
return first
}
6. 剑指 Offer 35. 复杂链表的复制
var copyRandomList = function(head) {
let cur = head
let map = new Map()
map.set(cur,new Node(cur.val))
while(cur.next){
cur = cur.next
map.set(cur,new Node(cur.val))
}
let p = head
while(p){
map.get(p).next = map.get(p.next)
map.get(p).random = map.get(p.random)
p = p.next
}
return map.get(head)
};
二叉树
- 层序遍历(广度遍历) 按层遍历 队列实现比较方便
- 中序遍历 左节点——根节点——右节点 递归
1. 剑指 Offer 55 - I. 二叉树的深度
var maxDepth = function(root) {
if(!root) return 0
let left = maxDepth(root.left)
let right = maxDepth(root.right)
return Math.max(left,right)+1
};
2. 剑指 Offer 55 - II. 平衡二叉树
var isBalanced = function(root) {
if(!root) return true
let left = getDepth(root.left)
let right = getDepth(root.right)
return isBalanced(root.left)&&isBalanced(root.right)&& Math.abs(right-left)<=1
};
var getDepth = function(root){
if(!root) return 0
return Math.max(getDepth(root.left),getDepth(root.right))+1
}
3. 剑指 Offer 27. 二叉树的镜像
var mirrorTree = function(root) {
if(!root) return root
let tmp = root.right
root.right = root.left
root.left = tmp
mirrorTree(root.left)
mirrorTree(root.right)
return root
};
4. 剑指 Offer 28. 对称的二叉树
var isSymmetric = function(root) {
let newRoot = mirrorTree(root)
return newRoot === root
};
var mirrorTree = function(root){
if(!root) return root
var tmp = root.right
root.right = root.left
root.left = tmp
mirrorTree(root.left)
mirrorTree(root.right)
return root
}
5. 剑指 Offer 32 - I. 从上到下打印二叉树
var levelOrder = function(root) {
let queue = [],res=[]
if(!root) return res
queue.push(root)
while(queue.length>0){
let root = queue.shift()
res.push(root.val)
if(root.left) queue.push(root.left)
if(root.right) queue.push(root.right)
}
return res
};
6. 剑指 Offer 32 - II. 从上到下打印二叉树 II
var levelOrder = function(root) {
let res = []
if(!root) return res
let queue = []
queue.push(root)
while(queue.length>0){
let tmp = []
let curLength = queue.length
for(let i = 0;i<curLength;i++){
let node = queue.shift()
tmp.push(node.val)
if(node.left) queue.push(node.left)
if(node.right) queue.push(node.right)
}
res.push(tmp)
}
return res
};
7. 剑指 Offer 32 - III. 从上到下打印二叉树 III
var levelOrder = function(root) {
let res = []
if(!root) return res
let queue = []
queue.push(root)
let j =0
while(queue.length>0){
let tmp = []
j++
let curLen = queue.length
for(let i = 0;i<curLen;i++){
let node = queue.shift()
tmp.push(node.val)
if(node.left) queue.push(node.left)
if(node.right) queue.push(node.right)
}
if(j%2) res.push(tmp)
else res.push(tmp.reverse())
}
return res
};
8. 剑指 Offer 54. 二叉搜索树的第k大节点
var kthLargest = function(root, k) {
let arr =[]
var helper = function(root){
if(!root) return null
helper(root.left)
arr.push(root.val)
helper(root.right)
return arr
}
arr = helper(root)
return arr.reverse()[k-1]
};
var kthLargest = function(root, k) {
let arr =[]
var helper = function(root){
if(!root) return null
helper(root.right)
arr.push(root.val)
helper(root.left)
return arr
}
arr = helper(root)
return arr[k-1]
};
9. 剑指 Offer 68 - II. 二叉树的最近公共祖先
var lowestCommonAncestor = function(root, p, q) {
if(!root||p === root ||q === root ) return root
let left = lowestCommonAncestor(root.left,p,q)
let right = lowestCommonAncestor(root.right,p,q)
if(!left) return right
else if(!right) return left
else return root
};
10. 剑指 Offer 68 - I. 二叉搜索树的最近公共祖先
- 二叉搜索树:若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值; 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值;
var lowestCommonAncestor = function(root, p, q) {
if(p.val<root.val&&q.val<root.val) return lowestCommonAncestor(root.left,p,q)
if(p.val>root.val&&q.val>root.val) return lowestCommonAncestor(root.right,p,q)
else return root
};
11. 剑指 Offer 07. 重建二叉树
var buildTree = function(preorder, inorder) {
if(!preorder.length) return null
let root = new TreeNode(preorder[0])
let index = inorder.indexOf(preorder[0])
root.left = buildTree(preorder.slice(1,index+1),inorder.slice(0,index))
root.right = buildTree(preorder.slice(index+1,preorder.length),inorder.slice(index+1,inorder.length))
return root
};
12. 剑指 Offer 26. 树的子结构 **
var isSubStructure = function(A, B) {
if(!A || !B) return false
else return helper(A,B)||isSubStructure(A.left,B)||isSubStructure(A.right,B)
};
var helper = function(A,B){
if(!B) return true
if(!A) return false
if(A.val !== B.val) return false
return helper(A.left,B.left)&&helper(A.right,B.right)
}
13. 剑指 Offer 34. 二叉树中和为某一值的路径 **
var pathSum = function(root, target) {
let res = []
if(!root) return res
let tmp = []
let sum = 0
const helper = function(root,target,sum,tmp){
tmp.push(root.val)
sum += root.val
if(sum === target && !root.left && !root.right){
res.push(tmp)
}
if(root.left) helper(root.left,target,sum,tmp.slice())
if(root.right) helper(root.right,target,sum,tmp.slice())
return res
}
return helper(root,target,sum,tmp)
};
14. 剑指 Offer 37. 序列化二叉树 **
// An highlighted block
var foo = 'bar';
栈、堆、队列
1. 剑指 Offer 09. 用两个栈实现队列
var CQueue = function() {
this.stackA = []
this.stackB = []
};
/**
* @param {number} value
* @return {void}
*/
//队尾插入
CQueue.prototype.appendTail = function(value) {
this.stackA.push(value)
};
/**
* @return {number}
*/
//队列头部删除
CQueue.prototype.deleteHead = function() {
let a = this.stackA.length
let b = this.stackB.length
if(!a&&!b) return -1
else if(b) return this.stackB.pop()
else{
while(a>0){
this.stackB.push(this.stackA.pop())
a--
}
return this.stackB.pop()
}
};
/**
* Your CQueue object will be instantiated and called as such:
* var obj = new CQueue()
* obj.appendTail(value)
* var param_2 = obj.deleteHead()
*/
2. 剑指 Offer 30. 包含min函数的栈
/**
* initialize your data structure here.
*/
var MinStack = function() {
this.stack = []
this.minstack = []
};
/**
* @param {number} x
* @return {void}
*/
MinStack.prototype.push = function(x) {
this.stack.push(x)
if(!this.minstack.length) this.minstack.push(x)
else if(x<=this.minstack[0]) this.minstack.unshift(x)
else this.minstack.push(x)
};
/**
* @return {void}
*/
MinStack.prototype.pop = function() {
let tmp = this.stack.pop()
if(tmp === this.minstack[0]){
this.minstack.shift()
}
};
/**
* @return {number}
*/
MinStack.prototype.top = function() {
return this.stack[this.stack.length-1]
};
/**
* @return {number}
*/
MinStack.prototype.min = function() {
return this.minstack[0]
};
/**
* Your MinStack object will be instantiated and called as such:
* var obj = new MinStack()
* obj.push(x)
* obj.pop()
* var param_3 = obj.top()
* var param_4 = obj.min()
*/
3. 剑指 Offer 59 - II. 队列的最大值 **没过
var MaxQueue = function() {
this.queue = []
this.maxQueue = []
};
/**
* @return {number}
*/
MaxQueue.prototype.max_value = function() {
if(!this.queue.length) return -1
else return this.maxQueue[0]
};
/**
* @param {number} value
* @return {void}
*/
MaxQueue.prototype.push_back = function(value) {
this.queue.push(value)
if(!this.maxQueue.length) this.maxQueue.unshift(value)
else if(value>=this.maxQueue[0]) this.maxQueue.unshift(value)
else this.maxQueue.push(value)
};
/**
* @return {number}
*/
MaxQueue.prototype.pop_front = function() {
if(!this.queue.length) return -1
let tmp = this.queue.shift()
if(tmp === this.maxQueue[0]) this.maxQueue.shift()
return tmp
};
/**
* Your MaxQueue object will be instantiated and called as such:
* var obj = new MaxQueue()
* var param_1 = obj.max_value()
* obj.push_back(value)
* var param_3 = obj.pop_front()
*/
4. 剑指 Offer 59 - I. 滑动窗口的最大值 **
递归
1. 剑指 Offer 10- II. 青蛙跳台阶问题
var numWays = function(n) {
let res =[]
let MAX = Math.pow(10,9)+7
res[0] = 1
res[1] = 1
for(let i =2;i<=n;i++){
res[i] = res[i-1] + res[i-2]
res[i] = res[i]%MAX
}
return res[n]
};
2. 剑指 Offer 10- I. 斐波那契数列
// An highlighted block
var fib = function(n) {
let res = []
res[0] = 0
res[1] = 1
for(let i = 2;i<n+1;i++){
res[i] = res[i-1] + res[i-2]
res[i] = res[i] % 1000000007
}
return res[n]
};
3. 剑指 Offer 16. 数值的整数次方
/**
* @param {number} x
* @param {number} n
* @return {number}
*/
var myPow = function(x, n) {
if(n === 0) return 1
if(n === 1) return x
if(n === -1) return 1/x
if(n%2 === 0){
let a = myPow(x,n/2)
return a*a
}else{
let b = myPow(x,(n-1)/2)
return x*b*b
}
};
动态规划
1. 剑指 Offer 42. 连续子数组的最大和
/**
* @param {number[]} nums
* @return {number}
*/
var maxSubArray = function(nums) {
let res = []
res[0] = nums[0]
let max = nums[0]
for(let i=1;i<nums.length;i++){
let tmp = Math.max(0,res[i-1])+nums[i]
res.push(tmp)
max = Math.max(max,tmp)
}
return max
};
2. 剑指 Offer 14- I. 剪绳子 **
var cuttingRope = function (n) {
if (n === 2) return 1
if (n === 3) return 2
if (n > 3) {
let dp = []
dp[1] = 1
dp[2] = 2
dp[3] = 3
for (let i = 4; i <= n; i++) {
dp[i] = 0
for (let j = 1; j <= n / 2; j++) {
dp[i] = Math.max(dp[i], dp[j] * dp[i - j])
}
}
console.log(dp)
return dp[n]
}
}