代码编织梦想

二叉树遍历 https://labuladong.gitee.io/algo/di-ling-zh-bfe1b/dong-ge-da-334dd/

void traverse(TreeNode* root) {
    if (root == nullptr) {
        return;
    }
    // 前序位置
    traverse(root->left);
    // 中序位置
    traverse(root->right);
    // 后序位置
}

动态规划 https://labuladong.gitee.io/algo/di-ling-zh-bfe1b/dong-tai-g-1e688/

# 自顶向下递归的动态规划
def dp(状态1, 状态2, ...):
    for 选择 in 所有可能的选择:
        # 此时的状态已经因为做了选择而改变
        result = 求最值(result, dp(状态1, 状态2, ...))
    return result

# 自底向上迭代的动态规划
# 初始化 base case
dp[0][0][...] = base case
# 进行状态转移
for 状态1 in 状态1的所有取值:
    for 状态2 in 状态2的所有取值:
        for ...
            dp[状态1][状态2][...] = 求最值(选择1,选择2...)

回溯算法 https://labuladong.gitee.io/algo/di-ling-zh-bfe1b/hui-su-sua-c26da/

result = []
def backtrack(路径, 选择列表):
    if 满足结束条件:
        result.add(路径)
        return
    
    for 选择 in 选择列表:
        做选择
        backtrack(路径, 选择列表)
        撤销选择

BFS 层序遍历 https://labuladong.gitee.io/algo/di-ling-zh-bfe1b/bfs-suan-f-463fd/

int BFS(Node start, Node target) {
    queue<Node> q; // 核心数据结构
    unordered_set<Node> visited; // 避免走回头路
    
    q.push(start); // 将起点加入队列
    visited.insert(start);
    int step = 0; // 记录扩散的步数

    while (!q.empty()) {
        int sz = q.size();
        /* 将当前队列中的所有节点向四周扩散 */
        for (int i = 0; i < sz; i++) {
            Node cur = q.front();
            q.pop();
            /* 划重点:这里判断是否到达终点 */
            if (cur == target)
                return step;
            /* 将 cur 的相邻节点加入队列 */
            for (Node x : cur.adj()) {
                if (visited.count(x) == 0) {
                    q.push(x);
                    visited.insert(x);
                }
            }
        }
        /* 划重点:更新步数在这里 */
        step++;
    }
}

二分查找 https://labuladong.gitee.io/algo/di-ling-zh-bfe1b/wo-xie-le–3c789/

int binary_search(vector<int>& nums, int target) {
    int left = 0, right = nums.size() - 1; 
    while(left <= right) {
        int mid = left + (right - left) / 2;
        if (nums[mid] < target) {
            left = mid + 1;
        } else if (nums[mid] > target) {
            right = mid - 1; 
        } else if(nums[mid] == target) {
            // 直接返回
            return mid;
        }
    }
    // 直接返回
    return -1;
}

int left_bound(vector<int>& nums, int target) {
    int left = 0, right = nums.size() - 1;
    while (left <= right) {
        int mid = left + (right - left) / 2;
        if (nums[mid] < target) {
            left = mid + 1;
        } else if (nums[mid] > target) {
            right = mid - 1;
        } else if (nums[mid] == target) {
            // 别返回,锁定左侧边界
            right = mid - 1;
        }
    }
    // 判断 target 是否存在于 nums 中
    // 此时 target 比所有数都大,返回 -1
    if (left == nums.size()) return -1;
    // 判断一下 nums[left] 是不是 target
    return nums[left] == target ? left : -1;
}

int right_bound(vector<int>& nums, int target) {
    int left = 0, right = nums.size() - 1;
    while (left <= right) {
        int mid = left + (right - left) / 2;
        if (nums[mid] < target) {
            left = mid + 1;
        } else if (nums[mid] > target) {
            right = mid - 1;
        } else if (nums[mid] == target) {
            // 别返回,锁定右侧边界
            left = mid + 1;
        }
    }
    // 此时 left - 1 索引越界
    if (left - 1 < 0) return -1;
    // 判断一下 nums[left] 是不是 target
    return nums[left - 1] == target ? (left - 1) : -1;
}

滑动窗口 https://labuladong.gitee.io/algo/di-ling-zh-bfe1b/wo-xie-le–f02cd/

/* 滑动窗口算法框架 */
void slidingWindow(string s) {
    unordered_map<char, int> window;
    
    int left = 0, right = 0;
    while (right < s.size()) {
        // c 是将移入窗口的字符
        char c = s[right];
        // 增大窗口
        right++;
        // 进行窗口内数据的一系列更新
        ...

        /*** debug 输出的位置 ***/
        // 注意在最终的解法代码中不要 print
        // 因为 IO 操作很耗时,可能导致超时
        printf("window: [%d, %d)\n", left, right);
        /********************/
        
        // 判断左侧窗口是否要收缩
        while (window needs shrink) {
            // d 是将移出窗口的字符
            char d = s[left];
            // 缩小窗口
            left++;
            // 进行窗口内数据的一系列更新
            ...
        }
    }
}
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/a13821684483/article/details/129832085

Github最强算法刷题笔记.pdf-爱代码爱编程

资料一 昨晚逛GitHub,无意中看到一位大佬(https://github.com/halfrost)的算法刷题笔记,感觉发现了宝藏!有些小伙伴可能已经发现了,但咱这里还是忍不住安利一波,怕有些小伙伴没有看到。 关于算法刷题的困惑和疑问也经常听朋友们提及。这份笔记里面共包含作者刷LeetCode算法题后整理的数百道题,每道题均附有详细题解过程。

BAT大佬写的Leetcode刷题笔记,太经典了!-爱代码爱编程

大家都知道,现在互联网公司面试,只要是研发岗位,基本是跑不了算法题伺候的,所以大家准备校招、社招,或者平时空闲的时候,都可以刷刷 LeetCode,保持手感 之前刷题,一直觉得漫无目的的刷,效率很低,后来发现了一位 BAT 大佬霜神(halfrost@github)写的 LeetCode 刷题笔记。 我研读后,感觉发现了宝藏!刷 LeetCode 中等

2021 CISP核心知识点 - 刷题笔记-爱代码爱编程

目次 1. 信息安全保障2. 网络安全监管网络安全等级保护相关政策3. 信息安全管理信息安全风险管理信息安全管理体系建设PDCA过程信息安全管理体系(Information Security Management System - ISMS)文档化信息安全管理体系(Information Security Management System - I

二叉树刷题学习笔记1-爱代码爱编程

数据遍历框架 普通数组链表遍历: 对数据的遍历无非就是顺序遍历或者递归遍历,遍历的对象无非也就是数组和链表,一般来说,我们遍历数据有以下框架:/* 迭代遍历数组 */ void traverse(int[] arr) { for (int i = 0; i < arr.length; i++) { } } /* 递归遍历数组

【力扣刷题笔记】初级算法_阿离离离离离李的博客-爱代码爱编程

初级算法 数组 1.删除排序数组中的重复项 题目 给你一个 升序排列 的数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。 由于在某些语言中不能改变数组的长度,所以必须将结果放在数组nums的第一部分。更规范地说,如果在删除重复项之后有 k 个元素,那么 num

字节leetcode刷题笔记,看完吊打问你算法的面试官_park33448的博客-爱代码爱编程

介绍 leetcode 题解,记录自己的 leetcode 解题之路。 目前分为五个部分: 第一个部分是 leetcode 经典题目的解析,包括思路,关键点和具体的代码实现。 第二部分是对于数据结构与算法的总结 第三部分是 anki 卡片, 将 leetcode 题目按照一定的方式记录在 anki 中,方便大家记忆。 第四部分是每日一题,每日

字节大佬leetcode刷题笔记,看完吊打问你算法的面试官_跟着我学java的博客-爱代码爱编程

介绍 leetcode 题解,记录自己的 leetcode 解题之路。 目前分为五个部分: 第一个部分是 leetcode 经典题目的解析,包括思路,关键点和具体的代码实现。第二部分是对于数据结构与算法的总结第三部分是 anki 卡片, 将 leetcode 题目按照一定的方式记录在 anki 中,方便大家记忆。第四部分是每日一题,每日一题是在交流群

算法刷题笔记(初级篇)_输入一个数组nums,请你返回一个等长的结果数组,结果数组中对应索引存储着下一个更-爱代码爱编程

前序:感谢学长的资料推荐以及某位算法大佬的笔记。学了数据结构和算法之后,加上一门好的编程语言刷题会达到事倍功半的效果,例如c++。 总体上分为两大部分:算法思路和代码实现。有了算法思路理解代码实现就不困难,代码实现考察coder的基本功啦。 数据结构的存储方式 数组(顺序存储)和链表(链式存储)是所有数据结构的基础,图,二叉搜索树,哈希表,B树,DF

18-爱代码爱编程

题目 给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点,返回 null 。 图示两个链表在节点 c1 开始相交: 题目数据保证整个链式结构中不存在环。 注意,函数返回结果后,链表必须 保持其原始结构 。 自定义评测: 评测系统的输入如下(你设计的程序不适用此输入):