java-数据结构与算法
讲解一些基于java语言的数据结构与算法
逸川先生
Java开发工程师,专注后台开发两年,擅长分布式系统
展开
-
前缀树
1)插入一个字符串到前缀树中 2)查找一个字符串是否在前缀树中存在 3)在前缀树中删除一个自定的字符串 4)查看指定前缀在前缀树中出现过多少次public class C01_TrieTree { public static class TrieTree{ public int end;//字符串结束标志 public int path;//字符串经过的标志 ...原创 2018-03-19 21:16:20 · 265 阅读 · 0 评论 -
拼接字符串,使其具有最低字典序
* 给定一个字符串类型的数组strs[],找到一种拼接方式,使得把所 * 有字 符串拼起来之后形成的字符串具有最低的字典序。 * 贪心策略。import java.util.Arrays;import java.util.Comparator;public class C02_LowestLexicography { //贪心策略 public static String lowestS...原创 2018-03-19 22:51:02 · 369 阅读 · 0 评论 -
切金条问题
一块金条切成两半,是需要花费和长度数值一样的铜板的。比如 长度为20的 金条,不管切成长度多大的两半,都要花费20个铜 板。一群人想整分整块金 条,怎么分最省铜板? 例如,给定数组{10,20,30},代表一共三个人,整块金条长度为 10+20+30=60. 金条要分成10,20,30三个部分。 如果, 先把长 度60的金条分成10和50,花费60 再把长度5...原创 2018-03-20 19:59:24 · 1051 阅读 · 0 评论 -
项目最大收益(贪心问题)
输入: 参数1,正数数组costs 参数2,正数数组profits 参数3,正数k 参数4,正数m costs[i]表示i号项目的花费 profits[i]表示i号项目在扣除花 费之后还能挣到的钱(利润) k表示你不能并行、只能串行的最多做k个项目 m表示你初始的资金 说明:你每做完一个项目,马上获得的收益,可以支持你去做下一个 项目。 输出: 你最后获得的最大钱数...原创 2018-03-20 21:20:13 · 2686 阅读 · 0 评论 -
活动安排问题2
/** * 活动安排问题 * 一些项目要占用一个会议室宣讲,会议室不能同时容纳两个项目 * 的宣讲。 给你每一个项目开始的时间和结束的时间(给你一个数 * 组,里面 是一个个具体的项目),你来安排宣讲的日程,要求会 * 议室进行 的宣讲的场次最多。返回这个最多的宣讲场次。 */import java.util.Arrays;import java.util.Comparator;...原创 2018-03-20 22:08:59 · 295 阅读 · 0 评论 -
归并排序及其应用
归并排序(英语:Merge sort,或mergesort),是建立在归并操作上的一种有效的排序算法,效率为O(n*log n)} 。1945年由约翰·冯·诺伊曼首次提出。该算法是采用分治法(Divide and Conquer)的一个非常典型的应用,且各层分治递归可以同时进行。import java.util.Arrays;import java.util.Random;public cla...原创 2018-03-30 14:33:53 · 491 阅读 · 0 评论 -
如何反转单向链表和双向链表( 空间复杂度O(1) )
反转链表,最简单的就是使用栈了,放进栈里然后拿出来,但这样的操作使用的空间复杂度是O(N)..其实可以做到空间复杂度是O(1)的。public class C08_RevolveLinked1 { // 单向链表 public static class Node { int value; Node next; public Node(int value) { this.va...原创 2018-04-01 21:11:12 · 2716 阅读 · 0 评论 -
两个单链表相交的一系列问题(成环,不成环)
【题目】 在本题中,单链表可能有环,也可能无环。给定两个 单链表的头节点 head1和head2,这两个链表可能相交,也可能 不相交。请实现一个函数, 如果两个链表相交,请返回相交的 第一个节点;如果不相交,返回null 即可。 要求:如果链表1 的长度为N,链表2的长度为M,时间复杂度请达到 O(N+M),额外 空间复杂度请达到O(1)。我们将问题分为四个部...原创 2018-04-10 23:06:05 · 1086 阅读 · 0 评论 -
最小的路径和
/** 给你一个二维数组,二维数组中的每个数都是正数,要求从左上 角走到右下角,每一步只能向右或者向下。沿途经过的数字要累 加起来。返回最小的路径和。 */public class C02_MinPath { //递归版本--recurtion public static int recMinPath(int[][]matric,int i,int j){ int res = m...原创 2018-03-22 21:57:52 · 386 阅读 · 0 评论 -
生成图、表示图的一个强大方法
图的表示一般是可以使用邻接表、邻接矩阵……来表示的,网上大把,这里介绍的是一种更为强大的方式,基本上可以应对所有的关于图的算法,例如拓扑排序、深搜、广搜、Kruskal、Prim、Dijkstra。创建图的时候是传递一个二维数组过来,matrix[i][0]是权重,matrix[i][1]是起始点的值,matrix[i][2]是终止点的值,最后返回一张图。public class GraphGen...原创 2018-03-26 15:26:49 · 3131 阅读 · 0 评论 -
非递归 宽度优先遍历图(BFS)
流程: 1,利用队列实现 2,从源节点开始依次按照宽度进队列,然后弹出 3,每弹出一个点,把该节点所有没有进过队列的邻接点放入队 列 4,直到队列变空图的表示和生成见:点击打开链接import java.util.HashSet;import java.util.LinkedList;import java.util.Queue;public clas...原创 2018-03-26 15:31:21 · 660 阅读 · 0 评论 -
深度优先遍历图(DFS)
流程: 1,利用栈实现 2,从源节点开始把节点按照深度放入栈,然后弹出 3,每弹出一个点,把该节点下一个没有进过栈的邻接点放入栈 4,直到栈变空图的表示和生成见:点击打开链接import java.util.HashSet;import java.util.Set;import java.util.Stack;public class DFS { pub...原创 2018-03-26 15:36:41 · 631 阅读 · 0 评论 -
拓扑排序算法(TopologySort)
拓扑排序算法 适用范围:要求有向图,且有入度为0的节点,且没有环 1.将图中的所有节点全部记录到HashMap,入度为零的节点添加到zeroInQueue 2.建立一个集合用来存放结果 3.从zeroInQueue中弹出一个,遍历她的子节点 4.将其子节点入度减一 5.如果这个子节点的入度为零了,就将其放入到zeroInQueue中图的表示和生成见:点击打开链...原创 2018-03-26 15:39:22 · 2854 阅读 · 0 评论 -
最小生成树--Prim算法
条件:无向图任意一个点作为开端,将该点的所有边加到优先级队列,表示边被解锁,从队列中弹出一条边(必是权重最小的)看该边是否已经标记,如果没标记就标记,表示这条边是需要的,然后将该边的相连的另一个点相连的所有边解锁,,,如此类推图的表示和生成见:点击打开链接import java.util.Comparator;import java.util.HashSet;import java.util....原创 2018-03-26 21:34:58 · 1168 阅读 · 0 评论 -
最小生成树--Kruskal算法
条件:无向图从边开始,将所有边加到优先级队列里面,依次弹出,如果该边起点和终点不是在同一个并查集里面,就将该边加到结果集合里面,并且将这两个点合并到同一个并查集里图的表示和生成见:点击打开链接import java.util.Collection;import java.util.Comparator;import java.util.HashMap;import java.util.Has...原创 2018-03-26 21:42:46 · 2342 阅读 · 0 评论 -
归并排序
归并的思想其实不难,就是假设有两个有序数组a,b,现在需要把它合并成一个有序的数组,要是使用快排或者其他的排序(除了桶排序)理论值就达到了O(N*logN)了,假如我建立一个数组c,长度是他们两个数组的和,然后从两个数组a,b他们的第一个值来比较,将小的放到c的前面,然后指针下移一个位置,再拿出两个数组前面的较小值放到c,,,这样就使用了O(N)的时间复杂度完成了排序。剩下的就是递归的问题了,这个...原创 2018-03-18 19:09:19 · 203 阅读 · 0 评论 -
认识并查集结构
并查集是1964年别人脑补的一个算法,到证明结束是1989年,这个证明也是够漫长的。并查集的效率非常高,当有N个数据的时候,假设查询次数到了N之后,其时间复杂度仅为O(1)!!并查集使用哈希是来做的,所以节点中并不需要放些什么。FatherMap中key 是当前节点,value是当前节点的父节点。然后是sizeMap,key是当前节点,value是点当前节点的所在集合的节点总个数。getHeadN...原创 2018-03-19 13:18:35 · 216 阅读 · 0 评论 -
如何判断一棵二叉树是否平衡
平衡二叉树就是AVL树,定义也很简单,就是一棵树的每一个节点的左右子树高度相差不超过1。AVL树具有数组和链表的优点,方便查找也方便插入,时间复杂度仅为O(height),height就是树的高度,所以为什么需要平衡二叉树就显而易见了,就是效率!!那么如何判断一棵树是否是平衡的呢,使用递归可以很好很方便地解决这个问题,public class C05_BalanceTree { public s...原创 2018-03-12 21:28:45 · 736 阅读 · 0 评论 -
怎么计算一棵完全二叉树的节点个数
题目:已知一棵完全二叉树,求其节点的个数要求:时间复杂度低于O(N),N为这棵树的节点个数完全二叉树的概念就不多叙述了。讲讲思路:题目的要求是时间复杂度低于O(N),所以遍历的方式就不用考虑了,根据完全二叉树的特点可以知道,从头节点head开始一直往左走可以可以到达完全二叉树的最底层,而就是可以计算出二叉树的高度H了,(默认给定的一定是完全二叉树,,,)1)当头结点的右子节点作为头节点来计算他的高...原创 2018-03-13 22:00:58 · 10433 阅读 · 0 评论 -
设计RandomPool结构
设计RandomPool结构 【题目】 设计一种结构,在该结构中有如下三个功能: insert(key):将某个key加入到该结构,做到不重复加入。 delete(key):将原本在结构中的某个key移除。 getRandom(): 等概率随机返回结构中的任何一个key。 【要求】 Insert、delete和getRandom方法的时间复杂度都是O(1)im...原创 2018-03-15 20:49:47 · 936 阅读 · 1 评论 -
如何在二叉树中找到一个节点的后继节点
【题目】 现在有一种新的二叉树节点类型如下: public class Node { public int value; public Node left; public Node right; public Node parent; public Node(int data) { t...原创 2018-03-11 16:43:44 · 1843 阅读 · 0 评论 -
如何直观地打印一棵二叉树
二叉树是很常用的数据结构,但有时又会苦于没有办法对其进行直观的了解,如果你说可以使用遍历的方式来看他的结构,那么很对不起,这个方法并不是每次都靠谱的。这个时候,如果能有一个函数直观地看到二叉树的结构就很棒了,这里和大家分享一个这样的函数,虽然不是平常我们所看到的从上到下而是从左到右看的,但已经很不错了哦。看的时候,请把你的脑袋瓜逆时针转九十度当然了,这个代码是左老师给的,,,可以作为工具类使用pu...原创 2018-03-11 20:06:37 · 7624 阅读 · 0 评论 -
使用二分对插入排序进行优化
/* * test经过二分进行优化的插入排序(在工程上的基本数据类型排序其实当数据量少的时候是使用二分的) * 插排时间复杂度是O(N*N) * 经过二分的优化可以达到O(N*log(N)) * 插入排序具有 稳定性(假定在待排序的记录序列中,存在多个具有相同的关键字的记录,若经过排序,这些记录的相对次序保持不变,即在原序列中) */import java.util.Arrays;i...原创 2018-03-15 14:10:33 · 372 阅读 · 0 评论 -
最大差值问题
/** 给定一个数组,求如果排序之后,相邻两数的最大差值,要求时 间复杂度O(N),且要求不能用非基于比较的排序(桶排序) 分析:题目要求了不能使用 非基于比较的排序,但是我们可以借用桶排序的概念 假设有N个数,设置N+1个桶,将数放到桶中,最大值放到最后一个桶, 最小值放到第一个桶,故中间一定存在一个空桶(至少) 设计空桶的目的是否定最大差值来之一个桶内,而不是说最大差值一定在空...原创 2018-03-05 22:41:38 · 1027 阅读 · 0 评论 -
用数组结构实现大小固定的栈和队列
用数组结构实现大小固定的栈和队列,这是一个面试的常考题目,也是一个比较简单的题目。1.实现栈结构:栈结构是先进后出的,只需要一个数组和一个记录位置的变量size,当进来一个元素,size就++,出去一个元素size就--。2.实现队列结构:相对栈结构要难搞一些,队列的先进先出的,需要一个数组和三个变量,size记录已经进来了多少个元素,in记录刚进来的元素应该放在哪个位置,out表示用户要求弹出的...原创 2018-03-06 21:07:12 · 945 阅读 · 0 评论 -
队列实现栈 和 栈实现队列
如何仅用队列实现一个栈?如何仅用栈实现一个队列?这是一个简单的问题,但要是思维被限制了,就很难搞得定。大体的思路就是利用队列先进先出的特点来实现一个栈,将队列1的元素倒入队列2中,将最后一个元素返回就是了。实现队列也是同样的道理。/** * 利用两个队列实现一个栈 * 功能:push,pop,peek */import java.util.LinkedList;import java....原创 2018-03-07 21:12:36 · 422 阅读 · 0 评论 -
转圈打印矩阵
给出一个矩阵,例如 int arr[][] = new int[][]{ {1,2,3,4}, {5,6,7,8}, {9,10,11,12}, {13,14,15,16} };要求转圈打印,结果是:1 2 3 4 8 12 16 15 14 13 9 5 6 7 11 10 很容易就 局限与怎么从1打印到4,然后从4到16,,,这样局部的思维模式。这种关于打印一个矩...原创 2018-03-08 20:36:49 · 530 阅读 · 0 评论 -
顺时针旋转矩阵九十度
/** * 将一个矩阵(一定是正方形)顺时针旋转九十度 */public class C06_RotateMatrix { public static void rotateMatrix(int[][]arr){ if(arr==null || arr.length==0 || arr[0].length==0){ return ; } int a = 0;//左上角,列...原创 2018-03-08 21:21:24 · 1648 阅读 · 0 评论 -
之字形打印矩阵
题目看图:这个题目给人的第一感觉就是,这个出题人脑子又泡吧。之字形打印?太无聊了,其实这个是一种宏观调度思想的实例。我前面也有写过两个相关题目:转圈打印,旋转矩阵讲讲思路:如果限制自己的思路,这个题目是十分难以实现的,和前面两个题目一样,需要两个点来控制走向A(aR,aC),B(bR,bC)(行,列).A点只向右走,当走到最右点的时候,就向下走,B点向下走,当到达最下点的时候就向右走,这样就形成了...原创 2018-03-09 19:33:15 · 501 阅读 · 0 评论 -
在行列都排好序的矩阵中找数
题目看图:很简单的一个题目,好像剑指offer里面有个一样的题。因为题目给定的条件十分特殊,行列都是排好序的,所以只需要从右上或者左下角开始找,假设从右上角(A点)开始找,根据排好序的题设,可以知道,如果要找的数B大于A则B向下走一步在比较,否则向左走一步在比较,这样一直走到边界。下面看代码:public class C08_FindNumInSortMatrix { public static...原创 2018-03-09 20:13:19 · 181 阅读 · 0 评论 -
复制含有随机指针节点的链表
【题目】 一种特殊的链表节点类描述如下:public class Node { public int value; public Node next; public Node rand; public Node(int data) { this.value = data; }}Node类中的value是节点值,next指针和正常单链表中ne...原创 2018-03-09 23:27:04 · 270 阅读 · 0 评论 -
实现二叉树的先序、中序、后序遍历,包括递归方式和非递归方式
public static class Node{ public int value; public Node left; public Node right; public Node(int value){ this.value = value; } } 递归版 先序 //先序:中左右 public static void preTr...原创 2018-03-10 21:17:37 · 367 阅读 · 0 评论 -
经典快排和随机快排
/** * 经典快排、随机快排 * 经典快排:利用最后一个数作为分界点,小的放左边,大的放右边,可以使用荷兰国旗问题(文末)的方法优化 * 随机快排:产生一个随机位置作为分界点 */import java.util.Arrays;public class C04_QuickSort { public static void quickSort(int[]arr){ if(arr...原创 2018-02-28 14:29:56 · 3785 阅读 · 2 评论 -
堆排序
想学会堆排序,就应该先理解堆结构。堆分为大根堆和小根堆,大根堆就是所有的根节点都比他的子节点都要大,小根堆同理。我们进行堆排序的时候,其实并不是真的要用到二叉树(完全二叉树),而只是借用这个知识来理解,可以将一个数组想象成一棵树。例如i节点的父节点就是(i+1)/2,i节点的左子节点就是i*2+1,右子节点就是i*2+2。heapInsert:将数组的0到1位置的数变成一个大根堆,然后...原创 2018-03-02 16:05:24 · 290 阅读 · 0 评论 -
对数器的概念和使用
对数器在无法进行数据校验的情况下起着极为重要的作用,尤其是数据量大的时候。这里使用简单的冒泡排序进行演示/** 冒泡排序 并使用对数器进行校验 对数器的概念和使用 0)有一个你想要测的方法a, 1)实现一个绝对正确但是复杂度不好的方法b, 2)实现一个随机样本产生器 3)实现比对的方法 4)把方法a和方法b比对很多次来验证方法a是否正确。 5)如果有一个样本使得比对出错,打印样本...原创 2018-02-24 17:34:49 · 805 阅读 · 1 评论 -
时间复杂度
常数时间的操作:一个操作如果和数据量没有关系,每次都是固定时间内完成的操作,叫做常数操作。时间复杂度为一个算法流程中,常数操作数量的指标。常用O来表示。具体来说,在常数操作数量的表达式中,只要高阶项,不要低阶项,也不要高阶项的系数,剩下的部分如果记为f(N),那么时间复杂度为O(f(N))。评价一个算法流程的好坏,先看时间复杂度的指标,然后再分析不同数据样本下的实际运行时间,也就是常数项时间mas...原创 2018-02-25 13:33:13 · 287 阅读 · 0 评论 -
程序员代码面试指南--生成窗口最大值数组
/** 生成窗口最大值数组 【题目】 有一个整城数组arr和一个大小为w的窗口从数组的最左边滑到最右边,容口每次向右边滑一个位置。 如果数组长度为n,窗口大小为w,则一共产生n-w+1个窗口的最大值。 请实现一个函数。 -输入:整型数组arr,窗口大小为w。 -输出:一个长度为n-w+1的数组res,res[]表示每一种窗口状态下的最大值。 *//** 假设遍历到arr[i],...原创 2018-02-10 16:10:25 · 225 阅读 · 0 评论 -
程序员代码面试指南--设计一个具有getMin功能的栈
/* 设计一个有getMin功能的栈 【题目】 实现一个特殊的栈,在实现栈的基本功能的基础上,再实现返回 栈中最小元素的操作。 【要求】 1.pop、push、getMin操作的时间复杂度都是O(1)。 2.设计的栈类型可以使用现成的栈结构。在设计上我们使用两个栈,一个栈用来保存当前栈中的元素,其功能和一个正常的栈没有区别,这个栈记为stackData;另一个栈用于保存每原创 2018-02-04 16:21:06 · 238 阅读 · 0 评论 -
程序员代码面试指南--由两个栈组成的队列
/** 由两个栈组成的队列 【题目】编写一个类,用两个栈实现队列,支持队列的基本操作(add、pollpeek)。 栈的特点是先进后出,而队列的特点是先进先出。我们用两个栈正好能把顺序反过来实现类似队列的操作。 具体实现上是一个栈作为压入栈,在压入数据时只往这个栈中压入, 记为stackPush;另一个栈只作为弹出栈,在弹出数据时只从这个栈弹出,记为stackPop。 因为数据压入原创 2018-02-04 22:38:40 · 210 阅读 · 0 评论 -
程序员代码面试指南--如何仅用递归函数和栈操作逆序一个栈
/** 如何仅用递归函数和栈操作逆序一个栈 【题目】 一个栈依次压入1、2、3、4、5,那么从栈顶到栈底分别为5、4、 3、2、1。将这个栈转置后,从栈顶到栈底为1、2、3、4、5,也就 是实现栈中元素的逆序,但是只能用递归函数来实现,不能用其他数 据结构。 */import java.util.Stack;public class C03_ReverseStackUsing原创 2018-02-06 17:05:37 · 208 阅读 · 0 评论