算法基础
涛爸
勿在浮沙筑高台
展开
-
打印螺旋矩阵
给定一个m×n的矩阵,将其螺旋式打印 For example, Given the following matrix: [ [ 1, 2, 3 ], [ 4, 5, 6 ], [ 7, 8, 9 ] ] You should return [1,2,3,6,9,8,7,4,5] Spiral Matrix 从左到右,从上到下,从右到左,从下到上依次遍历即可,注意边界的判断v原创 2016-11-12 21:07:14 · 372 阅读 · 0 评论 -
从尾到头打印链表
输入一个链表,从尾到头打印链表每个节点的值。 解题思路: 最直接的思路是将链表反转,然后按序输出 反转链表有递归与非递归两种方式,具体可点击下面: 非递归反转链表 递归反转链表 但打印只是一个只读操作,最好不要破坏链表的结构,有以下几种解法 1.利用栈后进先出的原理,即可将链表逆序输出 2.使用递归 3.依次将链表中各结点的值insert到vector头,原理同stack 4.依原创 2016-12-08 23:12:49 · 260 阅读 · 0 评论 -
替换空格
请实现一个函数,将一个字符串中的空格替换成“%20”。例如,当字符串为We Are Happy.则经过替换之后的字符串为We%20Are%20Happy。 解题思路: 计算原字符串长度和空格长度,得到新字符串长度 判断是否越界,若不越界,从后往前复制,遇到空格替换成“%20” 之所以从后往前复制是因为从前往后复制需要多次移动字符,从后往前复制可以减少移动的次数 //注意:int index原创 2016-12-06 00:03:26 · 397 阅读 · 0 评论 -
二进制中1的个数
题意:输入一个整数,输出该数二进制表示中1的个数。其中负数用补码表示。解题思路: (n - 1)&n即是把n的二进制表示中的最后一个1变为0 则while执行次数对应n的二进制中1的个数class Solution {public: int NumberOf1(int n) { int count = 0; while (n) {原创 2016-12-16 20:09:59 · 291 阅读 · 0 评论 -
数值的整数次方
题意:给定一个double类型的浮点数base和int类型的整数exponent。求base的exponent次方。解题思路: 首先判断传入的base,exponent参数的有效性 当底数为0且指数为负数时,应判断输入无效 使用成员变量inputInvalid记录参数的有效性 这里需要注意的是:计算机表示小数(包括float,double)都有误差。因此不能直接用==判断两个小数是否相等,当原创 2016-12-17 21:15:01 · 395 阅读 · 0 评论 -
归并排序
1. 归并排序(设置哨兵)《算法导论》第3版2.3.1分治法里提出了归并排序的算法 归并排序算法完全遵循分治模式 1)分解:分解待排序的n个元素的序列成各具n/2个元素的两个子序列 2)解决:使用归并排序递归地排序两个子序列 3)合并:合并两个已排序的子序列以产生已排序的答案设置哨兵,它不可能为较小值void mergeWithSentry(int A[],...原创 2018-06-12 20:20:59 · 413 阅读 · 0 评论 -
插入排序
1. 插入排序迭代版void insert_sort_iterative(int A[], int len){ if (A == NULL || len <= 1) return; for (int j = 1; j < len; ++j) {原创 2018-06-06 20:16:00 · 235 阅读 · 0 评论 -
选择排序
选择排序在《算法导论》第3版的习题2.2-2中,描述了选择排序的过程首先找出A中的最小元素,与A[1]交换接着找出A中的次小元素,与A[2]交换对A中前n-1个元素按该方式继续void select_sort(int A[], int len){ if(A == NULL || len <= 1) return; for(int i =...原创 2018-06-08 19:14:57 · 162 阅读 · 0 评论 -
前/中序遍历序列重建二叉树
重建二叉树 //注意是在中序遍历序列中查找 auto in_left_last = find(in_first, in_last, rootValue); //注意传入的数的位置要对应 root->left = buildTree(next(pre_first), in_left_last, in_first, in_left_last); root->right = buildTree(原创 2016-12-10 23:29:25 · 314 阅读 · 0 评论 -
中/后序遍历序列重建二叉树
输入某二叉树的中序遍历和后序遍历的结果,请重建出该二叉树。 Construct Binary Tree from Inorder and Postorder Traversal 解题思路:取出后序遍历序列最后一个结点的值,即根结点的值 在中序遍历序列中找出根结点的位置,计算distance(in_first, in_left_last)为len 则post_left_last = next(原创 2016-12-11 00:24:47 · 436 阅读 · 0 评论 -
用两个栈实现队列
用两个栈来实现一个队列,完成队列的Push和Pop操作。 队列中的元素为int类型。 解题思路: 入队:直接push进stack1 出队:判断stack2是否为空 如果为空,则将stack1中所有元素pop,并push进栈stack2,取出stack2的栈顶; 如果不为空,直接取出stack2的栈顶。class Solution{public: void push(int no原创 2016-12-12 23:19:58 · 294 阅读 · 0 评论 -
生成螺旋矩阵
给定一个整数n,生成一个由1到n^2的元素填充的螺旋正方形 For example, Given n = 3, You should return the following matrix: [ [ 1, 2, 3 ], [ 8, 9, 4 ], [ 7, 6, 5 ] ] Spiral Matrix II 从左到右,从上到下,从右到左,从下到上依次遍历 同时赋予一个自增原创 2016-11-12 21:34:55 · 529 阅读 · 0 评论 -
最小路径和—Triangle
给定一个三角形,求自顶向下的最小路径和 每一步你可以移动相邻的数字到下面的行 For example,given the following triangle [ [2], [3,4], [6,5,7], [4,1,8,3] ] The minimum path sum from top to bottom is 11 (i.e., 2 + 3 + 5原创 2016-11-13 11:45:57 · 392 阅读 · 0 评论 -
最小路径和—Minimum Path Sum
给定一个非负的m×n个网格,找到一条从左上到右下的路径,使其总和最小 Minimum Path Sum 动态规划,状态转移方程为 result[i][j]=min(result[i-1][j], result[i][j-1])+grid[i][j];int minPathSum(vector<vector<int>>& grid) { if (grid.empty())原创 2016-11-14 14:33:43 · 492 阅读 · 0 评论 -
编辑距离
给定两个单词word1和word2,找到需要转换到的最小步数,每一个操作被计算为1个步骤 3个允许的操作: 插入一个字符 删除一个字符 替换字符动态规划int minDistance(string word1, string word2) { const int m = word1.size(); const int n = word2.size(); int resu原创 2016-11-14 15:36:12 · 257 阅读 · 0 评论 -
不同的子序列
用删除字符的方法将字符串s变换到字符串t,一共有多少种变换方法 Here is an example: S = “rabbbit”, T = “rabbit” Return 3 Distinct Subsequences 动态规划,定义dp[i][j]为字符串s变换到t的可变换次数 如果s[i-1]==t[j-1],那么dp[i][j] = dp[i-1][j-1] + dp[i-1][原创 2016-11-15 20:15:33 · 308 阅读 · 0 评论 -
斐波那契数列
题意:大家都知道斐波那契数列,现在要求输入一个整数n,请你输出斐波那契数列的第n项。 n<=39解题思路: 有以下几种解法: 1.递归:若n==0,返回0。若n==1,返回1。若n>=2,返回f(n - 1) + f(n - 2)。 2.循环:若n==0,返回0。若n==1,返回1。 若n>=2,由cur = prev + cur; 得到cur的值//解法1class Solution {原创 2016-12-15 23:53:39 · 360 阅读 · 0 评论 -
旋转数组的最小数字
把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。 输入一个非递减排序的数组的一个旋转,输出旋转数组的最小元素。 例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。 NOTE:给出的所有元素都大于0,若数组大小为0,请返回0。 解题思路: 有以下几种解法 1.遍历数组,找到minValue,但效率不高 2.使用二分查找 若rotat原创 2016-12-14 11:42:59 · 262 阅读 · 0 评论 -
S中是否存在两个其和刚好为x的元素
《算法导论》第3版习题2.3-7:描述一个运行时间为O(nlgn)的算法,给定n个整数的集合S和一个整数x,该算法能确定S中是否存在两个其和刚好为x的元素。首先对S[0…n-1]进行非降序排序,然后左右夹逼即可 时间复杂度分析:排序为O(nlgn),左右夹逼为O(n),最终O(nlgn)bool find(int A[], int len, int target){ if (l...原创 2018-06-24 14:53:51 · 1120 阅读 · 0 评论 -
求数组中的逆序对
在《算法导论》第3版习题2-4中讲到了如何求数组中的逆序对 假设A[0..n-1]是一个有n个不同数的数组。 若 i &amp;lt; j 且 A[i]&amp;gt;A[j],则对偶 (i,j) 称为A的一个逆序对(inversion)。 给出一个确定在n个元素的任何排列中逆序对数量的算法(提示:修改归并排序)题目已经提示修改归并排序可以完成,插入法是求逆序对的暴力解法,插入排序的次...原创 2018-06-18 13:57:42 · 546 阅读 · 0 评论 -
桶排序
《算法导论》第3版8.4描述了桶排序桶排序将[0,1)区间划分为n个相同大小的子区间,或称为桶。 然后,将n个输入数分别放到各个桶中。 为了得到输出结果,先对各个桶中的数进行排序,然后遍历每个桶, 按照次序把各个桶中的元素列出来即可。代码如下struct Node{ double value; Node *next;};void bucket_sort...原创 2018-07-18 18:06:41 · 220 阅读 · 0 评论 -
S中最接近中位数的k个元素
在《算法导论》第3版习题习题9.3-7提到,设计一个O(n)时间的算法,对于一个给定的包含n个互异元素的集合S和一个正整数 k<=n,该算法能够确定S中最接近中位数的k个元素。步骤如下:1: select A数组得到其中位数nmid,其下标为imid2: 计算A中每个数到中位数的差值作为数组dis, 并拷贝到数组dis_copy3: select dis_copy数组得到第k...原创 2018-07-24 11:46:13 · 1345 阅读 · 2 评论 -
堆排序
在《算法导论》第3版第6章讲解了堆排序算法1:初始时候,利用 build_max_heap 将输入数组 A[0..n-1] 建成最大堆 2:因为数组中的最大元素总在根结点 A[0] 中,把它与 A[n-1] 互换,从而让该元素放到正确的位置。 3:这时候,从堆中去掉结点 n-1(–heap_size),剩余的结点中,原来根的孩子结点仍然是最大堆,而新的根结点 可能会违背最大堆的性质。为了...原创 2018-07-06 19:06:23 · 156 阅读 · 0 评论 -
最小值和最大值
《算法导论》第3版9.1提到了如何查找最小值和最大值1:锦标赛排序:为了确定min/max,必须要做n-1次比较 完整源代码放于github2:将一对输入元素相互进行比较,然后把较小的与当前最小值比较,把较大的与当前最大值进行比较。 这样,对每两个元素共需3次比较,总的比较次数至多是3n/2代码如下struct node { int max; in...原创 2018-07-19 15:50:23 · 670 阅读 · 0 评论 -
期望为线性时间的选择算法
《算法导论》第3版9.2提到了期望为线性时间的选择算法 randomized_select 算法是以第7章的快速排序算法为模型的。 与快速排序一样,我们仍然将输入数组进行递归划分。 但与快速排序不同的是,快速排序会递归处理划分的两边, 而 randomized_select 只处理划分的一边。数组 A[p..r] 被划分为两个子数组 A[p..q-1] 和 A[q+1..r] ...原创 2018-07-20 11:15:37 · 1098 阅读 · 0 评论 -
基数排序
《算法导论》第3版8.3提到了基数排序基数排序(radix sort)是一种用在卡片排序机上的算法。 先按最低有效位进行排序,再按次低有效位进行排序,重复这一过程,直到对所有的d位数完全排好序。 为了使基数排序正确运行,一位数排序算法:计数排序必须是稳定的。代码如下void radix_sort(int A[], int B[], int d){ int *C =...原创 2018-07-18 11:14:59 · 292 阅读 · 0 评论 -
计数排序
《算法导论》第3版8.2提到了计数排序计数排序假设输入n个输入元素中的每一个都是在0到k区间内的一个整数,其中k为某个整数。 计数排序的基本思想是:对每一个输入元素x,确定小于x的元素个数。利用这一信息,就可以直接把x放到它在输出数组中的位置上了。但当有几个元素相同时,则不能把它们放在同一个输出位置上。 因此除了输入数组A[0..n-1],我们还需要两个数组:B[0..n-1]存放排序...原创 2018-07-18 11:11:07 · 198 阅读 · 0 评论 -
最坏情况为线性时间的选择算法
《算法导论》第3版9.3讲解了最坏情况为线性时间的选择算法步骤如下1: 将输入数组的n个元素划分为 n/5 组,每组5个元素,且至多只有一组由剩下的 n%5 个元素组成。2: 寻找 n/5 组中每一组的中位数:首先对每组元素(至多为5个)进行插入排序,然后确定每组有序元素的中位数。3: 对第2步中找出的 n/5 个中位数,递归调用 select 以找出其中位数 num(如果有偶数个...原创 2018-07-23 20:17:54 · 2205 阅读 · 3 评论 -
二分查找
在《算法导论》第3版习题2.3-5里提出二分查找的算法 如果序列A已排好序,就可以将该序列的中点与v进行比较。 根据比较的结果,原序列中有一半就可以不用再做进一步的考虑了。 二分查找算法重复这个过程,每次都将序列剩余部分的规模减半。程序代码如下// 迭代版int binary_search_iterative(int A[], int left, int right...原创 2018-06-18 16:16:11 · 264 阅读 · 0 评论 -
两个n位二进制整数相加
《算法导论》第3版习题2.1-4中提到把两个n位二进制整数加起来的问题,这两个整数分别存储在两个n元数组A和B中,这两个整数的和应按二进制形式存储在一个(n+1)元数组C中。可先将A、B数组反转,按位相加,定义进位carry,初始化为0,将三者加起来,对2取余即为当前位,对2取商即为当前进位,再将C数组反转一次即可得到想要的结果。void reverseArray(int A[], int...原创 2018-06-30 13:47:36 · 1853 阅读 · 0 评论 -
变形的二分查找
二分查找的原始写法如这篇文章所示 如果条件变化一下,比如数组中的元素可能重复,要求返回最小(或最大)的下标。 或者找出数组中第一个大于value(也就是最小的大于value)的元素下标等等, 代码实现会有所不同。 一共分为六种不同情况,下面列出这些变形的二分查找// 找出第一个与value相等的元素int firstEqual(int A[], int left, int ri...原创 2018-06-19 20:04:33 · 334 阅读 · 0 评论 -
最大子数组问题
1. 暴力解法在《算法导论》第3版习题4.1-2提到,对最大子数组问题进行暴力求解 使用两个for循环即可,代码如下void maxSubArray(vector&amp;amp;amp;amp;amp;amp;lt;int&amp;amp;amp;amp;amp;amp;gt; &amp;amp;amp;amp;amp;amp;amp;nums){ int len = nums.size(); if (len &原创 2018-07-02 19:37:10 · 272 阅读 · 0 评论 -
快速排序
《算法导论》第3版7.1提出了快速排序的描述与归并排序一样,快速排序也使用了分治思想。下面是对一个典型的子数组A[p..r]进行快速排序的三步分治过程:分解:数组A[p..r]被划分为两个(可能为空)子数组A[p..q-1]和A[q+1..r],使得A[p..q-1]中的每一个元素 都小于等于A[q],而A[q]也小于等于A[q+1..r]中的每个元素。其中,计算下标q也是划分过程的一部...原创 2018-07-16 10:37:26 · 197 阅读 · 0 评论 -
优先队列
《算法导论》第3版6.5讲解了优先队列优先队列(priority queue)是一种用来维护由一组元素构成的集合S的数据结构, 其中的每一个元素都有一个相关的值,称为关键字(key)。 一个最大优先队列支持以下操作:1) insert(S, x): 把元素x插入集合S中,这一操作等价于S=S∪{x}2) maximum(S): 返回S中具有最大键字的元素3) extract_m...原创 2018-07-15 17:50:24 · 263 阅读 · 0 评论 -
二叉树的层序遍历(非递归)
输出二叉树的层序遍历序列 如[2,6,8,null,null,10,12],输出[[2],[6,8],[10,12]] Binary Tree Level Order Traversal 借助两个队列,一个记录当前层,一个记录下一层 依次插入二维vector/** * Definition for a binary tree node. * struct TreeNode { *原创 2016-11-09 19:26:29 · 618 阅读 · 0 评论 -
二叉树的层序遍历(递归)
输出二叉树的层序遍历序列 如[2,6,8,null,null,10,12],输出[[2],[6,8],[10,12]] Binary Tree Level Order Traversal 借助vector/** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *原创 2016-11-08 22:44:25 · 3517 阅读 · 1 评论 -
反转整数
将一个整数的各位反转过来 Example1: x = 123, return 321 Example2: x = -123, return -321 Reverse digits of an integer 取模,依次进位即可 时间复杂度 O(logn),空间复杂度 O(1)int reverse(int x) { int result = 0; while (x)原创 2016-11-10 18:25:01 · 229 阅读 · 0 评论 -
回文数
判断一个整数是否为回文,不允许使用额外空间 如262,返回true Palindrome Number 依次比较头尾两位即可bool isPalindrome(int x) { if (x < 0) return false; int dig = 1; while (x / dig >= 10) dig *= 10; while (x原创 2016-11-10 19:58:39 · 355 阅读 · 0 评论 -
插入区间
给定一组非重叠的间隔,在间隔中插入一个新的间隔(必要的话合并)。 Example 1: Given intervals [1,3],[6,9], insert and merge [2,5] in as [1,5],[6,9]. Example 2: Given [1,2],[3,5],[6,7],[8,10],[12,16], insert and merge [4,9] in as [1原创 2016-11-10 20:57:49 · 238 阅读 · 0 评论 -
二叉树的非递归后序遍历
输出二叉树的后序遍历序列,不允许使用递归 如[2,6,null,8],输出[8,6,2] Binary Tree Postorder Traversal 借助栈,遍历二叉树 先让所有的左孩子结点入栈 再将右孩子结点入栈 根结点出栈时,比如检测右孩子结点是否已被访问或不存在 若未被访问,根结点必须重新入栈(因后序遍历应先打印右孩子结点的值)/** * Definition for a原创 2016-11-08 21:48:18 · 338 阅读 · 0 评论