算法
文章平均质量分 59
漂泊的羊
这个作者很懒,什么都没留下…
展开
-
排序算法之希尔排序
希尔排序的原理希尔排序其实就是增量从d逐渐到1,进行多次直接插入排序。这里的d的递减顺序是每次除2。举个例子还是1,8,2,3,5,6,0,2。刚开始我们的d为4(8除2)。 然后我们进行增量为4的直接插入排序。 1 和 5 ,8和6 ,2和0,3和2 一趟排序结果为 1,6,0,2,5,8,2,3.接下来增量为2(4/2)。然后进行增量为2的直接插入排原创 2015-01-19 20:54:04 · 367 阅读 · 0 评论 -
二叉树中和为某一值的路径
1.问题描述输入一颗二叉树和一个整数,打印出二叉树中的结点值的和为输入整数的所有路径。从树的根结点开始往下一直到叶结点所经过的结点形成一条路径。2.分析找到值为某一值的路径,我们知道无非就是树的遍历,但是怎么保存呢?因为树在遍历的时候需要递归,我们可以用栈来保存路径。比如:我们开始遍历 先是根结点 压栈,在是左孩子 压栈,如果左孩子是叶子结点的话,那么我们判断和是不是我们期望的原创 2015-01-28 17:50:50 · 348 阅读 · 0 评论 -
树的镜像
1.问题描述请完成一个函数,输入一个二叉树,该函数输出它的镜像。2. 分析镜像就是在镜子中看到的景象,比如一棵树8 的镜像为 8 ,只是将左右子树交换。610 10 63.代码#include typedef struct node{ int data; struct原创 2015-01-27 19:17:37 · 327 阅读 · 0 评论 -
删除链表的结点
1.问题描述给定链表的头结点和待删除结点,要求删除链表的结点要求时间复杂度为o(1)。2.分析我们都知道链表的要想访问某个结点必须要从头结点挨个遍历,并且单链表我们没有指向前驱的结点,因此我们可以用狸猫换太子(用这个待删除结点的下个结点里面的内容,复制到这个待删除结点,然后删除下个结点),这样就可以用o(1)时间复杂度来完成题目要求。但是如果这个待删除结点为尾结点没有下个结点,原创 2015-01-24 12:16:09 · 354 阅读 · 0 评论 -
数值的整数次方
1.问题描述实现函数 double Power(double base,int exponent), 求base的exponent次方,不得使用库函数,同时不考虑大数问题。2.分析这个问题需要考虑的一些情况包括,exponent为负数的话,base为0 并且exponent为负数的话。3.代码#include int isNotInvalid = 0原创 2015-01-24 09:05:24 · 335 阅读 · 0 评论 -
求1+2+....+n
1.问题描述求1+2+....+n,要求不能使用乘除法,for,while,if,else switch,case等关键字及条件判断语句。(来自《剑指offer》)2.分析在c语言里面我们可以使用函数指针,来调用不同的函数,达到题目的要求。3.代码unsigned int Solution_Teminator(unsigned int n){ retu原创 2015-02-03 18:21:11 · 351 阅读 · 0 评论 -
反转链表
1.问题描述定义一个函数,输入一个链表的头结点,反转该链表病输出翻转后链表的头结点。2.分析反转链表需要注意,头指针为空或者整个链表只有一个结点时,反转后链表有没有断裂,反转后头结点是否是原来的尾结点。3.代码typedef struct node{ int data; struct node *next; }ListNode;Lis原创 2015-01-27 10:44:23 · 347 阅读 · 0 评论 -
重建二叉树
1.问题描述输入某二叉树的前序遍历和中序遍历的结果,请重建出改二叉树。假设输入的前序遍历序列和中序遍历序列的结果中都不包含重复的数字。例如输入前序遍历的序列{1,2,4,7,3,5,6,8}和中序遍历的序列{4,7,2,1,5,3,,8,6},则重建出二叉树,并输出它的头结点。2.分析由于我们知道二叉树的先序和中序序列。先序 1,2,4,7,3,5,6,8。中序4,7,2,1,原创 2015-01-18 13:36:45 · 314 阅读 · 0 评论 -
桶中取黑白球问题
有一个桶,里面有白球,黑球各100个,人们必须按照一下规则把球取出来原创 2014-09-05 16:41:28 · 797 阅读 · 0 评论 -
数字在排序数组中出现的次数
1.问题描述统计一个数字在排序数组中出现的次数。例如输入排序数组{1,2,3,3,3,3,4,5}和数字3 由于3在这个数组中出现了4次,因此输出4.2.分析因为数组是排序的,我们可以通过这个性质分别找到第一个k和最后一个k,然后计算出k的个数。找k的时候,以前二分查找的时候 找到了k ,我们还要判断是不是第一个k或最后一个k,如果不是的话还要继续查找。直至找到第一个k和最后一原创 2015-02-02 14:57:34 · 277 阅读 · 0 评论 -
数组中出现次数超过一半的数字
1.问题描述数组中有一个数字超过数组长度的一半,请找出这个数字。例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}。由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2.2.分析1)数组中有一个数字出现的次数超过了数组长度的一半。如果把这个数组排序那么中间的那个数字(中位数)一定是出现次数超过一半的数字,快速排序中的partition函数可以得到数原创 2015-02-01 12:14:01 · 325 阅读 · 0 评论 -
二叉搜索树与双向链表
1.问题描述输入一颗二叉搜索树,将该二叉搜索树转换成一个排序的双向链表。要求不能创建任何新的结点,只能调整树中结点指针的指向。2.分析对于二叉搜索树我们知道,树的左孩子都比根节点要下,树的右孩子都比根结点要大,根据这个特点,我们进行中序遍历得到的序列就会满足题目的要求,我们另外需要做的就是对结点的指针进行操作,记录一下上次访问的元素,将当前元素的left指针指向上次访问的元素,原创 2015-01-28 20:20:27 · 322 阅读 · 0 评论 -
全排列问题
1.问题描述输入一串数字,打印出该数组中数字的全排列,例如 1 2 3 的全排列包括 123,132,213,231,312,321.2.分析我们可以分成两步 1.把第一个数字和后面的数字交换。2. 固定一个数字求后面数字的全排列。3.代码#include void swap(int *one,int *two){ int temp = *one;原创 2015-01-28 21:38:57 · 425 阅读 · 0 评论 -
最小的k个数
1.问题描述输入n个整数,找出其中最小的k个数,例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4.2.分析原创 2015-02-01 18:53:21 · 314 阅读 · 0 评论 -
排序算法之快速排序
快速排序的原理一般选取带排序数组的最后一个元素作为关键字(key) ,然后设置2个指针 i(用来指向数组中小于等于key的元素) 和 j 。假如 j 指针指向数组中的元素比key要小于或者等于,那么就会交换 i 指针和j指针指向的值,按照上述规则遍历完数组结束后,交换i+1指针指向的值和end 指针指向的值。这样得到的结果是 i+1之前的元素都要比i+1这个位置的元素要小于或者等于,i+1原创 2015-01-18 23:23:49 · 436 阅读 · 0 评论 -
排序算法之归并排序
归并排序的原理归并排序递归的将待排序数组分为左,右2段,然后分别对左右2段数组在分别排序,直到待排序长度变为1时(长度为1的序列有序),然后开始归并,归并的过程中,按照元素的大小归并到原数组中,最终使原数组有序。贴上一张图便于大家理解。#define INFINITE 1000000 void Merage(int* array, int start,int end,i原创 2015-01-20 10:45:26 · 376 阅读 · 0 评论 -
排序算法之选择排序
选择排序的原理选择排序是遍历数组找到一个最小的元素然后将其和第一个位置上的元素交换(这样最小元素在第一个位置上最小元素就排好序了),然后接下来从第二个元素开始遍历在找最小,在替换,依此类推。代码void Selected_Sort(int* array,int length){ for (int i = 0; i < length; i++) {原创 2015-01-19 21:25:20 · 234 阅读 · 0 评论 -
排序算法之冒泡排序
冒泡排序的原理冒泡排序对数组进行遍历的过程中比较前后2个元素的大小,如果前一个元素大于后一个元素,那么交换这俩个元素的位置,遍历结束后最大的元素位于数组的顶端,那么下次遍历的时候,遍历到数组倒数第二个元素(因为最大元素已经在他应该在的位置上了)。第二次遍历完成后第二大的元素 位于数组倒数第二个元素的位置上,依此类推。代码void Bubble_Sort(int *array原创 2015-01-19 21:03:45 · 286 阅读 · 0 评论 -
排序算法之插入排序
插入排序的原理插入排序是从待排序数组中的未排序序列中选取一个元素插入到前面已排序的序列中去。具体操作为,从数组中第二个元素开始(因为当只有一个元素时我们认为其有序),与前面的元素进行比较,假如前面的元素比这个要插入的元素要大,我们就将前面的元素向后移动一个位置,循环这个过程直到前面在没有元素。这时空出来的位置我们将选取的元素插入其中,这就是插入排序的过程。举个例子1,8,2,3原创 2015-01-19 20:03:36 · 286 阅读 · 0 评论 -
不用加减乘除做加法
1.问题描述写一个函数,求两个整数之和,要求函数体内不得使用加减乘除运算符。2.分析我们分析做十进制加法时,可以分为三步进行例如 5+17 , 1)各位相加不进位 5+7 = 12 , 2)第二步做进位 5+7有进位 进位的值是10 ,3)把前面两个结果加起来 12+10的结果是22 ,对于二进制同样也遵循这个规律。3.代码int add(int原创 2015-02-03 20:35:49 · 528 阅读 · 2 评论 -
圆圈中最后剩下的数字
1.问题描述题目0,1......n-1这n个数字排成一个圆圈,从数字0开始每次从这个圆圈里删除第m个数字。求出这个圆圈里剩下的最后一个数字。(来自《剑指offer》)2.分析1)用环形链表模拟圆圈,然后扫描链表删除结点,如果扫描到了链表结尾,重新在指向链表开头以此来模拟环形链表。typedef struct node{ int data;原创 2015-02-03 13:47:48 · 365 阅读 · 0 评论 -
翻转单词顺序
1.问题描述输入一个英文句子,翻转句子中单词的顺序,但单词内字符的顺序不变。为简单起见,标点符号和普通字幕一样处理。例如输入字符串 “I am a student.” 则输出"student. a am I".2.分析我们可以第一步翻转句子中所有的字符。比如反转 I am a student中所有的字符得到 ".tneduts a ma I" 第二步在翻转每个单词中字符的顺序得原创 2015-02-03 10:56:19 · 358 阅读 · 0 评论 -
数组中只出现一次的数字
1.问题描述一个整型数组里除了俩个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。要求时间复杂度o(n),空间复杂度o(1);2.分析如果说只有一个数字的话,那我们能想到使用异或运算(两个相同数字异或等于0)这样最后得到的就是那个只出现一次的数字。这里我们假如可以将数组分为两部分,使这俩个只出现一次的数字位于俩个数组中,而其他的数字都成对出现两次,这样就可以得到这原创 2015-02-02 17:20:04 · 316 阅读 · 0 评论 -
连续子数组的最大和
1.问题描述输入一个整型数组,数组里有正数也有负数。数组中一个或连续的多个整数组成一个子数组。求所有子数组的和的最大值。要求时间复杂度为o(n)。2.分析当 当前和为负数时我们在计算最大和时直接从下个值开始,否则的话在当前和加上下个值在与记录的最大值比较,如果比纪录的最大值还大,那更新记录的最大值。3.代码int FindGreatestSumOfArray(i原创 2015-02-01 19:34:25 · 277 阅读 · 0 评论 -
包含min函数的栈
1.问题描述定义栈的数据结构,请在该类型中实现一个能够得到栈的最小元素的函数,在该栈中调用min,push及pop的时间复杂度都为o(1).2.分析我们可以使用一个辅助栈,专门来处理题目中得到栈的最小元素的函数时间复杂度为o(1)的这个需求。 当我们压栈时,另外一个栈正常进行,对辅助栈的压栈做法是这样的 假如当前压入的这么元素比top元素要小,那我们压人,如果比顶端元素大,那么我们在把原创 2015-01-27 20:22:07 · 327 阅读 · 0 评论 -
打印1到最大的n位数
1.问题描述输入数字n,按顺序打印出从1刀最大的n位数的十进制数。比如输入3,则打印出1,2,3一直到最大的3位数999.2.分析对于这个问题,我们需要考虑大数。因此我们在字符串上模拟加法运算。3.代码/* nTakeOver代表进位,isNotOverFlow代表有没有溢出(是不是达到了n位的最大数了)。 我们每次对个位进行加一运算,判断是不是该进位,如果原创 2015-01-24 11:05:48 · 379 阅读 · 0 评论 -
替换空格
1.问题描述请实现一个函数,把字符串中的每个空格替换成“%20”,例如输入“we are happy” ,则输出 “we%20are%20happy%20”。2.分析我们要将字符串中的空格替换成%20,如果我们从前向后替换的话,每次替换空格后都需要将空格之后的所有字符向后移动。每次遇到空格都需要移动空格后面的字符导致时间效率低。我们可以从后向前替换,先遍历一遍得到空格的数目,然原创 2015-01-15 19:03:39 · 515 阅读 · 0 评论 -
左旋字符串
1.问题描述字符串的左旋操作是把字符串前面的若干个字符转移到字符串的尾部。请定义一个函数实现字符串左旋转操作的功能。比如输入字符串"abcdefg"和数字2,该函数将返回左旋转2位得到的结果“cdefgab”。2.分析其实和翻转单词顺序差不多,我们可以先将前面2位翻转得到 ba,在将后面5位翻转得到 gfedc ,然后再将整个字符串翻转得到 cdefgab。3.代码原创 2015-02-03 11:20:46 · 349 阅读 · 0 评论 -
和为s的两个数字
1.问题描述输入一个递增排序的数组和一个数字s,在数组中查找两个数,使得他们的和正好是s,如果有多对数字的和等于s,输出任意一对即可。2.分析如果首先想到的可能是穷举,但是这样的话就会浪费掉递增排序的这一性质,并且时间复杂度时o(n2) ,因为他是递增的 ,我们可以设置两个指针一个指向头一个指向尾。然后 求和 如果等于的话,就得到了一对答案,如果大于,那我们就向前移动尾指针原创 2015-02-02 21:10:21 · 364 阅读 · 0 评论 -
二叉搜索树的后序遍历序列
1.问题描述输入一个整数数组,判断该数组是不是某二叉树的后序遍历的结果。如果是则返回true,否则返回false。假设输入的数组的任意两个数字都互不相同。2.分析二叉搜索树有一个性质为:左子树的元素都比根结点要小,右子树的元素都比根结点要大,根据这个性质我们来划分左右子树,在判断右子树是不是都比根结点要大(我们划分时,左子树一定满足条件,因为我们就是按照比根结点小的是左子树来划原创 2015-01-28 12:41:05 · 326 阅读 · 0 评论 -
从上往下打印二叉树
1.问题描述从上往下打印出二叉树的每个结点,同一层的结点按照从左到右的顺序打印。2.分析我们可以使用队列这个容器,将元素压入队列,打印时每次从队列中取出一个元素打印其值,并且如果该节点有左孩子或右孩子,在将其左孩子右孩子压入队列,直至队列为空。(这个和有向图的广度优先遍历一个思想,树是图的一种特殊退化形式)。3.代码void PrintTreeFromTopTo原创 2015-01-28 12:02:56 · 392 阅读 · 0 评论 -
用两个栈实现队列
1.问题描述用两个栈实现一个队列。队列的声明如下,请实现它的两个函数appendTail和deleteHead,分别完成在队列的尾部插入结点和在队列的头部删除结点的功能。2.分析声明2个队列 s1 s2 , 当appendTail时我们向s1队列压入元素,当deleteHead时假如s2队列不为空 ,我们从s2队列弹出元素。如果s2队列为空,那么弹出s1队列的所有元素,压入到s2队列中原创 2015-01-18 17:42:05 · 283 阅读 · 0 评论 -
和为s的连续正数序列
1.问题描述输入一个正数s,打印出所有和为s的连续正数序列(至少有2个数)。例如输入15,有1,2,3,4,5. 4,5,6 7,8。三个序列输出。2.分析我们可以定义2个指针分别指向small和big,然后我们开始求 small和big的和,如果和等于要求的和,那我们打印这个序列并将small向后移动,并从当前的和里面减去当原创 2015-02-02 21:45:06 · 408 阅读 · 0 评论 -
二叉树的深度
1.问题描述输入一棵二叉树的根结点,求该树的深度。从根结点到叶结点依次经过的结点(含根 叶结点)形成树的一条路径,最长路径的长度求树的深度。2.分析最长路径的长度即为左子树或右子树中相对较长的一棵子树的深度在加1(加上的是当前左子树右子树的父亲)。3.代码int GetTreeLength(TreeNode* node){ if (node =原创 2015-02-02 15:38:34 · 298 阅读 · 0 评论 -
二进制中1的个数
1.问题描述请实现一个函数,输入一个整数,输出该二进制表示中的1的个数,例如输入9,9的二进制表示为1001,输出2。思路1先判断整数二进制最右边是不是1接着把整数右移一位在判断是不是1,这样每次移动一位直到整个整数变为0为止。只要把整数和1做位于运算看结果是不是0就知道了,1除了最右边一位之外所有位都是0。int NumberOfOne(int n){原创 2015-01-20 15:16:09 · 331 阅读 · 0 评论 -
旋转数组的最小数字
1. 问题描述把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个递增排序的数组的一个旋转,输出该旋转数组的最小元素。例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1.2.分析首先我们可以看到原数组为递增排序的,并且以最小元素为界左边的为递增有序,右边的也为递增有序因此我们可以使用二分查找。我们定义3个指针left,ri原创 2015-01-20 14:17:01 · 312 阅读 · 0 评论 -
调整数组的顺序使奇数位于偶数的前面
1.问题描述输入一个整形数组,实现一个函数来调整该数组中的数字的顺序,使得所有奇数位于数组的前半部分,所有的偶数位于数组的后半部分。2.分析这个问题只需要定义2个指针,一个指向头一个指向尾,头指针向后遍历当指向偶数时,尾指针向前遍历当指向奇数时,交换2个元素的位置。我们可以将这个代码设计的更具扩展性一些(比如题目改为负数在前,正数在后等等),因此我们使用单独的一个函数来判断数字原创 2015-01-24 16:53:49 · 361 阅读 · 0 评论 -
第一个只出现一次的字符
1.问题描述在字符串中找出第一个只出现一次的字符。例如输入abaccdeff,则输出 b。2.分析我们可以用一个容器来存放 对应的字符和出现次数(哈希表 这里仅仅用数组来简单的模拟了一下),第一次扫描时将出现的次数存放在表中,第二次扫描时扫描到次数为1的字符并返回该字符即可。表的大小为256,因为字符是8个bit的类型,总共有256个字符。3.代码char Fi原创 2015-02-01 22:17:48 · 302 阅读 · 0 评论 -
合并两个排序的数组
1.问题描述有俩个排序的数组A1,A2,内存在A1的末尾有足够多的空余空间容纳A2,请实现一个函数,把A2中所有的数字插入到A1中并且所有的数字是排序的。2.分析其实和之前写的一道替换空格的程序类似,都是数组的从后向前遍历的例子。这道题也同样,从前向后复制每个数字需要重复移动数字多次,从后向前复制可以减少移动次数,从而提高效率。3.代码void MerageArray(int原创 2015-01-15 21:47:01 · 1047 阅读 · 0 评论 -
二维数组中查找
1.问题描述在一个二维数组中,每一行按照从左到右的递增顺序排序,每一列按照从上到下的递增的顺序排序,请完成这样一个函数,输入这样的一个二维数组和一个整数,判断数组是否含有该整数。2.分析首先选取数组中右上角的数字。如果改数字等于要查找的数字,查找过程结束;如果改数字大于要查找的数字,那么剔除这个数字所在的列;如果小于要查找的数字,剔除数字所在的行。另外还需注意,二维数组在内原创 2015-01-15 12:43:52 · 361 阅读 · 0 评论