剑指offer
文章平均质量分 63
编程鸟
编程使我快乐,编程使我富裕,编程使我幸福!我爱编程!
展开
-
快速排序解析
1、定义 快速排序采用了分治的策略,是对冒泡排序的一种改进方法。2、基本思想 将一组无序的数据分成两部分,其中一部分的数据都比另外一部分数据大,再用快速排序的方法将两部分的数据排序,即采用了递归的方法,直至将数据排序好。图示如下: 3、编程思路 1)创建3个临时变量分别初始化为数组首元素下标(左指向)、尾元素下标(右指向)和首元素(设其为基点数),以及确保左指向标小于右指向标。 2)遍历整原创 2018-04-02 11:54:14 · 1314 阅读 · 0 评论 -
打印从1到最大的n位数
题目:输入数字n,按顺序打印出从1最大的n位十进制数。比如输入3,则打印出1、2、3一直到最大的3位数999。【例】#include<iostream>#include<stdlib.h>#include<stdbool.h>using namespace std; void PrintNumN(int n){ int number =...原创 2020-02-01 11:19:21 · 420 阅读 · 0 评论 -
数值的整数次方
题目:实现函数double Power(double base, intexponent),求base的exponent次方。不得使用库函数pow,同时不考虑大数问题。解题分析1、基数为0,指数小于0的情况,会导致程序出错,要进行特殊处理;2、当基数不为0,指数小于0的情况,即求整数指数幂的倒数;3、当基数不为0,指数大于0的情况,即求整数指数幂。方法一:递乘的方法#include&...原创 2020-01-05 18:34:22 · 260 阅读 · 0 评论 -
字符串的排列
题目:输入一个字符串,打印出该字符串中字符的所有排序。例如:输入字符串abc,则打印出由字符a、b、c所能排列出来的所有字符串abc、acb、bca、bac、cab、cba。解题思路:(1)求所有可能出现在第一个位置的字符,即把第一个字符和后面所有的字符交换。(2)把后面的所有字符分成两部分:1)后面字符的第一个字符,以及这个字符之后的所有字符;2)然后用第一个字符逐一和它后面的字符交换...原创 2019-12-10 10:49:23 · 267 阅读 · 1 评论 -
折半查找
1、含义: 折半查找亦称为二分查找,采用了分治的策略,对有序数列进行查找。2、查找思想: 假设一个数组有n个元素,从中间分成两部分,取中间元素与要查找数进行比较,如果大了,则从左部分数据中查找;如果小了,则从右部分数据中查找。使用此方法一直查找下去,找到则存在,否则不存在。3、查找过程,如下图所示: 4、程序代码:#include<stdio.h>#include<stdlib.h>////原创 2018-04-03 11:10:42 · 2508 阅读 · 0 评论 -
复杂链表的复制
什么是复杂链表? 复杂链表指的是一个链表有若干个结点,每个结点有一个数据域用于存放数据,还有两个指针域,其中一个指向下一个节点,还有一个随机指向当前复杂链表中的任意一个节点或者是一个空结点。要实现复制一个复杂链表,首先要知道复杂链表的结构。 复杂链表的数据结构定义如下: typedef int DataType; //数据域的类型 //复杂链表的数据结构 typedef struct Co原创 2017-07-05 15:05:32 · 3288 阅读 · 0 评论 -
调整数组顺序使奇数位于偶数前面
题目:输入一个整数数组,实现一个函数来调整该数组中的数字顺序,使得所有奇数位于数组的前半部分,所有偶数位于数组的后半部分。方案1: 先从前往后遍历整个数组,当遇到偶数时保存该偶数,并将该偶数后面的元素向前移动一位,再将该偶数放到数组的末尾。由于每次遇到偶数就要移动O(n)个元素,因此总的时间复杂度是O(n^2)。方案2: 先定义两个指针,一个指向数组首...原创 2019-05-02 12:55:26 · 199 阅读 · 0 评论 -
在二维数组中的查找
题目:在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。分析:当在数组中选出的数字与要查找的数字相等时,就结束查找; 当在数组中选出的数字比要查找的数字大,则要查找的数字在选出数字的左边或者在上边; 当在数组中选出的数字比要查找的数字小,则要查找的数字在选出数字的右...原创 2019-04-27 23:27:40 · 250 阅读 · 0 评论 -
数组中唯一出现一次的数字
题目:在一个数组中除一个数字只出现一次之外,其他数字都出现了三次。请找出那个只出现一次的数字。解题思路:如果一个数字出现三次,那么这个数表示的二进制的每一位的和都能被3整除。把不能整除的数加起来就是那个只出现一次的数字。如:在数组{8,6,7,8,8,6,6}中,3个8的二进制的每一位的和为:1000+ 1000+ 1000 = 3000,3个6的二进制的每一位的和为:0110 + 0...原创 2019-05-20 23:52:38 · 852 阅读 · 0 评论 -
数字在排序数组中出现的次数
题目:统计一个数字在排序数组中出现的次数。例如,输入排序数组{1,2,3,3,3,4,5,6}和数字6,由于3在数组中出现了3次,因此输出3方案一:时间复杂度为O(n)先用二分查找找到3; 在3的两边顺序扫描,分别找出第一个3和最后一个3的位置; 最后用最后一个3的位置减去第一个3的位置加1,就能得出3在数组中的个数。方案二:时间复杂度为O(log2(n))先用二分查找的方...原创 2019-05-11 19:09:06 · 272 阅读 · 0 评论 -
旋转数组中的最小数字
题目:把一个数组最开始的若干个元素搬到数组的末尾,称之为数组的旋转。输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素。例如,数组{3, 4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。1、旋转数组的特点:旋转之后的数组可以划分为两个排序的子数组,而且前面子数组的元素都大于或者等于后面子数组的元素,最小的元素刚好是这两个子数组的分界线。2、解题思路:...原创 2019-05-25 00:12:04 · 218 阅读 · 0 评论 -
在0~n-1中缺失的数字
题目:0~n-1中缺失的数字 一个长度为n-1的递增排序数组中的所有数字都是唯一的,并且每个数字都在范围0~n-1之内。在范围0~n-1内的n个数字中有且只有一个数字不在该数组中,请找出这个数字。方案一:时间复杂度为O(n)先用公式n(n-1)/2求出数组0~n-1的和,记为s1; 再求出数组元素的和,记为s2; 用s1减去s2就可以求得缺失的数字。方案二:时间复杂度为...原创 2019-05-12 12:04:47 · 691 阅读 · 0 评论 -
数组中数值与下标相等的元素
题目:数组中数值和下标相等的元素。 假设一个单调递增的数组里的每一个元素都是整数并且是唯一的。请编程一个函数,找出数组中任意一个数值等于其下标的元素。例如,在数组{-3,-1,1,3,5}中,数字3和它的下标相等。方案一:时间复杂度为O(n)遍历整个数组的元素,并且逐一检验元素是不是与下标相等。方案二:时间复杂度为log2(n)因为是在一个单调递增的数组里,所以可以考...原创 2019-05-12 18:19:24 · 946 阅读 · 0 评论 -
找出数组中只出现一次的数字
题目:一个整形数组里除两个数字之外,其他数字都出现了两次。请写程序找出这两个只出现一次的数字。要求时间复杂度是O(n),空间复杂度是O(1)。1、解题思路在这个数组里只有两个数出现一次,而其它数字都出现了两次。因为一个数字异或它本身等于0,所以可以消除出现两次的数字。剩下两个出现一次的数字可以把它们分到两个子数组中,这样问题就解决了。2、解题步骤:(1)分别异或整个数组中的元素,可...原创 2019-05-18 18:38:26 · 2242 阅读 · 0 评论 -
替换空格
题目:实现一个函数,把字符串中的每个空格替换成“%20”。例如:输入“We are happy.”,则输出“We%20are%20happy.”。方案1:时间复杂度为O(n^2)的解法 从头到尾扫描字符串,每次遇到空格就进行替换。由于是1个字符替换成3个字符,所以需要空格后的字符向后移动2格,否则就有2个字符被覆盖。假设字符串的长度是n,对每个空格字符需要移动后面的O(n...原创 2019-05-01 22:26:30 · 226 阅读 · 0 评论 -
递归算法
1、递归的概念递归是一个函数在内部自己调用这个函数自身。【例1】求1+2+……+n的和//求1+2+···+n的和#include<stdio.h>#include<stdlib.h>//方法一:用递归算法实现int AddN(int n){return (n <=0) ? 0 : n + AddN(n - 1);}//方法二:用循环实现int...原创 2019-04-14 17:14:19 · 417 阅读 · 0 评论 -
在O(1)时间内删除链表节点
题目:给定单向链表的头指针和一个节点指针,定义一个函数在O(1)时间内删除该节点。链表节点与函数定义如下:【方案】 方案一:从链表头节点开始顺序遍历查找要删除的节点,并在链表中删除该节点,如图A。因为这种思路需要顺序查找,时间复杂度是O(n),不符合要求。 方案二:把要删除节点的下一个节点的数据覆盖到被删除的节点,然后把下个节点删除掉,如图B。 图1 删除链表节点图【解题思路】 方案二有原创 2017-08-18 00:14:28 · 2928 阅读 · 0 评论 -
链表中倒数第k个节点
题目:输入一个链表,输出该链表中倒数第k个节点。本题从1开始计数,即链表的尾节点是倒数第1个节点。例如,一个链表有6个节点,从头节点开始,它们的值一次是1、2、3、4、5、6。这个链表的倒数第3个节点是值为4的节点,链表节点定义如下:【方案】 方案一: 先遍历整个链表,再往回走k步,就可得到链表倒数的第k个节点。但是,单链表没有往回走的指针。方案二: 先遍历整个链表得到n个节点,再从走n-k+原创 2017-08-11 00:57:27 · 2928 阅读 · 0 评论 -
链表中的入口节点
题目:如果一个链表中包含环,如何找到环的入口节点?例如,在下图1所示的链表中,环的入口节点是节点3。 图1 链表中环的入口节点【解题思路】 1、确定一个链表是否包含环。 定义两个指针(即pslow和pfast),同时从链表出发,pfast每次走两步,pslow每次走一步。如果无环,那么pfast将走到链尾而没有与pslow相遇;如果有环,那么pfast将与slow相遇。2、找到环的入口节点原创 2017-08-14 22:28:13 · 3073 阅读 · 0 评论 -
反转链表
题目:定义一个函数,输入一个链表的头节点,反转该链表并输出反转后链表的头节点。链表节点定义如下:typedef int DataType;typedef struct Node{ DataType data; struct Node *next;}Node, *pList, *pNode;【解题思路】 定义四个指针,一个指针用于指向链表的头节点,其他三个指针用于指向当原创 2017-08-15 11:26:39 · 2808 阅读 · 0 评论 -
两个链表的第一个公共节点
题目:输入两个链表,找出它们的第一个公共节点。链表节点定义如下:typedef int DataType;typedef struct Node{ DataType data; struct Node *next;}Node, *pList, *pNode;【方案】由于单向链表的节点只有一个next,所以从第一个节点开始,之后的所有节点都是重合不分叉的,如下图所示。 方案一:在原创 2017-08-25 18:53:58 · 2357 阅读 · 0 评论 -
从头到尾打印链表
题目:输入一个链表的头节点,从尾到头反过来打印出每个节点的值。链表的定义如下:typedef int DataType;typedef struct Node{ DataType data; struct Node *next;}Node, *pList, *pNode;【解题思路】(递归) 先递归出后面的节点,在输出节点本身。不足:当链表比较长时,会使函数调用层级比较深而导致原创 2017-08-26 10:13:53 · 2351 阅读 · 0 评论 -
直接插入排序
(1)概念: 直接插入排序(Insertion Sort),是一种简单直观的排序算法。它的工作原理是通过构建有序序列,对未排序的数据,在已排序序列中从后向前扫描,找到相应位置并插入。(2)性能分析: 最差时间复杂度:O(n^2) 最优时间复杂度:O(n) 平均时间复杂度:O(n^2) 稳定性:稳定(3)步骤: 1)从第一个元素开始,该元素可以认为已被排序; 2)取出下一个元素,在已经排原创 2017-09-13 10:07:44 · 2250 阅读 · 0 评论 -
希尔排序
(1)概念: 希尔排序(Shell Sort),也称为递减增量排序算法,是插入排序的一种高速而稳定的改进版本。希尔排序是基于插入排序的以下两点性质而提出改进方法的: 1)插入排序在对几乎已经排好序的数据操作时,效率高,即可以达到线性排序的效率; 2)插入排序是低效的, 因为插入排序每次只能将数据移动一位。(2)性能分析: 平均时间复杂度:O(nlogn) 稳定性:不稳定(3)基本思想:原创 2017-09-14 11:23:58 · 2227 阅读 · 0 评论 -
直接选择排序
选择排序算法就是每一趟从待排序的记录中选出关键字最小(最大)的记录,顺序放在已排好序的子文件的最后(最前),直到全部记录排序完毕。常见的选择排序有直接选择排序(Selection Sort),堆排序(Heap Sort),平滑排序(Smooth Sort),笛卡尔树排序(Cartesian Sort),锦标赛排序(Tournament Sort),循环排序(Cycle)。1、直接选择排序 直...原创 2017-09-16 10:41:13 · 3076 阅读 · 1 评论 -
C语言基础测试题1
1、下面的代码输出是多少?为什么?#include<stdio.h>#include<stdlib.h>void foo(void){ unsigned int a = 6; int b = -20; (a + b > 6) ? puts(">6") : puts("<6");}int main(){ foo(); printf("\n");原创 2018-04-22 10:44:59 · 9887 阅读 · 0 评论 -
C语言基础测试题2
1、请写出bool、float、指针变量与“零值”比较的if语句。 (1)请写出bool flag与“零值”比较的if语句:答:if(flag)或if(!flag);(2)请写出float x与“零值”比较的if语句: 答:#define EXP 0.000001if((x>-EXP) && (x<EXP))(3)请写出char *p与“零值”比较的if语句:答:if(p == NULL) 或原创 2018-04-23 21:24:21 · 3180 阅读 · 0 评论 -
求二进制中1的个数
题目:请事先一个函数,输入一个整数,输出该数二进制中表示1的个数。例如,把9表示成二进制1001,有2位是1。因此,如果输入9,则该函数输出2。1、位运算知识补充 位运算共有5种运算:与、或、异或、左移和右移。 (1)与、或和异或的运算规律 (2)左移 m<例:0000 1010B = 10d;1000 1010B = -10d 1)(无符号)0000 1010 << 2 = 0原创 2018-04-28 21:42:44 · 8844 阅读 · 0 评论 -
数组中出现次数超过一半的数字
题目:数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。例如:输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}。由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。1、分析:(1)数组是已序的先找到中位数,统计它在数组中出现的次数,如果次数的2倍超过数组长度,那么就找到了;否则没有。(2)数组是待排序的先遍历整个数组,保存数组元素和统计元...原创 2019-04-20 23:17:20 · 232 阅读 · 0 评论 -
数组中的重复数
题目一:找出数组中重复的数字 在一个长度为n的数组里的所有数字都在0~n-1的范围内。数组中某些数字是重复的,但是不知道有几个数字重复,也不知道每个数字重复了几次。请找出数组中任意一个重复的数字。例如,如果输入长度为7的数组{2,3,1,0,2,5,3},那么对应的输出是重复的数字2或者3。分析:方案1:先排序,再查找。先将数组排序,然后比较相邻元素,如果相等就找到重复数,...原创 2019-04-25 22:26:53 · 10381 阅读 · 0 评论 -
合并两条排序的链表
题目:输入两个递增排序的链表,合并这两个链表并使新链表中的节点仍然是递增排序的。例如,输入图1中的链表1和链表2,则合并之后的升序链表如链表3所示。链表节点定义如下: 图1:合并两个排序链表的过程【解题思路】 已知有两条链表,合并成一条新链表,所以定义一个指针(mergephead)指向新链表。 本题用递归方法解决。首先,判断两条链表的情况(空链表和多个节点),再判断两条链表头节点值的大小原创 2017-08-16 14:05:25 · 2792 阅读 · 0 评论