数据结构与算法
算法笔记
大音希声_
大音希声。大象无形。
展开
-
根据前序遍历与中序遍历序列重建二叉树
题目: 输入二叉树的前序遍历和中序遍历的结果,请重建该二叉树。假设输入的前序遍历与中序遍历中都不包含重复的数字。解题思路:二叉树的前序遍历中,第一个数字总是根节点的值;中序遍历中根节点的值在中间,将左右子树分开了;首先根据前序遍历得到根节点的值,然后根据中序遍历和根节点的值得到左右子树的前序遍历和中序遍历序列;递归构建左子树和右子树;代码实现: //二叉树的节点 static class BinaryTreeNode{ int value; Binary原创 2020-09-01 22:47:57 · 315 阅读 · 0 评论 -
从尾到头打印链表
题目: 输入一个链表的头节点,从尾到头反过来打印出每个节点的值。解题思路1:从尾到头打印链表,也就是最后一个添加到链表的元素,第一个打印。属于典型的“后进先出”类问题,因此我们可以借助栈来实现。从头到尾遍历链表,每经过一个节点,就把该节点压入栈中;链表遍历结束后,就可以从栈顶开始逐个输出节点的值。代码实现: /** * 倒序打印链表,使用栈辅助实现 * @param head 链表的头节点 */ public static void printList原创 2020-08-30 23:01:09 · 300 阅读 · 0 评论 -
替换空格
题目: 请实现一个函数,把字符串中的每个空格替换成“%20”。例如,输入“we are happy.”,则输出“we%20are%20happy.”解题思路:首先求出原字符串的长度length,然后求出替换空格后字符串的新长度newLength;然后将两者作为字符串的下标,指向对应位置;如下图所示:然后从后向前依次复制字符串的内容,每复制一个字符,对应length--;newLength--;;每当length下标对应的字符为空格时,就把空格内容替换为%20,同时执行一次length--,原创 2020-08-29 23:03:23 · 216 阅读 · 0 评论 -
二维数组中元素的查找
题目: 在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排列。求该二维数组中是否存在给定数字number。解题思路:因为二维数组从左到右、从上到下都是递增有序的,因此我们可以从右上角开始比对,如果目标数字number大于二维数组右上角的数字m,则目标数字不会出现在m所在行,所以将m所在行砍掉;如果number小于m,说明number不会出现在m所在列,则将m所在列砍掉。之后让目标数字number与新的右上角元素进行比较,如此循环,直到找到目标数字或二维数组为空。原创 2020-08-29 22:25:08 · 578 阅读 · 0 评论 -
找出数组中重复的数字
题目: 在一个长度为n的数组里所有数字都在0~ n-1的范围内。数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了几次。请找出数组中任意1个重复的数字。解题思路:由于数组中的数字都在0~ n-1的范围内。如果这个数组中没有重复的数字,那么当数组排序之后数字 i 将出现在下标为 i 的位置。如果出现重复数字,有些位置可能存在多个数字,而有些位置可能没有数字。遍历整个数组,当遍历到下标为 i 的数字时,首先比较这个数字(用m表示)是不是等于 i 。如果是,则接着扫描下一个数字;如原创 2020-08-28 10:38:22 · 586 阅读 · 0 评论 -
寻找缺失的整数
题目: 在一个无序数组里有99个不重复的正整数,范围是1~ 100,唯独缺少1个1~100中的整数,如何寻找这个缺失的整数。解题思路:先计算出1+2+3+ …… +100的和,然后依次减去数组里的元素,最后得到的那个差值,就是缺失的整数。代码实现: /** * @param array 无序数组 * @return 返回缺失的整数 */ public static int findLostNum1(int[] array){ int s原创 2020-08-28 09:12:32 · 579 阅读 · 0 评论 -
实现一个公平的抢红包算法
具体要求:所有人抢到的金额之和要等于红包总额,不能多也不能少;每个人至少抢到1分钱;要保证红包拆分的金额尽可能分布均衡,不要出现两级分化太严重的情况。解题思路1:二倍均值法二倍均值法保证的是每次随即金额的平均值是相等的,不会因为抢红包的先后顺序而造成不公平。具体方法如下:假设剩余红包金额为m元,剩余人数为n,那么:每次抢到的金额=随机区间[0.01,m/n×2-0.01]元。代码实现: /** * 拆分红包 * @param totalAmount 总金额原创 2020-08-27 22:52:58 · 685 阅读 · 0 评论 -
迷宫寻路(A星寻路算法)
题目:假设我们有一个7×5大小的迷宫,如下图所示,绿色格子表示起点,红色的格子表示终点,中间的3个深灰色格子表示障碍物。请找到一条从起点到终点最短的路径。解题思路: 需要引入两个集合和一个公式,如下:openList:可到达的格子;closeList:已到达的格子;F=G+H;G:从起点到当前格子的步数;H:在不考虑障碍的情况下,从当前格子到达终点的距离;F:总距离,即从起点到当前格子,再从当前格子到达目原创 2020-08-27 20:35:42 · 2510 阅读 · 0 评论 -
手写一个哈希链表(LRU算法的底层实现)
一、概述 之前在学习操作系统的时候,我们学习过一种LRU(Least Recently Used 即最近最少用)内存管理算法,这个算法基于一种假设:长期不被使用的数据,在未来被使用到的几率也不大。因此当数据所占内存达到一定阈值时,我们要移除掉最近被使用的数据。而在LRU算法的实现中,就采用了哈希链表的数据结构。二、什么是哈希链表首先哈希表是由“key-value”组成的,在逻辑上这些“key-value”是无所谓排列顺原创 2020-08-26 09:17:52 · 366 阅读 · 0 评论 -
动态规划求解金矿问题
题目: 很久很久以前,有一位国王拥有5座金矿,每座金矿的黄金储量不同,需要参与挖掘的工人人数也不同。例如有的金矿储量是500kg黄金,需要5个工人来挖掘;有的金矿储量是200kg黄金,需要3个工人来挖掘…… 如果参与挖矿的工人的总人数是10,每座金矿要么全挖,要么不挖,不能派出一半人挖取一半的金矿。要求用程序求出,要想得到尽可能多的黄金,应该选择挖取哪几座金矿?解决思路:...原创 2020-08-25 10:36:48 · 1045 阅读 · 0 评论 -
如何实现大整数相加
题目: 给出两个很大的整数,要求实现程序求出两个整数之和。解决思路:用数组存储大整数,进行相加,具体步骤如下:创建两个整型数组,数组长度是较大整数的位数+1。把每一个整数倒序存储在数组中,整数的个位存在数组下标为0的位置,最高存于数组的尾部。倒序的目的是为了从左到右访问数组的习惯;创建结果数组,结果数组的长度同样是较大整数的位数+1,+1的目的是给最高位进位预留的;遍历两个数组,从左到右按照对应下标把元素两两相加,相加结果保存在结果数组中,需要进位的,把进位的1填到结果数组的下一个位置;原创 2020-08-23 13:39:49 · 406 阅读 · 0 评论 -
删去k个数字后的最小值(贪心算法思想实现)
题目: 给出一个整数,从该整数中去掉k个数字,要求剩下的数字形成的新整数尽可能小。解题思路:这道题我们可以通过依次求得局部最优解,最终得到全局最优解,使用贪心算法的思想。即将去掉k个数字后求所剩下的数字形成的新整数的最小值转变为求k次去掉1个数字后形成的最小值;这时我们不仅要考虑数字的大小,也要考虑数字的位置;具体就是从高位开始遍历整数,如果发现某一位数字大于它右边的数字,那么在删除该数字后,必然会使该数位的值降低,并且获得的新数为删除1位后的最小值。代码实现: /** * 删原创 2020-08-21 09:30:51 · 736 阅读 · 0 评论 -
寻找全排列的下一个数
题目: 给出一个正整数,找出这个正整数所有数字全排列的下一个数。即就是在一个整数包含数字的全部组合中,找到一个大于且仅大于原数的新整数。例如:输入12345,则返回12354。解题思路:从后向前查看逆序区域,找到逆序区域的前一位,也就是数字交换的边界;让逆序区域的前一位和逆序区域中大于它的最小的数字交换位置;把原来的逆序区域转为顺序状态。代码实现: //找到全排列下一个数 public static int[] findNearestNumber(int[] numbers){原创 2020-08-20 08:52:37 · 177 阅读 · 0 评论 -
如何用两个栈实现队列
题目: 用栈来模拟一个队列,要求实现队列的两个基本操作:入队、出队。解决方案:栈的特点是先进后出,队列的特点是先进先出,这里我们可以使用两个栈(栈A和栈B)模拟队列,具体如下:初始时,栈A和栈B都为空,当需要压入元素时,全部压入栈A;当想要元素出栈时,将栈A中的元素依次出栈并压入栈B;例如:我们将元素a,b,c依次压入栈A,要出栈时,将栈A元素出栈并压入栈B,则栈B中的元素为c,b,a;这时再进行出栈,元素为a,符合队列先进先出的特点;这时,再有元素入栈的时候,继续放入栈A;出栈的时候就从原创 2020-08-19 08:59:43 · 1654 阅读 · 0 评论 -
无序数组排序后的最大相邻差(基于桶排序思想)
题目: 有一个无序整型数组,如何求出该数组排序后的任意两个相邻元素的最大差值?要求时间和空间复杂度尽可能低。解题思路一:利用计数排序的思想,先求出原数组的最大值max与最小值min的区间长度k(k=max-min+1),以及偏移量d=min;创建一个长度为k的新数组array;遍历原数值,每遍历一个元素,就把新数组Array对应下标的值+1.例如原数组元素的值为n,则将array[n-min]的值加1。遍历结束后,array数组的一部分元素值变成了1或更高的数值,一部分元素值仍然是0;遍历新数原创 2020-08-18 12:59:49 · 315 阅读 · 0 评论 -
一行代码解决一个数是否为2的整数次幂
题目: 实现一个方法,来判断一个正整数是否是2的整数次幂(如:16是2的4次方,返回true;18不是2的整数次幂,则返回false)。要求性能尽可能高。解题思路:我们将2的整数次幂转换成二进制数,会发现2的整数次幂只有最高位是1,其它位都是0,如下所示:十进制二进制是否为2的整数次幂81000是1610000是32100000是641000000是1001100100否将我们将2的整数次幂各自减1,再转换成二进制,会发现原创 2020-08-17 08:33:14 · 236 阅读 · 0 评论 -
求最大公约数及其优化算法
题目: 写一段代码,求两个数的最大公约数,尽量优化算法的性能。方案1:辗转相除法定理:两个正整数a和b(a>b),他们的最大公约数等于a除以b的余数c和b之间的最大公约数。 基于该定理,我们可以首先计算出a除以b的余数c,把问题转化成求b和c的最大公约数,然后计算出b除以c的余数d,把问题转化成求c和d的最大公约数;再计算出c除以d的余数e,把问题转换成求d和e的最大公约数…以此类推,逐渐把两个较大整数之间的原创 2020-08-16 09:07:03 · 731 阅读 · 0 评论 -
最小栈的实现
题目: 实现一个栈,该栈带有出栈(pop)、入栈(push)、去最小元素(getMin)3个方法,要保证这3个方法的时间复杂度都是O(1)解题思路:设原有的栈叫做栈A,此时创建一个额外的“备胎”栈B,用于辅助栈A;当第一个元素进入栈A,让新元素也进入栈B。这个唯一的元素就是栈A的当前最小值。之后每当新元素进入栈A时,比较新元素和栈A当前最小值的大小,如果小于栈A当前最小值,则让新元素进入栈B,此时栈B的栈顶元素就是栈A当前最小值;每当栈A有元素出栈时,如果出栈元素是栈A当前最小值,则让栈B的栈顶原创 2020-08-15 08:09:47 · 220 阅读 · 0 评论 -
如何判断链表有环以及求出环的长度和入口点
题目:有一个单向链表,链表中有可能出现“环”,如下图所示:那么如何用程序来判断该链表是否为有环链表呢?解题思路:首先创建两个对象引用p1和p2,让他们同时指向这个链表的头结点,然后开始遍历链表,让指针p1每次向后移动1个节点,指针p2每次向后移动2个节点,然后比较两个指针指向的节点是否相同,如果相同,则链表有环;否则继续遍历。这个解决思路的思想是,对于环形,速度快的总会在多跑一圈的情况下追上速度慢的。主要代码实现: //链表节点 private static class Node{原创 2020-08-14 09:44:38 · 455 阅读 · 0 评论 -
归并排序算法Java实现(两路归并和递归归并)
一、归并1、定义 归并就是将两个或两个以上的有序表合并成一个新的有序表。2、基本思想 设有两个有序表A和B,其数据元素个数分别为n和m,变量 i 和 j 分别是表A和表B的当前元素下标,设表C是归并后的新有序表,变量 k 是C的当前元素的下标。开始时,i , j , k ,分别指向A,B,C三个表的起始位置;然后根原创 2020-07-29 10:16:30 · 331 阅读 · 0 评论 -
桶排序的java实现
一、什么是桶排序 桶排序也是一种线性时间的排序算法。类似于计数排序所创建的统计数组,桶排序需要创建若干个桶来协助排序。 每一个桶(bucket)代表一个区间范围,里面可以承载一个或多个元素。桶排序的原理: 假设有一个非整数原创 2020-07-21 09:08:42 · 3004 阅读 · 2 评论 -
计数排序及其优化
一、什么是计数排序 计数排序是利用下标进行排序的算法,不用对要排序的数字进行比较,我们使用下面的例子进行说明。 假设有20个随机整数,其取值范围在0~10之间,对其进行排序,由于这20个随机整数的取值范围是固定的,那么我们可以定义一个长度为11的数组,数组下标为从0到10,并且元素初始值全为0,然后遍历要排序的20个随原创 2020-07-20 15:43:11 · 782 阅读 · 0 评论 -
图解堆排序之5分钟就能学会的堆排序算法
一、什么是堆排序 对于堆排序,我们首先要了解一下二叉堆的特性:最大堆的堆顶是整个堆中的最大元素;最小堆的堆顶是整个堆中的最小元素。 以最大堆为例,我们删除最大堆的堆顶(注意:这里不是真的删除,而是跟末尾的节点...原创 2020-04-01 19:55:14 · 143 阅读 · 0 评论 -
冒泡排序及其优化(鸡尾酒排序)
一、冒泡排序1、冒泡排序思想 将数组中相邻的元素两两比较,当一个元素大于右侧相邻元素时,交换他们的位置;当一个元素小于或等于右侧的相邻元素时,位置不变2、冒泡排序实现 冒泡排序基本都很熟悉了,直接上代码:...原创 2020-03-27 15:37:02 · 146 阅读 · 0 评论 -
快速排序算法实现
一、什么是快速排序 快速排序采用分治法的思路,对数组排序时每一轮挑选一个基准元素,然后将比基准元素大的移到数组的右边,比基准元素小的移到数组的左边,从而将数组一分为二,然后对一分为二的两部分再分别采用前面的思路,一直到整个数组有序。二、递归实现快速排序 ...原创 2020-03-26 14:46:05 · 765 阅读 · 0 评论