![](https://img-blog.csdnimg.cn/20201014180756928.png?x-oss-process=image/resize,m_fixed,h_64,w_64)
面试数据结构和算法
重复的名字
这个作者很懒,什么都没留下…
展开
-
如何求数组中两两相加等于20的数
方法一:蛮力法直接双重循环数组拍判断两个数是否相加等于20,但是这种方法的时间复杂度是O(n^2)。方法二:排序法首先将数组进行有小到大排序,将设从前到后遍历的下标为begin,而从后到前遍历的下标是end。如果arr[begin]+arr[end] > 20,那么说明end需要–。相反,如果arr[begin]+arr[end] < 20, 那么begin++。如果正好等于20,那么begin和end都进行改变(原数组中没有相同的值)。代码实现:首先排序算法选用性能较好稳定的快速排序原创 2020-06-12 15:57:47 · 763 阅读 · 0 评论 -
如何求最大子数组之和
问题概述:有一个长度为n的数组,这n个元素可以使正数也可以是负数,数组中连续的一个或多个元素可以组成一个连续的子数组,一个数组可以有多个这样连续的子数组,求子数组各个元素和的最大值。方法一:蛮力法找出所有子数组元素,进行求和,然后找到和的最大值public static int findSecond(int[] arr){ int n = arr.length; int thisSum= 0; int maxSum = 0; fo原创 2020-06-11 16:47:58 · 1496 阅读 · 0 评论 -
找出数组中最大值和最小值的集中常见方法
问题分解法把问题看做成两个独立的问题,即求最大值和求出最小值。所以需要经过两次遍历,比较的次数为2N。取单元素法维持两个变量min和max,min记录着最小值,max记录着最大值,每次取出一个数,将该数和min和max进行两次比较,只需要遍历一次的情况下就可以得到数组中的最大值和最小值。取双元素法位置两个变量min和max,每次取出两个数,首先比较取出的两个数,较大者和max进行比较,而较小者就和min进行比较。代码实现:public static void findMaxAndM原创 2020-06-11 15:47:13 · 757 阅读 · 0 评论 -
位运算(判断一个数是否是2的n次方;如何求二进制数中1的个数)
如何判断一个数是否是2的n次方最直观思想是用1做移位操作代码实现: public static boolean isPower(int n){ int i=1; if (n < 1) return false; while (i <= n){ if (i == n){ return true; } i <<= 1;原创 2020-06-11 09:18:49 · 1122 阅读 · 1 评论 -
各种排序算法有什么优劣
直接上图–各种排序算法的性能表由表中数据可以得出的结论(1):简单的说,所有相等的元素在经过某种排序后依然能够保持排序之前的相对次序,那么就称这种排序是稳定的。上述稳定的排序算法有:直接插入排序,冒泡排序,归并排序。其他的都是不稳定排序算法。(2):时间复杂度为O(n)的排序算法有:直接选择排序,直接插入排序,冒泡排序,其它的都为O(logn)的时间复杂度。(3):虽然直接选择排序和冒泡排序的时间复杂度较高,但是当待排序序列基本有序的时候,他们的效率还是蛮高的。当初始序列基本有序或者局部有序的时候原创 2020-06-10 15:25:09 · 335 阅读 · 0 评论 -
概述希尔排序和堆排序
希尔排序希尔排序又称为缩小增量排序,其原理如下:先将待排序的数组元素分成多个子序列,使得每个子序列的元素个数相对较少,然后对每个子序列分别进行直接插入排序,待整个序列基本有序后,再对所有元素进行一次快速排序。希尔排序的步骤:选择一个步长序列:t1,t2,t3,t4,…,tk,满足ti > tj(i<j),tk=1;对于步长序列为k,对待排序序列进行k趟排序。每趟排序,根据对应步长ti,将待排序序列分割成ti个子序列,分别对各个子序列进行直接插入排序。注意:当步长为1的时候,所有原创 2020-06-10 14:59:08 · 449 阅读 · 0 评论 -
概述快速排序
快速排序是一种非常高效的排序算法,它采用了“分而治之”的思想,把大的拆分为小的,小的拆分为更小的。原理:对于一个给定的记录,通过一趟排序后,将原序列拆分为两个部分,其中前面一部分的所有记录均比后一部分的所有记录小,然后在依次对前后两部分的记录进行快速排序,递归该过程,直到序列中所有的记录均为有序为止。整个演示的过程:初始化关键字【49,38,65,97, 76,13,27,49】第一趟排序【27,38,13】,49,【76,97,65,49】第二趟排序【13】,27,【38】,49,【49原创 2020-06-10 11:32:18 · 130 阅读 · 0 评论 -
概述归并排序
归并排序是利用递归和分治思想将数据序列划分为越来越小的半子表,再对半子表进行排序,最后利用递归的方法将排好序的半子表合并成为越来越大的有序序列。代码实现:public static void merge(int[] array, int p, int q, int r) { int i, j, k, n1, n2; n1 = q - p + 1; n2 = r - q; int[] L = new int[n1]; int[原创 2020-06-10 10:39:51 · 120 阅读 · 0 评论 -
基础排序-选择冒泡插入
前言排序问题一直是计算机技术研究的重要问题,排序算法的好坏直接影响到程序的执行速度和辅助存储空间。其中衡量一个排序算法的好坏是通过时间复杂度和空间复杂度判断的。同一说明:待排序的序列是{38,65,97,13,27,49}选择排序基本思想:对于给定的一组待排序记录,经过第一轮比较后得到最小的记录,然后该记录和第一个记录进行位置交换;接着对不包括第一个记录外的其他记录进行第二轮比较,得到最小值和第二个值进行交换,重复上述过程,直到进行比较的记录只有最后一个为止。(0):{38,65,9原创 2020-06-09 21:34:06 · 72 阅读 · 0 评论 -
如何使用两个队列实现栈
在我的上一篇博客中实现了两个栈实现队列的功能采用两个栈实现队列功能使用两个队列实现栈实现思路分析:1)假设使用队列q1和队列q2模拟栈S,q1为入队列,q2为出队列。2)认为q1提供入队列的操作,使用q2提供出队列的操作。3)当需要入队列的时候,直接将数据压入q1栈中即可。4)当需要从队列中取出数据的时候,就需要分情况考虑了。5)若队列q1中只有一个元素,则直接让q1中元素出栈并输出。6)若队列q1中不止一个元素,那么将q1中的元素弹出至q2直到q1中只剩下一个元素为止,然后弹出q1中的元原创 2020-06-09 17:03:59 · 233 阅读 · 0 评论 -
如何使用两个栈来模拟队列
栈或者队列代码需要实现的功能其实不论是栈还是队列,都必须实现:添加、删除、查看队尾(栈顶)元素、判断队列(栈)是否为空等基本的功能。实现思路:1)假设两个栈分别是栈A和栈B,栈A为插入栈,栈B为弹出栈,实现队列Q。2)对于向队列中添加值,只需要向栈A中添加即可3)要实现从队列中取出数据的操作,就需要根据栈B中是否存在元素来进行分条件操作。4)如果栈B中存在元素,直接弹出。5)如果栈B中不存在元素,依次从栈A中弹出元素放置在栈B中,再弹出栈B中元素。代码实现:public class原创 2020-06-09 16:44:22 · 187 阅读 · 0 评论 -
利用O(1)时间复杂度求栈中最小元素
对于栈实现的两种方式,大家可以看我之前写的一篇博客数组或链表实现栈结构利用O(1)时间复杂度求栈中最小元素基本思想既然题目要求是O(1)的时间复杂度,那么肯定不能采取遍历Stack全部弹出比较的方法,那样的时间复杂度为o(n)在程序设计中,我们很多时候都是采用用空间换取时间实现的时候使用两个栈结构,一个栈用来存储数据,另一个栈使用栈顶存储栈的最小值。思路:如果当前入栈元素比原先栈顶元素小,就把当前元素入栈。在求栈中最小元素的时候,直接将这个栈的栈顶元素返回,这个就是最小元素。代码实现:原创 2020-06-09 10:30:29 · 257 阅读 · 0 评论 -
如何检测一个单链表有环并找出环入口点
解决方法:定义两个指针fast和slow,其中,fast是快指针,slow是慢指针,二者的初始值都指向链表头,slow指针每次前进一步,fast指针每次前进两步,两个指针同时向前移动,快指针移动一次都需要和慢指针进行比较,直到相同位置,就可以证明链表是带环的单链表。public boolean isLoop(Node head){ Node fast = head; Node slow = head; if (fast == null){原创 2020-06-08 22:19:53 · 261 阅读 · 0 评论 -
如何快速的找到单链表的中间节点
方法一最简单想到的就是首先遍历单链表获取到链表的长度,然后计算出长度的一半是多少,然后再从头遍历,找到中间节点缺点:需要遍历两次链表,繁琐。方法二如果是双链表,可以首位并行,相遇的节点就是中间节点。类似于双链表,单链表寻找中间节点可以使用两个指针都指向头部,一个指针每一次走一步,一个指针每一次走两步,移动快速的指针走到表尾的时候,那么慢指针刚好走到中间节点。代码:public Node searchMid(Node head){ Node p = head; Nod原创 2020-06-08 16:52:50 · 1719 阅读 · 4 评论 -
如何从尾到头逆序打印单链表
方法一首先将原链表反转逆序,然后在顺序打印缺点:需要额外的操作,复杂方法二首先顺序遍历单链表,把节点信息保存在Stack中,然后一个一个弹出缺点:需要额外的栈空间,实现起来麻烦方法三递归的本质就是栈结构,自然可以用递归的方式来实现反向输出单链表代码:public void printListReversely(Node head) { if (head != null) { printListReversely(head.next); S原创 2020-06-08 16:38:50 · 194 阅读 · 0 评论 -
如何找出单链表中倒数第K个元素
第一种方法为了找出单链表的倒数第K个元素,需要知道这个单链表的长度是多少,就是需要遍历一遍这个单链表,长度为n,倒数第k个,就是单链表的第(n-k)个元素public Node findLastK(Node head, int k){ Node pNode = head; int n=0; while (pNode.next != null){ n++; pNode = pNode.next;原创 2020-06-08 15:36:08 · 5239 阅读 · 0 评论 -
如何实现链表的反转
为了正确的反转一个链表,需要调整指针的指向(Java中并不存在指针的概念,而是使用与之相似的引用来表示,这里用指针来代替引用)举例查看具体的反转过程:例如,i,m, n是三个相邻的节点,假设经过若干步操作,已经把节点i之前的指针已经调整完毕,这些指针的next域都指向前面一个节点。现在遍历到节点m,当然需要调整它的next域使它指向i。但是这里需要值得注意的是,一旦调整了m指针所指的对象,那么这个链会断开,导致后面节点消失无法访问到,这是因为没有指针指向节点n。所以为了避免链的断裂,在调整m的ne原创 2020-06-08 15:00:08 · 375 阅读 · 0 评论 -
如何从链表中删除重复元素
如何从链表中删除重复元素,最简单的就是遍历链表,将各个节点的信息保存在Hashtable中,若当前访问的值在Hashtable中已经存在,则说明这个数据是重复的,因此就可以删除。具体实现的代码如下:public void deleteDuplecate(Node head){ Hashtable<Integer, Integer> table = new Hashtable<>(); Node tmp = head; Node pre原创 2020-06-08 11:49:56 · 819 阅读 · 0 评论 -
如何实现单链表的增删操作
如何实现单链表的增删操作单链表的概念链表存储特点Java语言中,如下的数据类来实现存储节点的信息单链表的插入操作单链表的删除操作下面链表操作实例给出了链表的具体操作运行结果单链表的概念当节点只包含其后继节点的信息的链表就被称为单链表。链表存储特点可以使用任意一组存储单元来存储单链表中的数据元素(存储单元可以是不连续的),而且除了存储每个数据元素的ai的值外,还必须存储只是其后继元素的信息。Java语言中,如下的数据类来实现存储节点的信息class Node { Node next = null原创 2020-06-07 22:13:02 · 244 阅读 · 0 评论