Algorithm
文章平均质量分 65
Algorithm
SUKEPP
SDE
展开
-
算法分析03:排序算法
1. 排序算法分类基于选择的排序算法基于选择的排序算法选择排序(Selection Sort)堆排序(Heap Sort):将元素全部存储与最大(最小)堆中,再依次取出即可实现基于交换的排序冒泡排序(Bubble Sort)快速排序(Quick Sort)快速排序的实现分为三个步骤:选择基准值(Pivot)分割操作(Partition)递归...原创 2020-03-28 08:24:16 · 153 阅读 · 0 评论 -
算法分析02:动态规划
1. 定义动态规划(英语:Dynamic programming,简称DP)是一种在数学、管理科学、计算机科学、经济学和生物信息学中使用的,通过把原问题分解为相对简单的子问题的方式求解复杂问题的方法。动态规划常常适用于有重叠子问题[1]和最优子结构性质的问题,动态规划方法所耗时间往往远少于朴素解法。2. 适用情况最优子结构大问题的最优解可以由小问题的最优解推出,这个性质叫做“最优子结...原创 2020-03-28 08:17:12 · 190 阅读 · 0 评论 -
算法分析01:分治
1. 定义将原问题分解为若干个规模较小但类似于原问题的子问题(Divide),递归的求解这些子问题(Conquer),然后再合并(Combine)这些子问题的解来建立原问题的解。2. 基本过程Divide:将问题的规模变小Conquer:递归的处理小规模问题(只需递归调用即可)Combine:将小规模问题的解合并为原始问题的解3. 分治与动态规划的关系StevenSun2014 ...原创 2020-03-28 08:02:04 · 136 阅读 · 0 评论 -
数据结构分析01:线性表
1. Linked List1.1. 哨兵问题链表的插入或者删除操作存在邻居依赖问题对于单向链表,插入或者删除操作需要依赖前驱结点或者后继结点依赖前驱节点的原因该情况下实现相关操作需要修改前驱结点的 next 变量,如果没有前驱哨兵的话,这样会导致插入首结点与插入其余结点时代码实现不一致,因为首结点没有前驱结点,从而增加了代码复杂度。所以此时需要加入前驱哨兵。依赖后继节点的...原创 2020-03-28 07:53:28 · 207 阅读 · 0 评论 -
剑指offer题23_从上往下打印二叉树
一.题目:从上往下打印二叉树的每个结点,同一层的节点按照从左到右的顺序打印。二.分析:通过STL中的deque实现(两端都可以进出的队列)三.答案:void PrintFromTopToBottom(BinaryTreeNode* pTreeRoot) { if (!pTreeRoot) { return; } std::原创 2018-02-27 17:41:36 · 133 阅读 · 0 评论 -
剑指offer题22_栈的压入和弹出序列
一.题目:输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否为该栈的弹出序列。二.分析:总结压入弹出规律:如果下一个弹出的数字刚好是栈顶元素,那么直接弹出;如果下一个弹出的数字不在栈顶,我们把压栈序列中还没有入栈的数字压入辅助栈,直到把下一个需要弹出的数字压入栈顶为止。如果所有的数都压入了栈仍然没有找到下一个弹出的数字,那么该序列不可能是一个弹出序列。三.答案:bool IsPopO原创 2018-02-12 16:39:02 · 158 阅读 · 0 评论 -
剑指offer题21_包含min函数的栈
一.题目:定义栈的数据结构,请在该类型中实现一个能够得到栈的最小元素的min函数。在该栈中,调用min,push及pop的时间复杂度都是O(1)。二.分析:在面试时,很多应聘者都止步于添加一个变量保存最小元素的思路。其实只要举个例子多做几次入栈,出栈的操作就能看出问题,并能想到最小元素用另外的辅助栈保存。三.答案:template <template T> void StackWithMin<T>:原创 2018-02-08 17:01:37 · 161 阅读 · 0 评论 -
剑指offer题20_顺时针打印矩阵
一.题目:输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字。二.分析:当我们遇到一个复杂的问题,可以用图形来帮助我们思考。1.我们可以用一个循环来打印矩阵,每一次打印矩阵中的一个圈。2.下一步分析循环结束的条件。我们可以分析出,让循环继续的条件是column > startX * 2并且rows > startY * 2。三.答案:void printMatrixClockwisely(原创 2018-02-07 17:02:14 · 155 阅读 · 0 评论 -
剑指offer题19_二叉树的镜像
一.题目:请完成一个函数,输入一个二叉树,该函数输出它的镜像。 二叉树结点的定义如下:struct BinaryTreeNode { int m_nValue; BinaryTreeNode* m_pLeft; BinaryTreeNode* m_pRight;};二.分析:需要尝试通过举例画图,然后可以总结出求一棵树镜像原创 2018-02-05 18:43:26 · 179 阅读 · 0 评论 -
剑指offer题18_树的子结构
一.题目:输入两棵二叉树A和B,判断B是不是A的子结构。二叉树的子结构如下:struct BinaryTreeNode { int m_nValue; BinaryTreeNode* m_pLeft; BinaryTreeNode* m_pRight;}二.分析:我们可以分成两步:1.第一步在树A中找到和树B的根结点的值一样原创 2018-02-03 17:26:12 · 153 阅读 · 0 评论 -
剑指offer题17_合并两个排序的链表
一.题目:输入两个递增排序的链表,合并这两个链表并使新链表中的结点仍然是按照递增排序的。链表结点定义如下:struct ListNode { int m_nValue; ListNode* m_pNext;};二.分析:1.当我们得到两个链表中的值较小的头结点并把它链接到已经合并的链表之后,两个链表剩余的结点依然是排序的,因此合并的步骤和之前步骤是一样的。这就是典原创 2018-02-02 18:12:08 · 163 阅读 · 0 评论 -
剑指offer题16_反转链表
一.题目:定义一个函数,输入一个链表的头结点,反转该链表并输出反转后链表的头结点,链表结点定义如下:typedef struct ListNode { int m_nValue; struct ListNode* m_pNext;} ListNode;二.分析:以这道题为例,我们至少应该想到几类测试用例对代码进行功能测试。 1.输入的链表头结点是原创 2018-02-01 18:20:28 · 126 阅读 · 0 评论 -
剑指offer题15_链表中倒数第k个结点
一.题目:输入一个链表,输出该链表中倒数第k个结点。 链表定义如下:typedef struct ListNode { int m_nValue; struct ListNode* m_pNext;} ListNode;二.分析:功能之外还需要考虑代码的鲁棒性,其中考虑如下三点:1.若输入的头指针为空指针,不能引起程序崩溃。 2.若输入的链表的结点总数小于k,原创 2018-01-31 17:55:56 · 159 阅读 · 0 评论 -
剑指offer题14_调整数组顺序使奇数位于偶数前面
一.题目:输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有奇数位于数组的前半部分,所有偶数位于数组的后半部分。二.分析:只完成基本功能的解法,仅适用于初级程序员,需要考虑可扩展性的方法才行,我们需要把整个函数解耦成两部分:一个是判断数字应该在数组前半部分还是后半部分;二是拆分数组的操作。三.答案:#include <stdio.h>bool isEven(int n) {原创 2018-01-29 16:36:21 · 131 阅读 · 0 评论 -
剑指offer题13_在O(1)时间内删除链表结点
一.题目:给定单向链表的头指针和一个结点指针,给定一个函数在O(1)时间删除该结点。链表结点与函数定义如下: 二.分析:共需考虑三种情况: 1.首先考虑的是并不是一定需要得到被删除结点的前一个结点,如果我们把下一个结点的内容复制到需要删除的结点上覆盖原有的内容,再把下一个结点删除即可。 2.如果需要删除的结点位于链表的尾部,那我们还是需要顺序遍历链表。 3.如果链表只有一个结点原创 2018-01-26 19:07:30 · 146 阅读 · 0 评论 -
剑指offer题11_数值的整数次方
一.题目:实现函数double Power(double base, int exponent),求base的exponent次方。不得使用库函数,同时不需要考虑大数问题。二.分析:1.注意代码的规范性和完整性。 (1)需要考虑指数是负数的情况; (2)需要考虑底数为0且指数为负数的情况; (3)考虑到0的0次方是没有意义的,结果为0或1均可。 2.乘方函数的实现上,可以底数循环乘法,但是效原创 2018-01-19 15:10:32 · 188 阅读 · 0 评论 -
剑指offer题10_二进制中1的个数
一.题目:请实现一个函数,输入一个整数,输出该数二进制表示中1的个数。例如把9表示成1001,有2位是1。因此如果输入9,该函数输出2。二.分析:1.可能引起死循环的解法: 判断输入的整数最右一位是否为1,然后循环右移,但是问题是如果输入的整数是一个负数,那么循环右移就会变成死循环。 2.常规解法: 将输入的整数不进行右移,而是将1进行循环左移进行判断。 3.能给面试官带来惊喜的解法: 思原创 2018-01-18 16:52:06 · 129 阅读 · 0 评论 -
剑指offer题9_斐波那契数列
一.题目:写一个函数,输入n,求斐波那契(Fibonacci)数列的第n项。斐波那契(Fibonacci)数列定义如下: 二.分析:有三种解题方法: 1.基于递归的解法虽然直观,但时间效率很低,实际软件开发中不会用这种方法,也不可能得到面试官的青睐。 2.把递归的算法用循环实现,提高时间效率。 3.把求斐波那契数列转换成求矩阵的乘方,有创意,但不实用。三.答案:原创 2018-01-17 18:38:56 · 125 阅读 · 0 评论 -
剑指offer题8_旋转数组的最小数字
一.题目:把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素。例如数组{3, 4, 5, 1, 2}为{1, 2, 3, 4, 5 }的一个旋转,该数组的最小值为1。二.分析:1.本题给出的数组在一定程度上是排序的,因此我们可以尝试着用二分查找法的思路来寻找这个最小的元素。 2.按照定义有一个特例:如果把排序数组的前面的0个元原创 2018-01-16 19:13:57 · 118 阅读 · 0 评论 -
剑指offer题7_用两个栈实现队列
一.题目:用两个栈实现一个队列。队列的声明如下,请实现它的两个函数appendTail和deleteHead,分别完成在队列尾部插入结点和队列头部删除结点的功能。template <typename T> class CQueue{public: CQueue(void); ~CQueue(void); void appendTail(const T& node);原创 2018-01-13 13:57:30 · 117 阅读 · 0 评论 -
剑指offer题6_重建二叉树
一.题目:输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果都不含重复的数字。例如输入前序遍历序列{1, 2, 4, 7, 3, 5, 6, 8}和中序遍历序列{4, 7, 2, 1, 5, 3, 8, 6},则重建出该二叉树并输出它的头结点。二叉树结点的定义如下: struct BinaryTreeNode { int m_nValue;原创 2018-01-12 11:05:09 · 144 阅读 · 0 评论 -
剑指offer题5_从头到尾打印链表
一.题目:输入一个链表的头文件,从尾到头反过来打印出每个节点的值。链表节点定义如下:struct ListNode { int m_nValue; struct ListNode *m_pNext;};二.分析:可从两种思路来解决: 1.迭代 + 栈; 2.递归。三.答案:1.迭代 + 栈:void printLis原创 2018-01-09 19:29:18 · 152 阅读 · 0 评论 -
剑指offer题4_替换空格
一.题目:请实现一个函数,把字符串中的每个空格替换成“%20”。例如输入“We are happy”,则输出“We%20are%20happy”。二.分析:1.需要向面试官问清楚,是需要在原来字符串上做替换,还是创建新的字符串。若在原来字符串需要保证充足的内存空间。 2.假如是在原来字符串上做替换,思路是从字符串的后面开始复制和替换,需要准备两个指针。规律是,合并两个数组(包括字原创 2018-01-05 19:35:08 · 141 阅读 · 0 评论 -
剑指offer题3_二维数组的查找
一.题目:在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的二维数组和一个整数,判断数组中是否含有该整数。二.分析:1.可以从左下角或者右上角进行查询,这样可以保证每一次查询排除一行或者一列。 2.设计完算法,一定要准备测试用例,走一遍,才能确保正确。 (1)功能测试 (2)特殊输入测试三.答案:原创 2018-01-04 19:01:16 · 142 阅读 · 0 评论 -
剑指offer题1_赋值运算符函数
一.题目:如下为类型CMyString的声明,请为该类型添加赋值运算符函数。class CMyString {public: CMyString(char* pData = NULL); CMyString(const CMyString& str); ~CMyString(void);private: char* m_pData;}二.分析:1.是否返回值的类原创 2018-01-03 19:16:41 · 311 阅读 · 0 评论 -
数据结构基础6.2:图的遍历
图的遍历方式有两种:1.深度优先搜索(DGS),类似于树的前序遍历。2.广度优先搜索(BFS),类似于树的层次遍历。具体代码如下:1.DFS:void Visit(Vertex n){ printf("%d ", n);}/* DFS递归调用,类似树的前序遍历 */void DFS(MGraph graph, Vertex n, void (*Visit)原创 2015-11-25 18:12:51 · 290 阅读 · 0 评论 -
数据结构基础4:串
串的实现方式有三种:1.定长顺序存储实现2.堆分配存储实现3.块链存储实现本文介绍了第2种(堆分配存储实现)的方式,基本操作函数如下所示:注:该代码在linux下gcc编译实现,用windows下的dev c++不知为何运行结果出现错误,如果哪位大侠发现哪里有问题,还请指正。/* 初始化一个值为chars的串 */Status StrAssign(pString str,原创 2015-11-02 21:10:06 · 379 阅读 · 0 评论 -
数据结构基础6.1:图的表示方法
图的表示方法有多种:1. 邻接矩阵法 2. 邻接链表法3. 十字链表法 4. 邻接多重表法本文主要介绍邻接矩阵法和邻接链表法。1.邻接矩阵法 :好处:直观简单;方便检查任一对顶点间是否存在边;方便找任一顶点的所有邻接点;方便计算任一顶点的度。坏处:浪费空间,对于稀疏图会有大量无效元素。2.邻接矩阵法:好处:方便找任一顶点的所有邻接点;节约稀疏图的空间坏处:对于检查任原创 2015-11-23 16:55:40 · 741 阅读 · 0 评论 -
数据结构基础3:队列
本文分别介绍了队列的链表实现和顺序实现,其中顺序实现写为循环队列,两种实现的接口和调用基本相同。1.链表实现:Queue.h#include #include #include #include #define ElemType int#define Status int #define ERROR -1;#define OK 0#define TRUE 1#def原创 2015-10-15 20:19:04 · 422 阅读 · 0 评论 -
数据结构基础1:线性表
数据结构基础1:线性表试写一算法,将x插入到顺序表的适当位置,保持该表递增有序,插入结束后实现就地逆置的功能#include "LinkList.h"/* 试写一算法,将x插入到顺序表的适当位置,保持该表递增有序,插入结束后实现就地逆置的功能 */int main(int argc, char *argv[]){ int i = 0; int data[1原创 2015-10-15 11:26:19 · 346 阅读 · 0 评论 -
数据结构基础5.5:哈夫曼树(HuffmanTree)的构造
一:哈夫曼树的定义哈夫曼树,也叫最优二叉树,是WPL(带权路径长度)最小的树。二:哈夫曼树的特点1. 没有度为1的结点;2. n个叶子结点的哈夫曼树共有2n - 1个结点;3.哈夫曼树的任意非叶结点的左右子树交换后仍是哈夫曼树;三:哈夫曼树的构造代码如下,内部部分函数实现请参考上一篇博客中的堆操作。typedef struct HuffmanNode { in原创 2015-11-10 18:34:53 · 1284 阅读 · 0 评论 -
数据结构基础5.4:堆(HEAP)的基本操作(插入与删除)
首先,先介绍一下堆的两个特性:1. 结构性:用数组表示的完全二叉树2. 有序性:任一结点的关键字是其子树所有结点的最大值(或最小值)然后,我们正式开始介绍堆的基本操作,本文以最大堆为例,介绍了如下几个操作:1. 创建一个空的最大堆2. 判断最大堆是否满3. 判断最大堆是否空4. 将元素插入最大堆5. 删除最大堆的最大元素并返回其值具体完整代码如下:#incl原创 2015-11-09 20:47:16 · 1058 阅读 · 0 评论 -
数据结构基础5.2:二叉搜索树(BST)的基本操作(插入、查找、删除)
本文介绍了了二叉树的一些基本操作:1.插入(分别采用递归与非递归两种方式)2.查找(采用递归方式)3.删除(采用递归方式)具体完整代码如下:#include #include #include #include #define ElemType charusing namespace std;typedef struct bstnode { ElemT原创 2015-11-08 15:30:20 · 491 阅读 · 0 评论 -
数据结构基础5.3:平衡二叉树(AVL树)的调整
首先,先介绍一下平衡二叉树。平衡二叉树:空树,或者任一结点左右子树高度差的绝对值不超过1,即平衡因子 | BF(T) | 其结点数规律:设n(h)为高度为h的平衡二叉树的最小结点数,则n(h) = n(h - 1) + n(h - 2) + 1。所以给定结点数n的AVL树的最大高度为log2(N)。然后,进入重点,介绍平衡二叉树的调整,一共分为4种情况:注:这里我们把插入的原创 2015-11-08 20:13:45 · 659 阅读 · 0 评论 -
数据结构基础6.5:拓扑排序TopOrder
一. 定义:1. 拓扑序:如果图中从v到w有一条有向路径,则v一定排在w之前。满足此条件的顶点序列成为一个拓扑序。2. 获得一个拓扑序的过程就是拓扑排序。二. 算法描述:1. 通过遍历图,计算每个顶点的入度值。2. 将图中每个入度值为0的顶点入队。3. 判断队列是否为空,如果队列不为空,则出队赋值给v,输出顶点v,cnt计数值加1,并以此遍历v的所有邻接点,将其入度值减1,原创 2015-11-27 19:47:11 · 761 阅读 · 0 评论 -
数据结构基础6.3:最小生成树MST(Prim、Kruskal)
一.最小生成树:连通图的一次遍历所经过的边的集合及图中所有顶点的集合就构成了该图的一棵生成树,对连通图的不同遍历,就可以得到不同的生成树。如果无向连通图就是一个网,那么,它的所有生成树中必有一棵边的权值总和最小的生成树,我们称这棵生成树为最小生成树。二.最小生成树的两种算法:1.Prim算法:适用范围:该算法针对顶点展开,适用于边数较多的情况。算法描述:1).输原创 2015-11-25 21:27:44 · 527 阅读 · 0 评论 -
数据结构基础6.4:最短路径(Dijkstra, Floyd)
一. Dijkstra算法:1. 定义:Dijkstra算法是典型的单源最短路径算法,用于计算一个节点到其他所有节点的最短路径。主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止。Dijkstra算法是很有代表性的最短路径算法,在很多专业课程中都作为基本内容有详细的介绍,如数据结构,图论,运筹学等等。注意该算法要求图中不存在负权边。该算法用于解决单源最短路径。2. 算法描原创 2015-11-27 18:23:05 · 537 阅读 · 0 评论 -
数据结构基础7.5:快速排序
一.定义:快速排序,这也是在实际中最常用的一种排序算法,速度快,效率高。就像名字一样,快速排序是最优秀的一种排序算法。二.算法描述:快速排序采用的思想是分治思想。快速排序是找出一个元素(理论上可以随便找一个)作为基准(pivot),然后对数组进行分区操作,使基准左边元素的值都不大于基准值,基准右边的元素值 都不小于基准值,如此作为基准的元素调整到排序后的正确位置。递归快速排原创 2015-11-30 12:14:29 · 483 阅读 · 0 评论 -
数据结构基础7.4:归并排序
一.定义归并(Merge)排序法是将两个(或两个以上)有序表合并成一个新的有序表,即把待排序序列分为若干个子序列,每个子序列是有序的,然后再把有序子序列合并为整体有序序列。二.算法描述(递归实现):递归过程是将待排序集合一分为二,直至排序集合就剩下一个元素为止,然后不断的合并两个排好序的数组。三.代码实现(递归实现):#include #include #include原创 2015-11-30 11:20:30 · 361 阅读 · 0 评论 -
数据结构基础2:栈
数据结构基础2:栈求算术表达式有两种方法:1.运算符优先级法:该方法来自严蔚敏版数据结构,需要设置两个栈,一个操作数栈,一个操作符栈。2.后缀表达式法:中缀表达式转后缀表达式(逆波兰式)并求值,分为两个过程,每个过程个需要一个栈。本文采用后缀表达式法求算术表达式。main.c#include #include #include "Stack.h"/* 中缀表达式原创 2015-10-15 13:11:44 · 463 阅读 · 0 评论