Hello 算法
文章平均质量分 87
算法的逐步学习
tyb333333
这个作者很懒,什么都没留下…
展开
-
8.3 Top-k 问题
给定一个长度为 n 的无序数组nums,请返回数组中最大的 k 个元素。原创 2024-08-13 15:05:37 · 397 阅读 · 0 评论 -
汉诺塔问题
在归并排序和构建二叉树中,我们都是将原问题分解为两个规模为原问题一半的子问题。然而对于汉诺塔问题,我们采用不同的分解策略给定三根柱子,记为AB和C。起始状态下,柱子AC` 上,并保持它们的原有顺序不变(如图 12-10 所示)。在移动圆盘的过程中,需要遵守以下规则。2. 每次只能移动一个圆盘。。例如 f(3) 代表将 3 个圆盘从A移动至C的汉诺塔问题。原创 2024-08-15 15:59:29 · 683 阅读 · 0 评论 -
09 图
图(graph)是一种非线性数据结构,由顶点(vertex)和边(edge)组成。我们可以将图 G 抽象地表示为一组顶点 V 和一组边 E 的集合。以下示例展示了一个包含 5 个顶点和 7 条边的图。如果将顶点看作节点,将边看作连接各个节点的引用(指针),我们就可以将图看作一种从链表拓展而来的数据结构。如图 所示,,因而更为复杂。原创 2024-08-13 15:28:52 · 838 阅读 · 0 评论 -
8.2 建堆操作
在某些情况下,我们希望使用一个列表的所有元素来构建一个堆,这个过程被称为“建堆操作”。原创 2024-08-13 15:02:16 · 499 阅读 · 0 评论 -
15 贪心
贪心算法(greedy algorithm)是一种常见的解决优化问题的算法,其基本思想是在问题的每个决策阶段,都选择当前看起来最优的选择,即贪心地做出局部最优的决策,以期获得全局最优解。贪心算法简洁且高效,在许多实际问题中有着广泛的应用。贪心算法和动态规划都常用于解决优化问题。它们之间存在一些相似之处,比如都依赖最优子结构性质,但工作原理不同。我们先通过例题“零钱兑换”了解贪心算法的工作原理。这道题已经在“完全背包问题”章节中介绍过,相信你对它并不陌生。原创 2024-08-15 16:56:04 · 681 阅读 · 0 评论 -
14 动态规划
动态规划(dynamic programming)是一个重要的算法范式,它将一个问题分解为一系列更小的子问题,并通过存储子问题的解来避免重复计算,从而大幅提升时间效率。在本节中,我们从一个经典例题入手,先给出它的暴力回溯解法,观察其中包含的重叠子问题,再逐步导出更高效的动态规划解法给定一个共有 n 阶的楼梯,你每步可以上 1 阶或者 2 阶,请问有多少种方案可以爬到楼顶?如图 14-1 所示,对于一个 3 阶楼梯,共有 3 种方案可以爬到楼顶。本题的目标是求解方案数量,。原创 2024-08-15 16:54:39 · 935 阅读 · 0 评论 -
13 回溯
回溯算法(backtracking algorithm)是一种通过穷举来解决问题的方法,它的核心思想是从一个初始状态出发,暴力搜索所有可能的解决方案,当遇到正确的解则将其记录,直到找到解或者尝试了所有可能的选择都无法找到解为止。回溯算法通常采用“深度优先搜索”来遍历解空间。在“二叉树”章节中,我们提到前序、中序和后序遍历都属于深度优先搜索。接下来,我们利用前序遍历构造一个回溯问题,逐步了解回溯算法的工作原理。给定一棵二叉树,搜索并记录所有值为 7 的节点,请返回节点列表。原创 2024-08-15 16:49:01 · 657 阅读 · 0 评论 -
12 分治
分治(divide and conquer),全称分而治之,是一种非常重要且常见的算法策略。分治通常基于递归实现,包括“分”和“治”两个步骤。如图所示,“归并排序”是分治策略的典型应用之一。原创 2024-08-15 15:58:04 · 638 阅读 · 0 评论 -
11 排序
这个信息非常关键,因为它告诉我们各个元素应该出现在结果数组的哪个位置。接下来,我们倒序遍历原数组。原创 2024-08-14 15:53:28 · 816 阅读 · 0 评论 -
10.4 哈希优化策略
在算法题中,。我们借助一个算法题来加深理解。给定一个整数数组nums和一个目标元素targettarget。原创 2024-08-14 15:01:53 · 996 阅读 · 0 评论 -
10.3 二分查找边界
numstarget回忆二分查找插入点的方法,搜索完成后 i 指向最左一个targettarget。考虑通过查找插入点的函数实现查找左边界。请注意,数组中可能不包含target,这种情况可能导致以下两种结果。原创 2024-08-14 14:51:34 · 383 阅读 · 0 评论 -
10.2 二分查找插入点
二分查找不仅可用于搜索目标元素,还可用于解决许多变种问题,比如搜索目标元素的插入位置。原创 2024-08-14 14:38:01 · 740 阅读 · 0 评论 -
10.1 二分查找
二分查找(binary search)是一种基于分治策略的高效搜索算法。它利用数据的有序性,每轮缩小一半搜索范围,直至找到目标元素或搜索区间为空为止。numstarget我们先初始化指针 i=0 和 j=n−1 ,分别指向数组首元素和尾元素,代表搜索区间 [0,n−1]。请注意,中括号表示闭区间,其包含边界值本身。接下来,循环执行以下两步。nums[m]targettargettargettarget值得注意的是,由于 i 和 j 都是int类型,int。原创 2024-08-14 14:27:32 · 747 阅读 · 0 评论 -
8.1 堆
堆(heap)是一种满足特定条件的完全二叉树,主要可分为两种类型,如图 8-1 所示。小顶堆(min heap):任意节点的值 ≤ 其子节点的值。大顶堆(max heap):任意节点的值 ≥ 其子节点的值。堆作为完全二叉树的一个特例,具有以下特性。最底层节点靠左填充,其他层的节点都被填满。我们将二叉树的根节点称为“堆顶”,将底层最靠右的节点称为“堆底”。对于大顶堆(小顶堆),堆顶元素(根节点)的值是最大(最小)的。原创 2024-08-13 14:59:25 · 702 阅读 · 0 评论 -
07 树
二叉树(binary tree)是一种非线性数据结构,代表“祖先”与“后代”之间的派生关系,体现了“一分为二”的分治逻辑。与链表类似,二叉树的基本单元是节点,每个节点包含值、左子节点引用和右子节点引用。每个节点都有两个引用(指针),分别指向左子节点(left-child node)和右子节点(right-child node),该节点被称为这两个子节点的父节点(parent node)。原创 2024-08-12 16:52:44 · 1041 阅读 · 0 评论 -
00本书内容以及如何使用(Hello 算法)
这本书给我们这些算法小白提供了一个条很好的学习路径。我的学习方法就是阅读网页内容经行理解按照所给实例,自己经行答题不会再来学总结问题所在请教问题(向老师,评论区,学长学姐等)进行总结内容输出到博客。原创 2024-08-04 20:08:56 · 264 阅读 · 0 评论 -
01初识算法
算法(algorithm)是在有限时间内解决特定问题的一组指令或操作步骤,它具有以下特性。确定性:算法的每个步骤都是明确定义的,不会产生歧义。有穷性:算法必须在执行有限步骤后结束,不会无限循环。输入:算法有零个或多个输入,这些输入是算法执行所需的数据。输出:算法至少有一个输出,表示算法执行的结果。可行性:算法中的每个步骤都必须是可执行的,即在当前的计算模型下可以实现。通用性:算法通常不针对特定问题设计,而是可以应用于解决一类问题。效率性。原创 2024-08-04 20:07:55 · 256 阅读 · 0 评论 -
02复杂度分析
我们将线性阶的时间复杂度记为 O(n) ,这个数学符号称为大 O 记号(big-O notation),表示函数 T(n) 的渐近上界(asymptotic upper bound)。`若存在正实数 c 和实数 n0 ,使得对于所有的 n>n0 ,均有 T(n)≤c⋅f(n) ,则可认为 f(n) 给出了 T(n) 的一个渐近上界,记为 T(n)=O(f(n))设输入数据大小为 n ,由于每轮缩减到一半,因此循环次数是 log2n ,即 2n 的反函数。当 n 趋于无穷大时,这些常数变得无足轻重。原创 2024-08-04 20:07:07 · 579 阅读 · 0 评论 -
03数据结构
线性结构。原创 2024-08-05 19:33:35 · 739 阅读 · 0 评论 -
04 数组与链表
列表(list)是一个抽象的数据结构概念,它表示元素的有序集合,支持元素访问、修改、添加、删除和遍历等操作,无须使用者考虑容量限制的问题。在列表尾部添加元素的时间复杂度为 O(1) ,但插入和删除元素的效率仍与数组相同,时间复杂度为 O(n)。如果我们希望扩容数组,则需重新建立一个更大的数组,然后把原数组元素依次复制到新数组。在复杂的系统环境中,程序难以保证数组之后的内存空间是可用的,从而无法安全地扩展数组容量。值得注意的是,由于数组的长度是固定的,因此插入一个元素必定会导致数组尾部元素“丢失”原创 2024-08-08 19:27:37 · 648 阅读 · 0 评论 -
5.1 栈
数据结构原创 2024-08-09 14:21:48 · 850 阅读 · 0 评论 -
5.2 队列
队列(queue)是一种遵循先入先出规则的线性数据结构。顾名思义,队列模拟了排队现象,即新来的人不断加入队列尾部,而位于队列头部的人逐个离开。我们将队列头部称为“队首”,尾部称为“队尾”,将把元素加入队尾的操作称为“入队”,删除队首元素的操作称为“出队”原创 2024-08-09 14:31:38 · 711 阅读 · 0 评论 -
5.3 双向队列
双向队列(double-ended queue)提供了更高的灵活性,允许在头部和尾部执行元素的添加或删除操作。原创 2024-08-09 14:40:00 · 412 阅读 · 0 评论 -
6.1哈希表
哈希表(hash table),又称散列表,它通过建立键key与值value之间的映射,实现高效的元素查询。具体而言,我们向哈希表中输入一个键key,则可以在 O(1) 时间内获取对应的值value。如图 6-1 所示,给定 n 个学生,每个学生都有“姓名”和“学号”两项数据。假如我们希望实现“输入一个学号,返回对应的姓名”的查询功能除哈希表外,数组和链表也可以实现查询功能。原创 2024-08-12 15:33:45 · 664 阅读 · 0 评论 -
6.2 哈希冲突
上一节提到,,因此理论上哈希冲突是不可避免的。比如,输入空间为全体整数,输出空间为数组容量大小,则必然有多个整数映射至同一桶索引。哈希冲突会导致查询结果错误,严重影响哈希表的可用性。为了解决该问题,每当遇到哈希冲突时,我们就进行哈希表扩容,直至冲突消失为止。此方法简单粗暴且有效,但效率太低,因为哈希表扩容需要进行大量的数据搬运与哈希值计算。为了提升效率,我们可以采用以下策略。哈希表的结构改良方法主要包括“链式地址”和“开放寻址”。原创 2024-08-12 16:01:21 · 956 阅读 · 0 评论 -
6.3 哈希算法
前两节介绍了哈希表的工作原理和哈希冲突的处理方法。然而无论是开放寻址还是链式地址,。如果哈希冲突过于频繁,哈希表的性能则会急剧劣化对于链式地址哈希表,理想情况下键值对均匀分布在各个桶中,达到最佳查询效率;最差情况下所有键值对都存储到同一个桶中,时间复杂度退化至 O(n)。。原创 2024-08-12 16:11:07 · 547 阅读 · 0 评论