算法
文章平均质量分 63
Sunny君
这个作者很懒,什么都没留下…
展开
-
深拷贝与浅拷贝
浅拷贝只是对指针的拷贝,拷贝后两个指针指向同一个内存空间,浅拷贝只是增加了一个指针指向已经存在的内存,分配一次内存,调用两次析构函数,会造成内存泄漏。深拷贝不但对指针进行拷贝,而且对指针指向的内容进行拷贝,会申请一个内存,经深拷贝后的指针是指向两个不同地址的指针。释放内存的时候就不会出现在浅拷贝时重复释放同一内存的错误。操作符‘=’的重载。最能体现深层拷贝与浅层拷贝原创 2018-01-29 17:07:43 · 119 阅读 · 0 评论 -
二叉树中为某一值的路径
题目:输入一棵二叉树和一个整数,打印出二叉树中结点值的和为输入整数的所有路径。从树的根结点开始往下一直到叶结点所经过的结点形成一条路径。测试用例:功能测试(二叉树中有一条、多条符合条件的路径,二叉树中没有符合条件的路径)特殊输入测试(指向二叉树根结点的指针为NULL指针)代码如下:struct BinaryTreeNode{ int m_nValue; BinaryTre原创 2018-01-08 22:21:44 · 111 阅读 · 0 评论 -
二叉搜索树的后序遍历序列
题目:输入一个整数数组,判断数组是不是某二叉搜索树的后序遍历的结果。如果是返回true,否则返回false。假设输入的数组的任意两个数字互不相同。分析:例如输入数组{5,7,6,9,11,10,8},则返回true。如果输入数组是{7,4,6,5}。则返回false。在后序遍历得到的序列中,最后一个数字是树的根结点的值。数字中的前面的数字可以分成两部分:第一部分是左子树结点的值,他们都比根原创 2018-01-08 21:58:17 · 119 阅读 · 0 评论 -
从上往下打印二叉树
题目:从上往下打印二叉树的每一个结点,同一层的结点按照从左到右的顺序打印。例如输入 8 / \ 6 10 /\ /\ 5 7 9 11 输出8 6 10 5 7 9 11。分析:使用队列来保存结点代码如下:struct BinaryTreeNode{原创 2018-01-08 21:47:03 · 91 阅读 · 0 评论 -
栈的压入、弹出序列
题目:输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否为该栈的弹出顺序。假设压入栈的所有数字都不相等。例如1、2、3、4、5是该栈的压栈序列,序列4、5、3、2、1是该栈序列对应的一个弹出序列,但4、3、5、1、2就不可能是该压栈序列的弹出序列。分析:解决这个问题我们可以建立一个辅助栈,把输入的第一个序列中的数字依次压入该辅助栈,并按照第二个序列的顺序依次从该栈中弹出数字。原创 2018-01-08 20:57:12 · 128 阅读 · 0 评论 -
包含min函数的栈
题目:定义栈的数据结构,请在该类型中实现一个能够得到栈的最小元素的min函数。在该栈中,调用min、push以及pop的时间复杂度都是o(1)。分析:看到这个问题,我们第一反应是每次压入一个新元素进栈时,让栈中所有的元素排序,让最下的元素位于栈顶,这样就可以在O(1)时间得到最小元素。但是这种思路不能保证最后压入栈的元素最先出栈,因此这个数据结构已经不是栈了。可以在栈内添加一个成员变量存放原创 2018-01-08 17:08:33 · 92 阅读 · 0 评论 -
顺时针打印矩阵
题目:输入一个矩阵。按照从外向里以顺时针的顺序依次打印出每一个数字。例如,如果输入如下矩阵:1 2 3 45 6 7 89 10 11 1213 14 15 16则依次打印出数字1、2、3、4、8、12、16、15、14、13、9、5、6、7、11、10分析:我们可以用循环来打印矩阵,每一次打印矩阵中的一个圈。接下来分析循环结束的条件。假设这个矩阵的行数为原创 2018-01-08 16:12:45 · 107 阅读 · 0 评论 -
两个链表的第一个公共结点
题目:输入两个链表,找出它们的第一个公共结点分析:思路1:碰到这道题,很多人的第一反应就是蛮力法:在第一链表上顺序遍历每个结点,每遍历到一个结点的时候,在第二个链表上顺序遍历每个结点。如果在第二个链表上有一个结点和第一个链表上的结点一样,说明两个链表在这个结点上重合,于是就找到了它们的公共结点。如果第一个链表的长度为m,第二个链表的长度为n,显然该方法的时间复杂度是O(mn)。思路2:原创 2018-01-16 23:16:36 · 202 阅读 · 0 评论 -
数组中的逆序对
题目:在数组中的两个数字如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数。分析:分治思想,采用归并排序的思路来处理先把数组分解成两个长度为2的子数组,再把这两个子数组分解成两个长度为1的子数组。接下来一边合并相邻的子数组,一边统计逆序对的数目。在第一对长度为1的子数组{7}、{5}中7>5,因此(7,5)组成一个逆序对。原创 2018-01-16 22:48:35 · 118 阅读 · 0 评论 -
第一次出现一次的字符
题目:在字符串中找出第一个出现一次的字符。如输入"abaccdeff",则输出'b'。分析:最直观的解法从头扫描这个字符串中的每一个字符。当访问到某个字符的时候拿这个字符和后面的字符相比较,如果在后面没有发现重复的字符,那该字符就是只出现一次的字符。如果字符串有n个字符,每一个字符可能与后面的O(n)个字符比较,一次这种思路的时间复杂度是O(n^2)。另外一种解法就是使用哈希表,实现哈希表原创 2018-01-16 21:56:42 · 239 阅读 · 0 评论 -
二叉树遍历中序非递归/递归、前序非递归/递归、后序遍历非递归/递归、层序遍历
二叉树结点结构struct BinaryTreeNode{ int m_nValue; BinaryTreeNode* m_pLeft; BinaryTreeNode* m_pRight;}struct BinaryTreeNode{ int m_nValue; BinaryTreeNode* m_pLeft; BinaryTreeNode* m_pRight;}原创 2018-01-23 22:35:07 · 128 阅读 · 0 评论 -
排序算法总结
//选择排序void SelectSort(int* data,int length){ if(data==NULL || length<=0) return; for(int i=0;i<length-1;i++) { int min=i; for(int j=i+1;j<length;j++) { if(data[j]<data[min]...原创 2018-01-25 21:56:04 · 194 阅读 · 0 评论 -
复杂链表的复制
题目:请实现函数ComplexListNode* Clone(ComplexListNoed* pHead),复制一个复杂链表。在复杂链表中,每一个结点除了有一个m_pNext指针指向下一个结点外,还有一个m_pSibling指向链表中的任意结点或者NULL,结点的C++定义如下:struct ComplexListNode{ int m_nValue; ComplexListNode*原创 2018-01-09 15:30:13 · 123 阅读 · 0 评论 -
String类的函数实现
普通构造函数/拷贝构造函数/析构函数/赋值运算符函数/+运算符函数/相等运算符函数/索引运算符函数/length函数/友元函数class String{ friend std::ostream& operator<<(std::ostream& os,const string& s);//友元函数public: String(const char* str=NULL);//普通构造函数原创 2018-01-29 15:37:19 · 238 阅读 · 0 评论 -
翻转单词顺序VS左旋转字符串
题目一:输入一个英文句子,翻转句子中单词的顺序,但单词内字符的顺序不变。为简单起见,标点符号和普通字母一样处理。例如输入字符串“I am a student.”,则输出"student. a am I"。分析:第一步翻转句子中所有的字符。比如翻转“I am a student.”中的所有字符“.tneduts a ma I”,此时不但翻转了句子单词的顺序,单词内部的字符顺序也被翻转了.第二步再原创 2018-01-19 22:59:27 · 188 阅读 · 0 评论 -
和为S的两个数字VS和为S的连续正数序列
题目一:输入一个递增序列的数组和一个数字S,在数组中查找两个数,使得它们的和正好是S。如果有多对数字的和等于S,输出任意一对即可。分析:例如输入数组{1、2、4、7、11、15}和数字15。由于4+11=15,因此输出4和11。首先想到可以用两个循环嵌套来查找,但是时间复杂度O(n^2)。显然不是最好的解法,下面我们寻找更加好的解法,我们可以使用两个指针。首先定义两个指针,第一个指针指向数原创 2018-01-19 22:15:12 · 155 阅读 · 0 评论 -
数组中只出现一次的数字
题目:一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。要求时间复杂度为O(n),空间复杂度是O(1)。分析:例如输入数组{2,4,3,6,3,2,5,5},因为只有4、6这两个数字只出现了一次,其他数字都出现了两次,所以输出4和6。我们可以先考虑这个数组中只有一个数字只出现了一次,其他的都出现了两次,来找出这个数字。异或运算的一个性质:任何一个数字异原创 2018-01-19 21:19:32 · 154 阅读 · 0 评论 -
二叉树的深度
题目一:输入一课二叉树的根结点,求该树的深度。从根结点到叶结点依次经过的结点(含根、叶结点)形成树的一条路径,最长路径的长度为树的深度。二叉树的结点定义如下:struct BinaryTreeNode{ int m_nValue; BinaryTreeNode* m_pLeft; BinaryTreeNode* m_pRight;}思路:如果一棵树只有一个结点,它的深度为1。如果根结点只原创 2018-01-19 16:21:57 · 493 阅读 · 0 评论 -
字符串拷贝/字符串比较/字符串连接/字符串长度/字符子串/内存块复制/内存块赋值初始化库函数实现
字符串拷贝、字符串比较、字符串连接、字符串长度、字符子串、内存块复制、内存块赋值初始化//字符串拷贝char* strcpy(char* strDest,const char* strSrc){ assert(strDest!=NULL && strSrc!=NULL); if(strDest==strSrc) return strDest; char *address=strD原创 2018-01-27 21:17:54 · 294 阅读 · 0 评论 -
数字在排序数组中出现的次数
题目:统计一个数字在排序数组中出现的次数,例如输入排序数组{1,2,3,3,3,3,4,5},由于3在这个数组中出现了4次,因此输出4。思路:既然数组是排序的,那我们自然就能想到用二分查找算法。在题目给出的例子中,我们可以先用二分查找算法找到一个3.由于3出现了很多次,因此我们找到的3的左右两边都有3,于是我们在找到3的左右两边顺序扫描,分别找到第一个3和最后一个3。因为我们要查找的数字在长度为n原创 2018-01-19 10:51:36 · 277 阅读 · 0 评论 -
反转链表,递归/非递归实现
Struct ListNode{ int data; ListNode* next;}//递归实现ListNode * ReverseList(ListNode * head){ //如果链表为空或者链表中只有一个元素 if(head==NULL || head->next==NULL) return head; else { ListNode* newHead=Re原创 2018-01-26 21:55:41 · 145 阅读 · 0 评论 -
链表归并排序
Struct ListNode{ int data; ListNode* next;}ListNode* GetMidNode(ListNode* list){ if(list==NULL) return NULL; ListNode* low=list; ListNode* fast=list; while(fast->next->next!=NULL) { l原创 2018-01-26 21:20:53 · 181 阅读 · 0 评论 -
二分查找法递归和非递归实现
//非递归实现int BinarySearch(int A[], int length, int number){ if(A==NULL || length<=0) return -1; int start=0; int end=length-1; while(start<end) { int mid=(start+end)/2; if(A[mid]==number)原创 2018-01-26 16:27:33 · 135 阅读 · 0 评论 -
把数组排成最小的数
题目:输入一个正整数数组,把数组里所有数字拼接起开排成一个数,打印拼接出来的所有数字中最小的一个。例如输入数组{3,32,321},则打印出这3个数字排成的最小数字321323分析:这个题目最直接的做法应该是先求出这个数组中所有数字的全排列,然后把每一个排列拼起来,最后求出拼起来的数字的最小值。但是这道题其实是希望我们能找到一个排序规则,数组按照这个规则排序之后能排成最小的数字。要确定排序规则原创 2018-01-15 14:27:37 · 152 阅读 · 0 评论 -
从1到n整数中1出现的次数
题目:输入一个整数n,求从1到n这那个整数的十进制表示中1出现的次数。例如输入12,从1到12这些整数中包含1的数字有1,10,11,和12,1一共出现了5次解法一:不考虑时间效率的解法 最直观的解法就是累加1到n中每一个整数1出现的次数。我们可以通过对10求余数判断整数的个位数字是不是1,如果这个数字大于10,除以10之后再判断个位数字是不是1.int NumberOf1B原创 2018-01-12 16:30:51 · 167 阅读 · 0 评论 -
连续子数组的最大和
题目:输入一个整型数组,数组中有正数也有负数。数组中有一个或者连续的多个整数组组成一个子数组。求所有的子数组的和的最大值。要求时间复杂度为O(n)。分析:例如输入的数组为{}1,-2,3,10,-4,7,2,-5},和最大子数组为{3,10,-4,7,2},因此输出为该子数组的和18。最直观的解法就是枚举出数组的所有子数组并求出它们的和。一个长度为n的数组,总共有n(n-1)/2个子数组。计算原创 2018-01-12 16:02:24 · 340 阅读 · 0 评论 -
最小的K个数
题目:输入n个整数,找出其中最小的k个数。例如输入4、5、1、6、2、7、3、8这8个数字,则最小的4个数是1、2、3、4.测试用例:功能测试(输入的数组中有相同的数字,输入的数组中没有相同的数字)边界值测试(输入的k等于1或者等于数组的长度)特殊输入测试(k小于1,k大于数组的长度、指向数组的指针为NULL)解法一:O(n)的算法,所使用Partition函数,只有我们可以修改输原创 2018-01-12 15:03:00 · 134 阅读 · 0 评论 -
在O(1)时间删除链表结点
题目:给定单向链表的头指针和下一个结点指针,定义一个函数在O(1)时间删除该结点。链表结点与函数的定义如下:struct ListNode{ int m_nValue; ListNode* m_pNext;};void DeleteNode(ListNode** pListHead,ListNode* pToBeDeleted)思路:图(b)我们首先考虑到可以遍历链表,原创 2018-01-03 17:17:59 · 162 阅读 · 0 评论 -
数组中出现次数超过一半的数字
题目:数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}。由于数字2在数组中出现了5次,超过了数组长度的一半,因此输出2.分析:我们直观的想到,如果是排序的数组,我们就很容易统计出来每一个数字出现的次数。排序的时间复杂度是O(nlogn)。不是最快的算法测试用例:功能测试(数组中存在一个数字出现的次数超过数原创 2018-01-11 21:51:57 · 221 阅读 · 0 评论 -
数值的整数次方
题目:实现函数double Power(double base,int exponent),求base的exponent次方,不得使用库函数,同时不需要考虑大数问题思路:我们可以从base和exponent的取值来考虑所有的情况,底数和指数都可以分别取正数、负数、0。当底数为正数的时候,指数为正数可以直接计算、指数为负数的计算结果是指数为正数的倒数、指数为你0结果为1。当底数为负数原创 2018-01-02 11:48:02 · 132 阅读 · 0 评论 -
快速排序里面的Partition函数
Partition函数有两种实现方法,单边扫描和双边扫描Partition函数的作用就是在数组中选择一个数字,接下来把数组的数字分成两个部分,比选择的数字小的移动到数组的左边,比选择的数字大的移动到数组的右边。单边扫描:首先随机选择一个数字,与数组最后一个元素进行交换,变量i从左到右进行扫描,每一个数都与最后一个元素进行比较,如果比最后一个元素小,扫描变量i的元素与标记变量small的元素原创 2017-12-28 10:56:03 · 1496 阅读 · 0 评论 -
字符串的排列
题目:输入一个字符串,打印出该字符串中字符的所有排列。例如输入字符串abc,则打印出由字符a,b,c所排列出来的所有字符串abc、acb、bac、bca、cab和cba。分析:我们把一个字符串看成两部分组成:第一部分为它的第一个字符,第二部分是后面的所有字符。我们可以看成两步:首先求所有可能出现在第一个位置的字符,即把第一个字符和后面所有字符交换。第二步固定一个字符,求后面所有字符的排列。这个原创 2018-01-09 19:43:00 · 144 阅读 · 0 评论 -
二叉搜索树与双向链表
题目:输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表。要求不能创建任何新的结点,只能调整树中结点指针的指向。如下图,左边的二叉搜索树,则输出转换之后的排序双向链表。二叉树的结点定义如下:struct BinaryTreeNode{ int m_nValue; BinaryTreeNode* m_pLeft; BinaryTreeNode* m_pRight;}原创 2018-01-09 16:49:47 · 154 阅读 · 0 评论 -
二进制中1的个数
题目:实现一个函数,输入一个整数,输出该数二进制表示中1的个数,例如把9表示成二进制1001,有2位是1,。因此如果输入9,该函数的输出为2规律:把一个整数减去1之后和原来的整数做位与运算,得到的结果相当于是把整数的二进制表示中的最右边的一个1变成0.int numberof1(int n){ int count=0; while(n) { count++;原创 2017-12-30 20:59:05 · 103 阅读 · 0 评论 -
斐波那契数列
题目:写一个函数,输入n,求斐波那契数列的第n项,斐波那契数列的定义如下:n=0 f(n)=0n=1 f(n)=1n>1 f(n-1)+f(n-2)很多教科书上面的解法:long long Fibonacci(unsigned int n){ if (n<=0) return 0; if (n==1) return 1; if (n>1)原创 2017-12-30 20:36:32 · 161 阅读 · 0 评论 -
两个队列实现一个栈
队列的特点是先入先出,栈的特点是先入后出思路:假设入栈元素为:a->b>c,则出栈顺序为c->b->a入栈将元素a,b,c入栈,选择任意一个队列。入队列q1,此时q2是为空出栈1)将c出栈,先将a出队列q1,入队列q2。再将b出队列q1,入队列q2。此时q1中只有c,q2中有a,b。将c出队列删除,即出栈了如果此时有元素d入栈了,则将d入非空队列q2。下次出栈便会先出栈原创 2017-12-27 22:32:41 · 97 阅读 · 0 评论 -
两个栈实现一个队列
栈是先入后出,队列是先入先出假设我们入队列的元素为a->b->c 则出队列的顺序为a->b->c,先入先出。思路:1)首先我们入队列的元素为a,把a压入任意一个栈,假设压入栈stack1,此时stack2为空 如果此时需要出队列,先把a弹出,再压入stack2,再弹出a2)继续入队列元素b,把b压入栈stack1,此时stack2为空 如果此时需要出队列2原创 2017-12-27 16:49:14 · 101 阅读 · 0 评论 -
二叉树的镜像
题目:完成一个函数,输入一个二叉树,该函数输出它的镜像分析:交换根结点的左右子树,交换10的左右子树,交换6的左右子树。测试用例:功能测试(普通的二叉树,二叉树的所有结点都没有左子树或者右子树,只有一个结点的二叉树)特殊输入测试(二叉树的根结点为NULL指针)代码如下:struct BinaryTreeNode{ int m_nValue; BinaryTre原创 2018-01-05 16:27:43 · 134 阅读 · 0 评论 -
树的子结构
题目:输入两棵二叉树A和B,判断B是不是A的子结构。分析:要查找数A中是否存在数B结构一样的二叉树,分为两步,第一步是在数A中查找和B的根结点的值一样的结点R,第二步再判断树A中以R为根结点的子树是不是包含和树B一样的结构。测试用例:功能测试(树A和树B都是普通的二叉树,树B是或者不是树A的子结构)特殊输入测试(两棵二叉树中的一个或者两个根结点为NULL指针、二叉树的所有结点都没有原创 2018-01-05 15:52:51 · 113 阅读 · 0 评论 -
合并两个排序的链表
题目:输入两个递增排序的链表,合并这两个链表并使得新链表中的结点仍然按照递增排序的分析:假设链表1:1->3->5->7链表2:2->4->6->8合并之后的链表应该是1->2->3->4->5->6->7->8我们首先比较链表1和链表2的头结点的值的大小,值小的结点1作为新链表的头结点,此时链表1:3->5->7,链表2:2->4->6->8。再比较此时两个链表的头结点,值小的结点2原创 2018-01-05 15:11:25 · 115 阅读 · 0 评论