剑指offer 自己瞎写版

167 阅读2分钟

基本也都是看着别人的,经典的,自己敲一遍,做一下巩固,以后多看看,共勉

返回数组中重复最多的数字,重复了多少次

const arr = [1,3,5,8,9,3,2,5,6,5,3,1,2,2,3,3,4,4,3,3,3,3,7,0]
function searchMaxSame(arr=[]) {
  if (!arr || !arr.length) return arr
  // 任何函数,尤其可能导致死循环的,一定要兜底,养成这个编写习惯!!!
  let sameObj = {}
  let maxCount = 0
  let maxNum = 0
  for (let i = 0; i < arr.length; i++) {
    const item = arr[i]
    if (!sameObj[item]) {
      sameObj[item] = [item]
    } else {
      sameObj[item].push(item)
      if (maxCount < sameObj[item].length) {
        maxCount = sameObj[item].length
        maxNum = item
      }
    }
  }
  return {
    maxCount,
    maxNum
  }
}
console.log('searchMaxSame', searchMaxSame(arr.slice()))

在一个 n * m 的二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个高效的函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。

// 暴力解法 双层循环
const matrix = [
  [1, 4, 7, 11, 15],
  [2, 5, 8, 12, 19],
  [3, 6, 9, 16, 22],
  [10, 13, 14, 17, 24],
  [18, 21, 23, 26, 30],
];
function findNumIn2Darr(arr=[], target) {
  if (!arr || !arr.length || !target) return false
  for (let i = 0; i < arr.length; i++) {
    const item = arr[i]
    for (let j = 0; j < item.length; j++) {
      console.log('item[j]', item[j])
      if (item[j] === target) {
        return true
      }
    }
  }
  return false
}
// 解法二 
function findNumIn2Darr2(arr=[], target) {
  if (!arr || !arr.length || !target) return false
  let rows = arr.length
  let columns = arr[0].length
  let row = 0;
  let column = columns - 1
  while(row < rows && column >= 0) {
    let item = arr[row][column]
    if (target === item) {
      return true
    } else if (target > item) {
      row++
    } else {
      column--
    }
  }
  return false
}
console.log('findNumIn2Darr', findNumIn2Darr(matrix.slice(), 5))
console.log('findNumIn2Darr2', findNumIn2Darr2(matrix.slice(), 21))

输入一个链表的头节点,从尾到头反过来返回每个节点的值(用数组返回)

function reversePrint(head) {
  if (!head) return head
  const result = []
  let node = head
  while(node !== null) {
    result.unshift(node.val)
    node = node.next
  }
  return result
}

输入某二叉树的前序遍历和中序遍历的结果,请重建该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。

//前序遍历 preorder = [3,9,20,15,7]
//中序遍历 inorder = [9,3,15,20,7]
function TreeNode(val) {
    this.val = val
    this.left = this.right = null
}
function buildTree(preorder, inorder) {
    if (!preorder.length) return
    const rootVal = preorder[0] // 前序 根左右,第一项就是根节点 
    const curNode = new TreeNode(rootVal) // 创建根节点
    const rootIndex = inorder.indexof(rootVal) // 获取根节点在中序 左根右 中的索引
    curNode.left = buildTree(preorder.slice(1, rootIndex + 1), inorder.slice(0, rootIndex))
    curNode.right = buildTree(preorder.slice(rootIndex + 1), inorder.slice(rootIndex + 1))
    return curNode
}

用两个栈实现一个队列。队列的声明如下,请实现它的两个函数 appendTail 和 deleteHead,分别完成在队列尾部插入整数和在队列头部删除整数的功能。(若队列中没有元素,deleteHead 操作返回 -1 )

function CQueue(){
    this.firstStack = []
    this.secondStack = []
}
CQueue.prototype.appendTail = function(val) {
    this.firstStack.push(val)
}
CQueue.prototype.deledeHead = function() {
    if (this.secondStack.length) return this.secondStack.pop()
    for (let i = 0; i < this.firstStack.length; i++) {
        this.secondStack.push(this.firstStack.pop())
    }
    if (this.secondStack.length) {
        return this.secondStack.pop()
    } else {
        return -1
    }
}

写一个函数,输入 n ,求斐波那契(Fibonacci)数列的第 n 项(即 F(N))。斐波那契数列的定义如下, 斐波那契数列由 0 和 1 开始,之后的斐波那契数就是由之前的两数相加而得出。答案需要取模 1e9+7(1000000007),如计算初始结果为:1000000008,请返回 1。

function fib(n) {
    if (n <= 2) {
        return 2
    }
    let p = 0, q = 0, r = 1
    for (let i = 2; i < n; i++){
        p = q
        q = r
        r = (p + q) % 1000000007
    }
    return r
}

青蛙跳,每次可跳1或2

function fib(n) {
    let p = 0, q = 0, r = 1, k = 0
    while(k < n) {
        k++
        p = q
        q = r
        r = (p + q) % 1000000007
    }
    return r
}

割绳子得最大数

function cuttingRope(n) {
    if (n < 4) return n - 1
    let a = Math.floor(n / 3)
    let b = n % 3
    switch(b) {
        case 0:
            return Math.pow(3, a)
        case 1:
            return Math.pow(3, a - 1) * 4
        case 2:
            return Math.pow(3, a) * 2
    }
}
// 2
function cuttingRope(n){
    if (n < 4) return n - 1
    let res = 1
    while(n > 4) {
        n -= 3
        res * 3
    }
    return res * num
}

计算二进制中1的数量

function numLen(n) {
    return n.toString(2).split('0').join('').length
}
function getNumLen(n) {
    return n.toString(2).match(/1/g).length || 0
}

手动实现 Math.pow

function myPow(x, n) {
    if (n === 0) return 1
    if (n < 0) return 1 / (x * myPow(x, -n - 1))
    return n % 2 === 0 ? myPow(x, n / 2) : x * myPow(x, n - 1)
}

给定 n,返回n位数最大的数

function getMaxNum(n) {
    let arr = []
    let i = 0
    while(arr.length <= n) {
        i++
        arr.push(i)
    }
    return {
        maxNum: arr[arr.length - 1]
        arr
    }
}

给定数组,返回format后的数据

// 条件,pid为0,代表跟节点,有且只有一个,后续pid和id相同的item,代表id下的children, id 唯一
let arr = [
  {id: 1, name: '部门1', pid: 0},
  {id: 2, name: '部门2', pid: 1},
  {id: 3, name: '部门3', pid: 1},
  {id: 4, name: '部门4', pid: 3},
  {id: 5, name: '部门5', pid: 4},
  {id: 6, name: '部门5', pid: 2},
  {id: 7, name: '部门5', pid: 4},
]
function arr2Tree(arr) {
    let result = []
    let map = {}
    for (let item of arr) {
        let { id, pid } = item
        if (!map[id]) {
            map[id] = {
                ...item,
                children: []
            }
        }
        const treeItem = map[id]
        if (pid === 0) {
            result.push(treeItem)
        } else {
            if (!map[pid]) {
                map[pid] = {
                    children: []
                }
            }
            map[pid].children.push(treeItem)
        }
    }
    return result
}

给定一个列表表头,某节点val,删除这个节点

function deleteNode(head, val) {
    if (head.val = val) return head.next
    let prev = head
    let next = prev.next
    while(next) {
        if (next.val === val) {
            prev.next = next.next
            break;
        }
        prev = next
        next = next.next
    }
    return next
}

给定一个数组, 奇数在前,偶数在后

function reverseNum(arr) {
    if (!arr || arr.length <= 1) return arr
    let i = 0
    ler newArr = []
    while(i < arr.length) {
        if (arr[i] % 2) {
            newArr.unshift(arr[i])
        } else {
            newArr.push(arr[i])
        }
        i++
    }
    return newArr
}
// 2.
function reverseNum(arr) {
    if (!arr || arr.length <= 1) return arr
    return arr.sort((a, b) => (b % 2) - (a % 2))
}

反转链表

function reverseLink(head) {
    let prev = null
    let cur = head
    while(cur) {
        const next = cur.next
        cur.next = prev
        prev = cur
        cur = next
    }
    return prev
}

合并两个列表,要求从小到大排列

[2, 3, 4] [1, 2, 3] --> [1, 2, 2, 3, 3, 4]
function mergeTwoList(l1, l2) {
    if (!l1) return l2
    if (!l2) return l1
    if (l1.val < l2.val) {
        l1.next = mergeTwoList(l1.next, l2)
        return l1
    } else {
        l2.next = mergeTwoList(l1, l2.next)
        return l2
    }
}

给定一个二叉树,判断另一个二叉树是否属于第一个

function isSubStrict(a, b) {
    if (!a || !b) return false
    return isSame(a, b) || isSubStrict(a.left, b) || isSubstrict(a.right, b)
}
function isSame(a, b) {
    if (!b) return true
    if (!a) return false
    if (a.val !== b.val) return false
    return isSame(a.left , b.lengt) && isSame(a.right, b.right)
}

给定一个二叉树,获取二叉树镜像

function TreeNode(head) {
    this.val = head.val
    this.left = null
    this.right = null
}
function mirrorTree(head) {
    if (!head) return null
    let newTree = new TreeNode(head[0])
    let left = head.left
    let right = head.right
    newTree.left = right
    newTree.right = left
    return newTree
}

判断二叉树是否是对称二叉树

function isSymmetric(root) {
    return !root ? true : recur(root.left, root.right)
}
function recur(l, r) {
    if (!l && !r) return true // 两边都没有,也是相同
    if (!l || !r || l.val !== r.val) return false
    return recur(l.left. r.right) && recur(l.right, r.left)
}

输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字。

// 输入:matrix = [[1,2,3,4],[5,6,7,8],[9,10,11,12]]
// 输出:[1,2,3,4,8,12,11,10,9,5,6,7]
function spiralOrder(arr) {
    if (!arr || !arr.length) return arr
    let newArr = [], rows = arr.length, columns = arr[0].length, l = 0, t = 0, r = columns - 1, b = rows -1, size = rows * column;
    while(newArr.length < size) {
        for (let i = l; i <= r; i++) {
            newArr.push(arr[t][i])
        }
        t++
        for (let i = t; i <= b; i++) {
            newArr.push(arr[i][r])
        }
        if (newArr.length === size) break;
        r--
        for (let i = r; i >= l; i--) {
            newArr.push(arr[b][i])
        }
        b--
        for (let i = b; i >= t; i--) {
            newArr.push(arr[i][l])
        }
        l++
     }
     return newArr
}

定义栈的数据结构,请在该类型中实现一个能够得到栈的最小元素的 min 函数在该栈中,调用 min、push 及 pop 的时间复杂度都是 O(1)。

// MinStack minStack = new MinStack(); 
// minStack.push(-2); 
// minStack.push(0); 
// minStack.push(-3); 
// minStack.min(); --> 返回 -3. 
// minStack.pop(); 
// minStack.top(); --> 返回 0. 
// minStack.min(); --> 返回 -2.
function MinStack() {
    this.stack = []
    this.minStack = [Infinity]
}
MinStack.prototype.push = fucnt