3.29-4.17刷题记录

2022.3.29

一、 LRU缓存淘汰算法

面试题 16.25. LRU 缓存
剑指 Offer II 031. 最近最少使用缓存
/**
 * @param {number} capacity
 */
var LRUCache = function(capacity) {
    this.capacity = capacity;
    this.map = new Map();
};

/** 
 * @param {number} key
 * @return {number}
 */
LRUCache.prototype.get = function(key) {
    // 当值存在时
    if(this.map.has(key)){
        const temp = this.map.get(key);
        this.map.delete(key);
        this.map.set(key, temp);
        return temp;
    }
    else {
        return -1;
    }

};

/** 
 * @param {number} key 
 * @param {number} value
 * @return {void}
 */
LRUCache.prototype.put = function(key, value) {
    // 当值存在,被访问时
    if(this.map.has(key)){
        this.map.delete(key);
    }
    this.map.set(key,value);
    if(this.map.size > this.capacity) {
        this.map.delete(this.map.keys().next().value);
    }
};

/**
 * Your LRUCache object will be instantiated and called as such:
 * var obj = new LRUCache(capacity)
 * var param_1 = obj.get(key)
 * obj.put(key,value)
 */

2022、3、30

剑指 Offer 36. 二叉搜索树与双向链表

输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的循环双向链表。要求不能创建任何新的节点,只能调整树中节点指针的指向。

// ac地址:https://leetcode-cn.com/problems/er-cha-sou-suo-shu-yu-shuang-xiang-lian-biao-lcof/
// 原文地址:https://xxoo521.com/2020-02-06-btree-link/

/**
 * @param {Node} root
 * @return {Node}
 */
var treeToDoublyList = function(root) {
    if (!root) {
        return;
    }
    let head = null;
    let pre = head;
    inorder(root);
    // 完成中序遍历后,pre指向了最后一个节点
    // 将其闭合成环状结构
    head.left = pre;
    pre.right = head;
    return head;

    /**
     * @param {Node} node
     */
    function inorder(node) {
        if (!node) return;
        // 遍历左子树
        inorder(node.left, pre);

        // 处理当前节点
        if (!pre) {
            // 遍历到最左边节点,此时节点就是双向链表的head
            head = node;
        } else {
            pre.right = node;
        }
        node.left = pre;
        pre = node;

        // 遍历右子树
        inorder(node.right, pre);
    }
};

作者:xin-tan
链接:https://leetcode-cn.com/problems/er-cha-sou-suo-shu-yu-shuang-xiang-lian-biao-lcof/solution/zhong-xu-bian-li-zhuan-hua-er-cha-sou-suo-shu-di-g/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

2022.3.31

剑指 Offer II 048. 序列化与反序列化二叉树
var serialize = function(root) {
    return rserialize(root, '');
};

var deserialize = function(data) {
    const dataArray = data.split(",");
    return rdeserialize(dataArray);
};

const rserialize = (root, str) => {
    if (root === null) {
        str += "None,";
    } else {
        str += root.val + '' + ",";
        str = rserialize(root.left, str);
        str = rserialize(root.right, str);
    }
    return str;
}

const rdeserialize = (dataList) => {
    if (dataList[0] === "None") {
        dataList.shift();
        return null;
    }

    const root = new TreeNode(parseInt(dataList[0]));
    dataList.shift();
    root.left = rdeserialize(dataList);
    root.right = rdeserialize(dataList);

    return root;
}

/**
 * Definition for a binary tree node.
 * function TreeNode(val) {
 *     this.val = val;
 *     this.left = this.right = null;
 * }
 */

/**
 * Encodes a tree to a single string.
 *
 * @param {TreeNode} root
 * @return {string}
 */

var serialize = function(root) {
    const rserialize = (root, str) => {
        if (root === null) {
            str += "None,";
        } else {
            str += root.val + '' + ",";
            str = rserialize(root.left, str);
            str = rserialize(root.right, str);
        }
        console.log(str)
        return str;
    }
    return rserialize(root, '');
};

/**
 * Decodes your encoded data to tree.
 *
 * @param {string} data
 * @return {TreeNode}
 */
var deserialize = function(data) {
    let arr = data.split(",");
    console.log(arr)
    
    // const detraverse = (arr) => {
    //     // if(arr.length === 0) return null;

    //     // 列表的最左侧就是根节点
    //     let first = nodes.shift();
    //     if (first === NULL) return null;

    //     let root = new TreeNode(first);

    //     root.left = detraverse(root);
    //     root.right = detraverse(root);

    //     return root;
    // }

    // return detraverse(arr)
};

/**
 * Your functions will be called as such:
 * deserialize(serialize(root));
 */

2022.4.3

一、 297. 二叉树的序列化与反序列化

/**
 * Definition for a binary tree node.
 * function TreeNode(val) {
 *     this.val = val;
 *     this.left = this.right = null;
 * }
 */

/**
 * Encodes a tree to a single string.
 *
 * @param {TreeNode} root
 * @return {string}
 */
var serialize = function(root) {
    let str = '';
    const rserialize = (root) => {
        if (root === null) {
        str += "None,";
    } else {
        str += root.val + '' + ",";
        str = rserialize(root.left, str);
        str = rserialize(root.right, str);
    }
    return str;
    }
    // console.log(reSerialize(root))
    return rserialize(root)
};

/**
 * Decodes your encoded data to tree.
 *
 * @param {string} data
 * @return {TreeNode}
 */
var deserialize = function(data) {
    // console.log(data)
    let arr = data.split(",");
    // console.log(arr)
    
    const detraverse = (arr) => {
        // console.log(arr)
        if (arr[0] === "None") {
        arr.shift();
            return null;
        }

        const root = new TreeNode(parseInt(arr[0]));
        arr.shift();
        root.left = detraverse(arr);
        root.right = detraverse(arr);
        return root;
    }

    return detraverse(arr)
};

/**
 * Your functions will be called as such:
 * deserialize(serialize(root));
 */

记录序列化到底写过什么闹坑写法

我好像回了,但没完全学会,大冤种

/**
 * Definition for a binary tree node.
 * function TreeNode(val) {
 *     this.val = val;
 *     this.left = this.right = null;
 * }
 */

/**
 * Encodes a tree to a single string.
 *
 * @param {TreeNode} root
 * @return {string}
 */
 // 序列化
var serialize = function(root) {
    let res ='';

    let preserialize = (root, res) =>{
        if (root === null){
            res.concat('NULL',',');
            return;
        }
        res.concat(root.val, ',');
        preserialize(root.left, res);
        preserialize(root.right, res);
    }
    preserialize(root, res);
    return res;
};

/**
 * Decodes your encoded data to tree.
 *
 * @param {string} data
 * @return {TreeNode}
 */
var deserialize = function(data) {
    // 字符串转换成列表
    let preorder = data.split(' ').map(item => {
        return Number.parseInt(item);
    })
    let nodes = [...preorder];
    const predeserialize = (nodes) => {
        const first = nodes.shift();
        if(first === null) return null;
        let root = new TreeNode(first);

        root.left = predeserialize(nodes);
        root.right = predeserialize(nodes);

        return root;
    }


    return predeserialize(nodes);
};

/**
 * Your functions will be called as such:
 * deserialize(serialize(root));
 */
  • 突然看到困扰我4.1的那个问题:

    image-20220403111202039

二、 449. 序列化和反序列化二叉搜索树

序列化是将数据结构或对象转换为一系列位的过程,以便它可以存储在文件或内存缓冲区中,或通过网络连接链路传输,以便稍后在同一个或另一个计算机环境中重建。

设计一个算法来序列化和反序列化 二叉搜索树 。 对序列化/反序列化算法的工作方式没有限制。 您只需确保二叉搜索树可以序列化为字符串,并且可以将该字符串反序列化为最初的二叉搜索树。

编码的字符串应尽可能紧凑。

/**
 * Definition for a binary tree node.
 * function TreeNode(val) {
 *     this.val = val;
 *     this.left = this.right = null;
 * }
 */

/**
 * Encodes a tree to a single string.
 *
 * @param {TreeNode} root
 * @return {string}
 */
 // 序列化
var serialize = function(root) {
    let str = ''
    const reSerialize = (root) => {
        if(root === null){
            str+="None,";
        }else {
            str += root.val+',';
            reSerialize(root.left);
            reSerialize(root.right);
           
        }
        return str;
        
    }
    // console.log(reSerialize(root))
    return reSerialize(root)
};

/**
 * Decodes your encoded data to tree.
 *
 * @param {string} data
 * @return {TreeNode}
 */
var deserialize = function(data) {
    console.log(data)
    let arr = data.split(",");
    console.log(arr)

    const reDeserialize =(arr)=>{
        let head = arr.shift();
        if(head === "None") {
            return null;
        }

        const root = new TreeNode(parseInt(head));
        root.left = reDeserialize(arr);
        root.right = reDeserialize(arr);
        return root;

    }
    return reDeserialize(arr)
};

/**
 * Your functions will be called as such:
 * deserialize(serialize(root));
 */

image-20220403111938095

三、 剑指 Offer 37. 序列化二叉树

请实现两个函数,分别用来序列化和反序列化二叉树。

你需要设计一个算法来实现二叉树的序列化与反序列化。这里不限定你的序列 / 反序列化算法执行逻辑,你只需要保证一个二叉树可以被序列化为一个字符串并且将这个字符串反序列化为原始的树结构。

提示:输入输出格式与 LeetCode 目前使用的方式一致,详情请参阅 LeetCode 序列化二叉树的格式。你并非必须采取这种方式,你也可以采用其他的方法解决这个问题。

四、 剑指 Offer II 048. 序列化与反序列化二叉树

2022.4.5

一、 556. 下一个更大元素 III

给你一个正整数 n ,请你找出符合条件的最小整数,其由重新排列 n 中存在的每位数字组成,并且其值大于 n 。如果不存在这样的正整数,则返回 -1 。

注意 ,返回的整数应当是一个 32 位整数 ,如果存在满足题意的答案,但不是 32 位整数 ,同样返回 -1 。

/**
 * @param {number} n
 * @return {number}
 */
// function nextGreaterElement(n) {
//   let res = 0
//   let q = []
//   let str = Array.from(String(n))//字符串数组

//   for (let i = str.length - 1; i >= 0; i--) {
//     if (q.length === 0 || str[i] >= q[q.length - 1]) q.push(str[i]) ;
//     else {
//       let count = 0
//       // 出栈,记录出栈的位数
//       while (q.length !== 0 && str[i] < q[q.length - 1]) {
//         q.pop()
//         count++
//       }
//       [str[i], str[i + count]] = [str[i + count], str[i]]  // swap元素
//       res = parseInt(
//         str.slice(0, i + 1).join('') +
//         str.slice(i + 1).reverse().join('')
//       ) // 反转右边
//       return res >= 2 ** 31 - 1 ? -1 : res
//     }
//   }

//   return -1
// }

/**
 * @param {number} n
 * @return {number}
 */
// var nextGreaterElement = function(n) {
//     let s = ('' + n).split('');
//     let i = s.length - 2;
//     while (s[i] >= s[i + 1]) i--; // 从右开始,找第一个严格降序的数字
//     if (i < 0) return -1; // 不存在,返回-1
//     let j = s.length - 1;
//     while (s[j] <= s[i]) j--; // 从右开始,找到第一个比上一步找到数字大的
//     [ s[i], s[j] ] = [ s[j], s[i] ]; // 换位
//     let res = parseInt(s.slice(0, i + 1).join('') + s.slice(i + 1).reverse().join('')); // 反转右边
//     return res >= 2 ** 31 - 1 ? -1 : res;
// };

/**
 * @param {number} n
 * @return {number}
 */
var nextGreaterElement = function(n) {
    // 把 n 字符串化
    const nStr = n + ''
    const len = nStr.length
    // 我们从后往前遍历,找到第一个比他后面的最大数字小的一个数字,这个位置的数字就是我们要更换的数字
    let max = nStr[len - 1]

    // 已经遍历过的数字组成的数字,当我们已经更换的数字更换了之后,这个数组就保存更换数字之后的所有数字,我们取得这个数组能组成的数字的最小值拼接在后面即可
    const after = [max]

    // 需要更换的数字的位置
    let before = -1
    for (let i = len - 2; i >= 0; i--) {
        if (nStr[i] < max) {
            before = i
            break;
        } else {
            max = nStr[i]
            after.unshift(nStr[i])
        }
    }

    // 当没有需要更换的数字,表示重排找不到比 n 最大的数字了,返回 -1
    if (before < 0) return -1

    // 保存需要更换的数字
    let num = nStr[before]

    // after数组从小到大排序,到时候直接拼接就是能组合的最小数字
    after.sort((a, b) => a - b)

    // 遍历after数组,找到第一个比 num 大的数,来和 num 做交换
    for (let i = 0, len = after.length; i < len; i++) {
        if (after[i] > num) {
            const temp = after[i]
            after[i] = num
            num = temp
            break
        }
    }

    // 拼接数字
    // 需要更换的数字之前 + 更换的后数字 + 更换的数字位置之后的所有数字能组成的最小数字
    const ret = +(nStr.slice(0, before) + num + after.join(''))
    
    return ret <= (2 ** 31 - 1) ? ret : -1
};



image-20220405221152803

二、 232. 用栈实现队列

var MyQueue = function() {
    this.inStack = [];
    this.outStack = [];
};

MyQueue.prototype.push = function(x) {
    this.inStack.push(x);
};

MyQueue.prototype.pop = function() {
    if (!this.outStack.length) {
        this.in2out();
    }
    return this.outStack.pop();
};

MyQueue.prototype.peek = function() {
    if (!this.outStack.length) {
        this.in2out();
    }
    return this.outStack[this.outStack.length - 1];
};

MyQueue.prototype.empty = function() {
    return this.outStack.length === 0 && this.inStack.length === 0;
};

MyQueue.prototype.in2out = function() {
    while (this.inStack.length) {
        this.outStack.push(this.inStack.pop());
    }
};

image-20220406211847647

2022.4.6

一、 剑指 Offer II 018. 有效的回文

给定一个字符串 s ,验证 s 是否是 回文串 ,只考虑字母和数字字符,可以忽略字母的大小写。

本题中,将空字符串定义为有效的 回文串

/**
 * @param {string} s
 * @return {boolean}
 */
var isPalindrome = function(s) {
    let str = s.toLowerCase();
    let arr = [];
    for(let i = 0 ;i < str.length; i++) {
        if (str.charCodeAt(i) >= 97 && str.charCodeAt(i) <= 122)
            arr.push(str[i])
        if(str.charCodeAt(i) >= 48 && str.charCodeAt(i) <= 57)
            arr.push(str[i]);
    }
    if (arr === []) return true
    str = arr.join('')
    str2 = arr.reverse().join('')
    if(str === str2) return true
    return false
};

二、 剑指 Offer II 027. 回文链表

三、 234. 回文链表

/**
 * 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 {boolean}
 */
var isPalindrome = function(head) {
    let left = 0;
    const res = [];
    let sign = true;
    while(head !== null){
        res.push(head.val);
        head = head.next;
    }
    // console.log(res)
    let right = res.length-1;
    while(left < right) {
        if(res[left]!== res[right]) {
            sign = false
        }
        left++;
        right--;
    }
    return sign
};

2022.4.7 344. 反转字符串

编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组 s 的形式给出。

不要给另外的数组分配额外的空间,你必须原地修改输入数组、使用 O(1) 的额外空间解决这一问题。

/**
 * @param {character[]} s
 * @return {void} Do not return anything, modify s in-place instead.
 */
var reverseString = function(s) {
    // console.log(s.reverse())
    return s.reverse()
};

2022.4.8 剑指 Offer II 080. 含有 k 个元素的组合

给定两个整数 nk,返回 1 ... n 中所有可能的 k 个数的组合。

  1. /**
     * @param {number} n
     * @param {number} k
     * @return {number[][]}
     */
    var combine = function(n, k) {
        const track = [];
        const result = [];
        const backtrack = (start)=> {
            if(track.length === k){
                result.push(track.slice());
            }
            for(let i = start ;i < n ;i++){
                track.push(i+1);
                backtrack(i+1);
                track.pop()
            }
        }
        backtrack(0)
        return result
    };
    
  2. image-20220412180037165

2022.4.9

剑指 Offer II 079. 所有子集

/**
 * @param {number[]} nums
 * @return {number[][]}
 */
var subsets = function(nums) {
    let result = [];
    let res = [];
    const backtracking = (start) => {
        result.push(res.slice())
        for(let i = start; i < nums.length; i++){
            res.push(nums[i]);
            backtracking(i+1);
            res.pop()
        }
    }
    backtracking(0)
    return result;
};

image-20220409223139307

2022.4.12

一、 90. 子集 II
/**
 * @param {number[]} nums
 * @return {number[][]}
 */
var subsetsWithDup = function(nums) {
    const result = [];
    const path = []
    const sortNums = nums.sort((a,b) => {
        return a-b
    }) 
    function backtracing(startIndex, sortNums) {
        result.push(path.slice(0))
        if(startIndex > nums.length - 1) {
            return 
        }
        for(let i = startIndex; i < nums.length; i++) {
            // 使用过的不重复添加
            if(i > startIndex && nums[i] === nums[i-1]) {
                continue
            }
            path.push(nums[i])
            backtracing(i+1, sortNums)
            path.pop()
        }
    }
    backtracing(0, sortNums)
    return result
};

image-20220412225204215

二、37. 解数独
var solveSudoku = function(board) {
    function isValid(row, col, val, board) {
        let len = board.length
        // 行不能重复
        for(let i = 0; i < len; i++) {
            if(board[row][i] === val) {
                return false
            }
        }
        // 列不能重复
        for(let i = 0; i < len; i++) {
            if(board[i][col] === val) {
                return false
            }
        }
        let startRow = Math.floor(row / 3) * 3
        let startCol = Math.floor(col / 3) * 3

        for(let i = startRow; i < startRow + 3; i++) {
            for(let j = startCol; j < startCol + 3; j++) {
                if(board[i][j] === val) {
                    return false
                }
            }
        }

        return true
    }

    function backTracking() {
        for(let i = 0; i < board.length; i++) {
            for(let j = 0; j < board[0].length; j++) {
                if(board[i][j] !== '.') continue
                for(let val = 1; val <= 9; val++) {
                    if(isValid(i, j, `${val}`, board)) {
                        board[i][j] = `${val}`
                        if (backTracking()) {
                            return true
                        }
                        
                        board[i][j] = `.`
                    }
                }
                return false
            }
        }
        return true
    }
    backTracking(board)
    return board
    
};

2022.4.13

22. 括号生成
var generateParenthesis = function (n) {
    let set = new Set(['()']);
    for (let c = 2; c <= n; c++) {
        let nextSet = new Set();
        for (const s of set) {
            for (let j = 0; j <= s.length; j++) {
                nextSet.add(s.slice(0, j) + '()' + s.slice(j));
            }
        }
        set = nextSet;
    }
    return [...set];
};

var generateParenthesis = function (n) {
  const res = [];

  const dfs = (lRemain, rRemain, str) => { // 左右括号所剩的数量,str是当前构建的字符串
    if (str.length == 2 * n) { // 字符串构建完成
      res.push(str);           // 加入解集
      return;                  // 结束当前递归分支
    }
    if (lRemain > 0) {         // 只要左括号有剩,就可以选它,然后继续做选择(递归)
      dfs(lRemain - 1, rRemain, str + "(");
    }
    if (lRemain < rRemain) {   // 右括号比左括号剩的多,才能选右括号
      dfs(lRemain, rRemain - 1, str + ")"); // 然后继续做选择(递归)
    }
  };

  dfs(n, n, ""); // 递归的入口,剩余数量都是n,初始字符串是空串
  return res;
};

/**
 * @param {number} n
 * @return {string[]}
 */
var generateParenthesis = function(n) {
    if(n===0) return {}
    // 记录所有合法的括号组合
    const res = [];
    // 回溯过程中的路径
    const track = [];
    // 可用的左括号和右括号数量初始化为n
    backtrack(n, n, track, res);
    return res;

};

// 可用的左括号数量为left个,可用的右括号数量为right
const backtrack = (left, right, track, res) => {
    // 数量小于0 不合法
    if (left < 0 || right < 0){
        return;
    }
    // 左括号剩下的多,不合法
    if (right < left) return;
    // 当所有 括号都恰好用完,得到一个合法的括号组合
    if (left === 0 && right === 0) {
        res.push(track)
        return;
    }
    // 尝试添加一个左括号
    track.push('(');
    backtrack(left-1, right, track, res);
    track.pop(); // 撤销

    // 添加一个有右括号
    track.push(')');   // 选择
    backtrack(left, right-1, track, res)
    track.pop()
}

2022.4.17

111. 二叉树的最小深度
var minDepth = function(root) {
    if(root == null) {
        return 0;
    }
    if(root.left == null && root.right == null) {
        return 1;
    }
    let ans = Number.MAX_SAFE_INTEGER;
    if(root.left != null) {
        ans = Math.min(minDepth(root.left), ans);
    }
    if(root.right != null) {
        ans = Math.min(minDepth(root.right), ans);
    }
    return ans + 1;
};

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值