数据结构与算法
cqu_shuai
实事求是,不自以为是
展开
-
数据结构与算法——求二叉树的深度
使用递归算法求二叉树的深度计算二叉树的深度,一般都是用后序遍历,采用递归算法,先计算出左子树的深度,再计算出右子树的深度,最后取较大者加1即为二叉树的深度struct TreeNode{ int data; TreeNode* left=nullptr; TreeNode* right=nullptr;};int TreeDepth(TreeNode* root){ if (!root) { return 0; } int left_height = TreeDepth(ro原创 2021-09-02 00:49:50 · 9889 阅读 · 0 评论 -
数据结构与算法——非递归实现二叉树的遍历
非递归实现二叉树的遍历树的遍历可以用递归实现,程序中递归的调用就是保存函数的信息在栈中。一般情况下,能用递归解决的问题都可以用栈解决,只是递归更符合人们的思维方式,代码相对而言也更简单,但不能说明递归比栈的方式更快、更节省空间,因为在递归过程中都是操作系统来帮助用栈实现存储信息非递归实现二叉树的后序遍历对于后序遍历,应该在父节点入栈时就把右左孩子一并入栈。在父节点出栈时,应该判断右左孩子是否已经遍历过(是否执行过入栈),那么就应该有一个标记来判断孩子是否遍历过定义一个适用于这个算法的结构体:typ原创 2021-09-01 23:13:49 · 425 阅读 · 0 评论 -
数据结构与算法——从尾到头打印链表
参考《剑指offer》从尾到头打印链表题目输入一个链表的头节点,从尾到头反过来打印出每个节点的值链表节点定义如下:struct ListNode{ int m_nKey; ListNode* m_pNext;};解法栈通常打印是一个只读操作,不希望打印时修改内容,所以解决这个问题肯定要遍历链表。要按与遍历相反的顺序输出节点,就是先进后出,可以使用栈实现。每经过一个节点,把该节点放到一个栈中。当遍历完整个链表后,再从栈顶开始逐个输出节点的值#include<原创 2021-08-18 17:09:13 · 155 阅读 · 0 评论 -
数据结构与算法——替换空格
参考《剑指offer》替换空格题目请实现一个函数,把字符串中的每个空格替换成“%20”解法先遍历一次字符串,统计出字符串中空格的总数,并计算出替换后的字符串的总长度。每替换一个空格,长度增加2,因此替换后字符串的长度等于原来的长度加上2乘以空格数目然后从字符串的后面开始复制和替换。首先准备两个指针:P1和P2。P1指向原始字符串的末尾,而P2指向替换后的字符串的末尾。接下来向前移动P1,逐个把它指向的字符串复制到P2指向的位置,碰到空格后,把P1向前移动1格,在P2之前插入字符串“%20”原创 2021-08-18 13:13:54 · 135 阅读 · 0 评论 -
数据结构与算法——二维数组中的查找
参考链接《剑指Offer》二维数组中的查找题目在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数解法首先选取数组中右上角的数字。如果该数字等于要查找的数字,则查找过程结束;如果该数字大于要查找的数字,则剔除这个数字所在的列;如果该数字小于要查找的数字,则剔除这个数字所在的行。也就是说,如果要查找的数字不在数组的右上角,则每一次都在数组的查找范围中剔除一行或者一列,这样每一步都可以原创 2021-08-14 00:15:00 · 165 阅读 · 0 评论 -
数据结构与算法——排序
参考链接https://github.com/forthespada/InterviewGuide/排序选择排序选择排序是一种简单直观的排序算法,它的基本原理如下:对于给定的一组记录,经过第一轮比较后得到最小的记录,然后将该记录与第一个记录进行交换;接着对不包括第一个记录外的其他记录进行第二轮的比较,得到最小的记录,并与第二个记录进行位置交换;重复该过程,直到进行比较的记录只有一个时为止void selectSort(vector<int>& a, int n){原创 2021-07-29 01:10:04 · 245 阅读 · 0 评论 -
数据结构与算法——使用两个栈模拟队列
如何使用两个栈模拟队列操作要求用两个栈来模拟队列,栈A与栈B模拟队列Q,A为插入栈,B为弹出栈,以实现队列Q假设A和B都为空,可以认为栈A提供入队列的功能,栈B提供出队列的功能入队列即入栈A;出队列分两种情况考虑:如果栈B不为空,则直接弹出栈B的数据如果栈B为空,则依次弹出栈A的数据,放入栈B中,再弹出栈B的数据#include <iostream>#include <stack>using namespace std;template <typenam原创 2021-07-27 10:31:56 · 175 阅读 · 0 评论 -
数据结构与算法——实现循环队列
如何实现循环队列在队列的顺序存储中,除了使用一组地址连续的单元依次存放从队列头到队列尾的元素外,还需要另外设置front和rear两个指针,分别指示队列头元素以及队列尾元素的位置。初始化建空队列时,令front=rear=0,每当出入新的队列尾元素时,尾指针增1;而每当删除队列头元素时,则执行头指针增1为充分利用内存空间,克服“假溢出”现象的方法是:将内存空间想象为一个首尾相接的圆环,存储在其中的队列称为循环队列。循环队列中,由于入队时尾指针向前追赶尾指针;出队时头指针向前追赶尾指针,造成队空和队满时头原创 2021-07-27 10:01:47 · 537 阅读 · 0 评论 -
数据结构与算法——删除单链表中的重复结点
如何删除单链表中的重复结点方法一:递归对于一个结点head,首先把链表head->next作为头结点的链表中的重复项删除,然后遍历head->next为头结点的链表中的元素,判断遍历到的元素是否与head结点元素相等,如果相等,则删除。对于head->next为头结点的链表而言,可以使用同样的思路来删除以head->next->next为头结点的链表中的重复元素。因此可以使用递归的方法求解struct ListNode { int val; ListNod原创 2021-07-26 21:54:17 · 9181 阅读 · 0 评论 -
数据结构与算法——判断两个无环单链表是否交叉
如何判断两个无环单链表是否交叉单链表相交指的是两个链表存在完全重合的部分方法一:hash法由于结点的地址可以作为结点的唯一标识,因此可以通过判断两个链表中的结点是否有相同的地址来判断链表是否相交。首先遍历链表head1,把遍历到的所有结点的地址存放到hash表中;接着遍历链表head2,每遍历到一个结点,就判断这个结点的地址在hash表中是否存在,如果存在,那么说明两个链表相交并且当前遍历到的结点就是它们的相交点由于需要分别遍历两个链表,因此算法的时间复杂度为O(n1+n2),n1与n2分别为两个链原创 2021-07-26 21:05:08 · 308 阅读 · 0 评论 -
数据结构与算法——检查一个单链表是否有环
如何检查一个单链表是否有环方法一:暴力定义一个hash_set用来存放结点的指针,初始化为空指针,从链表的头指针开始往后遍历,每次遇到一个指针就判断hash_set是否存在这个结点的指针,如果在hash_set中找到了同样的指针,说明这个结点已经被访问过了,于是就形成了环。这个算法的时间复杂度为O(n),但空间复杂度也为O(n)方法二:快慢指针定义两个指针,分别为fast与slow,二者的初始值都指向头结点,slow每次前进一步,fast每次前进两步,两个指针同时向前移动,快指针每移动一次都要跟慢指原创 2021-07-26 20:33:11 · 406 阅读 · 0 评论 -
数据结构与算法——二分搜索模板
参考链接https://labuladong.gitee.io/algo/二分搜索模板最基本的二分搜索int binary_search(vector<int> nums, int target){ int left = 0; int right = nums.size() - 1; while (left <= right) { int mid = left + (right - left) / 2; if (原创 2021-07-26 17:52:57 · 71 阅读 · 0 评论 -
数据结构与算法——实现单链表反转
如何实现单链表反转方法一:就地逆序在遍历链表的时候,修改当前结点的指针域的指向,让其指向它的前驱结点。为此需要用一个指针变量保存前驱结点的地址。此外,为了在调整当前结点指针域的指向后还能找到后继结点,还需要另外一个指针变量来保存后继结点的地址。除此之外,还需要特别注意对链表首尾结点的特殊处理struct ListNode { int val; ListNode *next; ListNode() : val(0), next(nullptr) {} ListNode(i原创 2021-07-26 17:18:01 · 399 阅读 · 0 评论 -
数据结构与算法——将单链表向右旋转k个位置
如何将单链表向右旋转k个位置给定1->2->3->4->5->6->7,k=3,那么旋转后的链表变为5->6->7->1->2->3->4主要思路:首先找到链表倒数第k+1个结点的尾结点slow和尾结点fast把链表断开为两个子链表,其中后半部分子链表结点的个数为k使原链表的尾结点指向链表的第一个结点使链表的头结点指向原链表倒数第k个结点这种方法只需要对链表进行一次遍历,因此时间复杂度为O(n),空间复杂度为O(1)原创 2021-07-26 11:46:32 · 764 阅读 · 0 评论 -
数据结构与算法——找出单链表中的倒数第k个元素
如何找出单链表中的倒数第k个元素方法一:顺序遍历两遍首先遍历一遍单链表,求出整个单链表的长度n,然后把求倒数第k个元素转换为求正数第n-k个元素,再去遍历一次就可以得到结果方法二:快慢指针法在查找过程中,设置两个指针,让其中一个指针比另一个指针先前移k步,然后两个指针同时往前移动。循环,直到先行的指针值为NULL时,另一个指针所指的位置就是所要找的位置struct ListNode { int val; ListNode *next; ListNode() : val(0)原创 2021-07-26 11:35:01 · 1281 阅读 · 0 评论 -
数据结构与算法——重新排列数组,使得数组左边为奇数,右边为偶数
重新排列数组,使得数组左边为奇数,右边为偶数给定一个存放整数的数组,如何重新排列数组,使得数组左边为奇数,右边为偶数。要求:空间复杂度为O(1),时间复杂度为O(N)可以用两个指针分别指向数组的头和尾,头指针正向遍历数组,找到第一个偶数,尾指针逆向遍历数组,找到第一个奇数,交换两个指针指向的数字,然后两指针沿着相应的方向继续向前移动。重复上述步骤,知道头指针大于尾指针为止void swap(int& a, int& b){ int temp = a; a = b; b = te原创 2021-07-25 14:00:42 · 1246 阅读 · 0 评论 -
数据结构与算法——找出数组中出现奇数次的元素
如何找出数组中出现奇数次的元素只有一个数出现奇数次给定一个含有n个元素的整型数组array,其中只有一个元素出现奇数次,找出这个元素将array中所有元素进行异或,那么个数为偶数的元素异或后都变成了0,只留下了个数为奇数的那个元素int findElementWithOddCount(vector<int> &a, int n){ int r = a[0]; for (int i = 0; i < n; ++i) { r ^= a[i]; } return原创 2021-07-25 13:21:20 · 1775 阅读 · 1 评论 -
数据结构与算法——判断一个数组中的数值是否连续
如何判断一个数组中的数值是否连续一个整数数列,元素的取值可能是0~65535中的任意一个数,相同数值不会重复出现;0是例外,可以反复出现。设计一个算法,当从该数列中任意选取n个数值时,判断这n个数值是否连续相邻。需要注意以下4点:n个数值允许是乱序的0可以通配任意数值0可以多次出现全0算连续,只有一个非0算连续如果没有0的存在,要组成连续的数组,最大值和最小值的差距必须是n-1,存在0的情况下,只要最大值和最小值的差距小于n-1即可。所以找出数组中非0的最大值和非0的最小值,时间复杂度为O(原创 2021-07-25 12:14:01 · 4754 阅读 · 0 评论 -
数据结构与算法——找出数组中唯一的重复元素
如何找出数组中唯一的重复元素数组a[N],1~N-1这N-1个数存放在a[N]中,其中只有唯一的一个数重复了,写一个函数,找出这个重复的数字。要求每个数组元素只能访问一次,不用辅助存储空间方法一:求和法因为只有一个数字重复一次,而数又是连续的,根据累加和原理,对数组的所有项求和,然后减去1~N-1的和,即为所求的重复数int findDup(vector<int> &a, int N){ int temp1 = 0; int temp2 = 0; for (int i =原创 2021-07-25 11:06:54 · 885 阅读 · 0 评论 -
数据结构与算法——在O(n)的时间复杂度内找出数组中出现次数超过了一半的数
如何在O(n)的时间复杂度内找出数组中出现次数超过了一半的数方法一:hash法首先创建一个hash_map,其中,key为数组元素值,value为此数出现的次数。遍历一遍数组,用hash_map统计每个数出现的次数,并用两个值存储目前出现次数最多的数和对应的次数,此时的时间复杂度为O(n),空间复杂度为O(n)方法二如果每次删除两个不同的数,那么在剩余的数字里,原出现次数最多的数出现的频率一样超过了50%,不断重复这个过程,最后剩下的将全是同样的数字。具体实现为:使用两个变量A和B,其中变量A存储原创 2021-07-24 23:45:23 · 335 阅读 · 0 评论 -
使用递归算法判断一个数组中的元素是否递增
使用递归算法判断一个数组中的元素是否递增设数组为a,则递增数组需要满足以下条件:如果数组长度为1,则该数组为递增,返回true如果数组长度为(n≥2),则先比较最后两个元素是否递增,如果最后两个元素递增,则再递归比较前n-1个元素是否递增bool isIncrease(vector<int> &a, int n){ if (n <= 1) { return true; } else { return a[n - 1] >= a[n-2] &am原创 2021-07-24 19:14:34 · 1137 阅读 · 0 评论 -
数据结构与算法——用一个for循环打印多维数组
如何用一个for循环打印多维数组打印二维数组二维数组在内存中是按行存储的,所以可以将数组array看出是一个一维数组,设i表示该数组在一维数组中的位置,array在二维数组中的行号和列号分别为[i/MAXY]、[i%MAXY]#define MAXY 2#define MAXY 3void printArray(){ int i; int array[MAXX][MAXY] = {1, 2, 3, 4, 5, 6}; for (i = 0; i < MAXX * MAXY; i++原创 2021-07-24 19:06:31 · 428 阅读 · 0 评论 -
数据结构与算法——数组中重复的数字
参考《剑指offer》数组中重复的数字题目一:找出数组中重复的数字在一个长度为n的数组里的所有数字都在0~n-1的范围内。数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了几次。请找出数组中任意一个重复的数字解法一一个简单的方法是先把输入的数组排序,然后从头到尾扫描排序后的数组即可。排序一个长度为n的数组需要O(nlogn)的时间解法二还可以利用哈希表来解决。从头到尾按顺序扫描数组的每个数字,每扫描到一个数字的时候,都可以用O(1)的时间判断哈希表里是否包含了该数字原创 2021-07-21 19:08:29 · 239 阅读 · 0 评论