DAILY DOCDAILY DOC
Rust
Node
Notes
Ubuntu
Leetcode
  • it-tools
  • excalidraw
  • linux-command
Rust
Node
Notes
Ubuntu
Leetcode
  • it-tools
  • excalidraw
  • linux-command
  • Array

    • 数组
    • 二分查找
    • moveZeros
  • Dynamic-programming

    • 动态规划
  • 刷题指南
  • String

    • 字符串
  • bitwise-operator

    • 位运算符
  • heap
  • history

    • [1014] 最佳观光组合
    • [1022] 从根到叶的二进制数之和
    • [104] 二叉树的最大深度
    • [11] 盛最多水的容器
    • [110] 平衡二叉树
    • [1227] 飞机座位分配概率
    • [129] 求根节点到叶节点数字之和
    • [1306] 跳跃游戏 III
    • [148] 排序链表
    • 155.最小栈
    • [165] 比较版本号
    • 1763. 最长的美好子字符串
    • [1870] 准时到达的列车最小时速
    • [199] 二叉树的右视图
    • [21] 合并两个有序链表
    • 215.数组中的第 k 个最大元素
    • [2306] 公司命名
    • [234] 回文链表
    • [2516] 每种字符至少取 K 个
    • [316] 去除重复字母
    • [3171] 找到按位或最接近 K 的子数组
    • [322] 零钱兑换
    • [41] 缺失的第一个正数
    • [44] 通配符匹配
    • [494] 目标和
    • [509] 斐波那契数
    • [518] 零钱兑换 II
    • [62] 不同路径
    • [676] 实现一个魔法字典
    • 70 爬楼梯
    • [718] 最长重复子数组
    • [78] 子集
    • [82] 删除排序链表中的重复元素 II
    • [871] 最低加油次数
    • [88] 合并两个有序数组
    • [887] 鸡蛋掉落
    • 958.二叉树的完全性检验
    • [98] 验证二叉搜索树
    • [983] 最低票价
    • leetcode practice
    • 约瑟夫问题
    • 移除重复节点
  • linked-list

    • 706. 设计哈希映射
    • 链表
  • stack

    • stack
  • tree

    • Tree Traversal
    • 二叉树的最近公共祖先
    • 二叉树
    • 题目
  • leetCode 刷题
  • 回溯
  • 排序算法

刷题指南

参考文档:

  1. https://oi-wiki.org/basic/
  2. hello-algo

数据结构遍历方式

数组 线性迭代

function traverse(list) {
    for (let i = 0; i < list.length; i++) {
        const element = array[i];
        //
    }
}

链表 递归 迭代

linkedList

class LinkNode {
    constructor(val, next) {
        this.val = val;
        this.next = next;
    }
}

function traverse(node) {
    for (let i = 0; i != null; i = i.next) {
        const val = node.val;
        //
    }
}

function traverse(node) {
    // 前序 node.val
    traverse(node.next);
    // node.val
    // 后序
}

二叉树递归遍历

binaryTree

class TreeNode {
    constructor(val, left, right) {
        this.val = val;
        this.left = left;
        this.right = right;
    }
}

function traverse(node) {
    // 前序 console.log(node.val)
    traverse(node.left);
    // 中序 console.log(node.val)
    traverse(node.right);
    // 后序 console.log(node.val)
}

dp 数组遍历方式

正向遍历

for (let i = 0; i < len; i++) {
    for (let j = 0; j < len; j++) {
        nums[i][j];
    }
}

反向遍历

for (let i = len - 1; i >= 0; i--) {
    for (let j = len - 1; j >= 0; j--) {
        nums[i][j];
    }
}

斜向遍历

for (let l = 2; l <= len; l++) {
    for (let i = 0; i <= len - l; i++) {
        let j = l + i - 1;
        nums[i][j];
    }
}

或者

for (let l = 1; l < len; l++) {
    for (let i = 0; i < len - l; i++) {
        let j = l + i;
        nums[i][j];
    }
}

反着遍历

for (let i = len - 2; l >= 0; l--) {
    for (let j = i + 1; j < len; j++) {
        nums[i][j];
    }
}

二分查找

寻找一个数

递归实现
/**
 * @param {number[]} nums - 有序数组
 * @param {number} target - 目标值
 * @return {number} - 目标值的索引,如果未找到则返回 -1
 */
function binarySearch(nums, target) {
    return traverse(nums, target, 0, nums.length - 1);
}

function traverse(nums, target, left, right) {
    if (left > right) {
        return -1;
    }

    const mid = Math.floor((left + right) / 2);

    if (nums[mid] === target) {
        return mid;
    } else if (nums[mid] < target) {
        return traverse(nums, target, mid + 1, right);
    } else {
        return traverse(nums, target, left, mid - 1);
    }
}
迭代实现
/**
 * @param {number[]} nums - 有序数组
 * @param {number} target - 目标值
 * @return {number} - 目标值的索引,如果未找到则返回 -1
 */
function binarySearchIterative(nums, target) {
    let left = 0;
    let right = nums.length - 1;

    while (left <= right) {
        const mid = Math.floor((left + right) / 2);

        if (nums[mid] === target) {
            return mid;
        } else if (nums[mid] < target) {
            left = mid + 1;
        } else {
            right = mid - 1;
        }
    }

    return -1;
}

寻找左侧边界的二分搜索

尽可能移动 right ,结束检测 left 值

/* @param {number[]} nums - 有序数组
 * @param {number} target - 目标值
 * @return {number} - 目标值的左侧边界索引
 */
function leftBoundBinarySearch(nums, target) {
    let left = 0;
    let right = nums.length - 1;

    while (left <= right) {
        const mid = Math.floor((left + right) / 2);
        // 先判断 < 情况,否则都移动 right
        if (nums[mid] < target) {
            left = mid + 1;
        } else {
            right = mid - 1;
        }
    }

    // 检查 left 是否越界以及 nums[left] 是否为 target
    if (left >= nums.length || nums[left] !== target) {
        return -1; // 如果未找到目标值,则返回 -1
    }

    return left; // 返回左侧边界索引
}

寻找右侧边界的二分搜索

/**
 * @param {number[]} nums - 有序数组
 * @param {number} target - 目标值
 * @return {number} - 目标值的右侧边界索引
 */
function rightBoundBinarySearch(nums, target) {
    let left = 0;
    let right = nums.length - 1;

    while (left <= right) {
        const mid = Math.floor((left + right) / 2);

        if (nums[mid] <= target) {
            left = mid + 1;
        } else {
            right = mid - 1;
        }
    }

    // 检查 right 是否越界以及 nums[right] 是否为 target
    if (right < 0 || nums[right] !== target) {
        return -1; // 如果未找到目标值,则返回 -1
    }

    return right; // 返回右侧边界索引
}

回溯算法

算法框架 路径 选择列表 结束条件

const res = [];
function backtrack(路径,选择列表) {
  if(结束条件){
    res.push(路径);
    return ;
  }

  for(选择 of 选择列表) {
    // 1. 做选择
    backtrack(路径,选择列表);
    // 3. 撤销选择
  }
}
Last Updated:
Contributors: rosendo