程序员经典面试题集
文章平均质量分 59
选取剑指offer以及互联网名企的笔试面试经典算法进行讲解,给出最优实现代码。所有题目博主均在vs2008编辑器上实现,亲测算法有效,OJ题目均ac通过。
代码采用c语言实现。
Hao_09
这个作者很懒,什么都没留下…
展开
-
面试题之变态跳台阶
变态跳台阶一个台阶总共有n级,如果一次可以跳1级,也可以跳2级......它也可以跳上n级。该青蛙跳上一个n级的台阶总共有多少种跳法? 分析:用Fib(n)表示青蛙跳上n阶台阶的跳法数,青蛙一次性跳上n阶台阶的跳法数1(n阶跳),设定Fib(0) = 1; 当n = 1 时, 只有一种跳法,即1阶跳:Fib(1)= 1; 当n = 2 时, 有两种跳的方原创 2015-08-13 11:16:15 · 1688 阅读 · 0 评论 -
判断二叉树是不是平衡二叉树
题目:输入一棵二叉树的根结点,判断该树是不是平衡二叉树。某二叉树中任意结点的左右子树的深度相差不超过1,那么它就是一棵二叉树。 我们很容易就能想到一个代码简洁却性能不佳的思路:在遍历树的每个结点的时候,调用函数TreeDpth得到它的左右子树的深度。如果每个结点的左右子树的深度相差都不超过1,按照定义它就是一棵平衡的二又树。 较好的思路是:用后序遍历的方式遍历整原创 2015-06-04 21:55:29 · 1795 阅读 · 0 评论 -
面试题之求二叉树的深度
题目:输入一棵二叉树的根节点,求该树的深度。从根节点到叶子结点一次经过的结点形成树的一条路径,最长路径的长度为树的深度。根节点的深度为1。struct BinaryTreeNode{ int m_nValue; BinaryTreeNode *m_pLeft; BinaryTreeNode *m_pRight;}; 如果一棵树只有一个结点,它的深度为1。如果根结点只有左子原创 2015-06-04 21:32:17 · 1356 阅读 · 0 评论 -
数字在排序数组中出现的次数
题目:统计一个数字在排序数组中出现的次数。例如,输入排序数组{1,2,3,3,3,3,4,5}和数字3由于3在这个数组中出现了4次,因此输出4。题目解法很多,关键是要找到让人满意的方法,直接统计当然可以,可是显然不是我们要的答案。比较好的思路如下:使用二分查找的拓展,当查找的元素有重复的时,找到元素的第一个和最后一个。这样将可以计算出该元素有多少个重复的了。二分法在数组中查找一个合乎要原创 2015-06-04 21:10:35 · 2416 阅读 · 0 评论 -
微软面试题之两个链表的第一个公共结点
问题描述:给定两个单向链表,找出它们的第一个公共节点。链表的节点定义如下:struct ListNode{ int m_nKey; ListNode* m_pNext;};思路: 如果两个单向链表有公共的节点,也就是说两个链表从某一个节点开始,它们的m_pNext都指向同一个节点。但由于是单向链表的节点,每个节点只有一个m_pNext,因此从第原创 2015-06-03 22:34:29 · 1646 阅读 · 0 评论 -
第一个只出现一次的字符
题目:在字符串中找出第一个只出现一次的字符。如输入“abaccdeff”,则输出'b‘。思路: 我们可以定义哈希表的键值(Key)是字符的ASCII值,而值(Value)是该字符出现的次数。同时我们需要扫描两次字符串,第一次扫描字符串时,每扫描到一个字符就在哈希表的对应项中把次数加1。接下来第二次扫描的时候,没扫描到一个字符就能在哈希表中得到该字符出现的次数。找出第一个Val原创 2015-05-29 13:24:57 · 1105 阅读 · 0 评论 -
丑数
题目:我们把只包含因子2、3、5的数称作丑数(Ugly Number)。求按从小到大的顺序的第1500个丑数。例如6、8都是丑数,但14不是,因为它包含因子7。习惯上我们把1当做第一个丑数。 思路: 根据丑数的定义,丑数应该是另一个丑数乘以2、3或者5的结果(l除外)。因此我们可以创建一个数组,里面的数字是排好序的丑数,每一个丑数都是前面的丑数乘以2、3或者5得到的。原创 2015-05-28 21:56:11 · 1031 阅读 · 0 评论 -
把数组排成最小的数
题目:输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。例如输入数组{3,32,321},则打印出这3个数字能排成的最小数字321323。思路: 对于数字a和b,排列的结果为ab和ba,如果ab小于ba,应该输出ab,即a排在b的前面,也就是a//数组中每个整数的最大长度const int g_MaxNumberLength=10;原创 2015-05-28 21:10:33 · 1113 阅读 · 0 评论 -
连续字数组的最大和
题目:输入一个整型数组,数组里有正数也有负数。数组中一个或连续的多个整数组成一个子数组。求所有子数组的和的最大值。要求时间杂度为O(n)。此题思路比较简单,直接上代码,注意考虑无效的输入。//全局变量,判断输入参数是否无效bool g_InputInvalid=false;int FindGreatestSumOfArray(int *data, int length){ if原创 2015-05-27 20:24:45 · 1573 阅读 · 0 评论 -
最小的K个数
题目:输入n个整数,找出其中最小的K个数。例如输入4、5、1、6、2、7、3、8这8个数字,则最小的4个数字是1、2、3、4。思路: 我们可以先创建一个大小为k的数据容器来存储最小的k个数字,接下来我们每次从输入的n个整数中读入一个数。如果容器中已有的数字少于k个,则直接把这次读入的整数放入容器之中;如果容器中己有k个数字了,也就是容器已满,此时我们不能再插入新的数字而只能替换已有的原创 2015-05-27 19:39:20 · 1000 阅读 · 0 评论 -
数组中出现次数超过一半的数字
题目:数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}。由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。思路:数组中有一个数字出现的次数超过数组长度的一半,也就是说它出现的次数比其他所有数字出现次数的和还要多。因此我们可以考虑在遍历数组的时候保存两个值:一个是数组中的一个数字,一个是次数。当我们遍历原创 2015-05-26 22:45:26 · 1120 阅读 · 0 评论 -
字符串的排列
题目:输入一个字符串,打印出该字符串中字符的所有排列。例如输入字符串abc,则打印出由字符a、b、c所能排列出来的所有字符串abc、acb、bac、bca、cab和cba。思路: 我们以三个字符abc为例来分析一下求字符串排列的过程。首先我们固定第一个字符a,求后面两个字符bc的排列。当两个字符bc的排列求好之后,我们把第一个字符a和后面的b交换,得到bac,接着我们固定第一原创 2015-05-26 21:40:58 · 1016 阅读 · 0 评论 -
二叉搜索树与双向链表
题目:输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表。要求不能创建任何新的结点,只能调整树中结点指针的指向。二叉树结点的定义如下:struct BinaryTreeNode{ int m_nValue; BinaryTreeNode *m_pLeft; BinaryTreeNode *m_pRight;};解法如下://返回双向链表的头结点BinaryTreeNo原创 2015-05-25 22:56:52 · 1140 阅读 · 0 评论 -
复杂链表的复制
题目:请实现函数ComplexListNode *Clone(ComplexListNode *pHead),复制一个复杂链表。在复杂链表中,每个结点除了有一个m_pNext指针指向下一个结点外,还有一个m_pSibling指向链表中的任意结点或者NULL。结点的C++小定义如下:struct ComplexListNode{ int m_nValue; ComplexListNode *原创 2015-05-20 22:52:09 · 1444 阅读 · 0 评论 -
二叉树中和为某一值的路径
题目:输入一棵一二叉树和一个整数,打印出二叉树中结点值的和为输入整数的所有路径。从树的根结点开始往下一直到叶结点所经过的结点形成一条路径。二义树结点的定义如下:struct BinaryTreeNode{ int m_nValue; BinaryTreeNode *m_pLeft; BinaryTreeNode *m_pRight;};思路: 由于路径是从根结原创 2015-05-18 22:34:22 · 1095 阅读 · 0 评论 -
二叉搜索树的后序遍历序列
题目:输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果。如果是则返回true,否则返回false。假设输入的数组的任意两个数字都互不相同。思路: 在后序遍历得到的序列中,最后一个数字是树的根结点的值。数组中前面的数字可以分为两部分:第一部分是左子树结点的值,它们都比根结点的值小;第二部分是右子树结点的值,它们都比根结点的值大。代码如下:bool Verif原创 2015-05-18 21:43:09 · 1121 阅读 · 0 评论 -
从上往下打印二叉树
题目:从上往下打印出二叉树的每个结点,同一层的结点按照从左到右的顺序打印。例如输入图中的二叉树,则依次打印出8、6、10、5、7、9、11。二叉树结点定义如下:struct BinaryTreeNode{ int m_nValue; BinaryTreeNode *m_pLeft; BinaryTreeNode *m_pRight;};思路:每一次打印一个结点的时候原创 2015-05-17 11:43:55 · 1095 阅读 · 0 评论 -
栈的压入、弹出序列
题目:输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如序列1、2、3、4、5是某栈的压栈序列,序列4、5、3、2、1是该压栈序列对应的一个弹出序列,但4、3、5、1、2就不可能是该压栈序列的弹出序列。思路: 如果下一个弹出的数字刚好是栈顶数字,那么直接弹出。如果下一个弹出的数字不在栈顶,我们把压栈序原创 2015-05-16 21:03:36 · 949 阅读 · 0 评论 -
包含min函数的栈
定义栈的数据结构,请在该类型中实现一个能够得到栈的最小元素的min函数。在该栈中调用min,pop,push函数的时间复杂度都是O(1)。#include #include using namespace std;template class StackWidthMin{public: StackWidthMin(){} ~StackWidthMin(){} T& top()原创 2015-05-16 19:43:00 · 894 阅读 · 0 评论 -
顺时针打印矩阵
题目:输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字。例如,如果输入如下矩阵:1 2 3 45 6 7 89 10 11 1213 14 15 16则依次打印出数字1、2、3、4、8、12、16、15、12、13、9、5、6、7、11、10。//顺时针打印矩阵void PrintMatrixClockwisely(int **n原创 2015-05-16 11:53:13 · 859 阅读 · 0 评论 -
二叉树的镜像
题目:请完成一个函数,输入一个二叉树,该函数输出它的镜像。二叉树结点定义如下:struct BinaryTreeNode{ int m_nValue; BinaryTreeNode *m_pLeft; BinaryTreeNode *m_pRight;};思路:我们先前序遍历这棵树的每个结点,如果遍历到的结点有子结点,就交换它的两个子结点。当交换完所有非叶护结点的左右子结点之后,就原创 2015-05-16 11:01:02 · 1103 阅读 · 0 评论 -
树的子结构
题目:输入两颗二叉树A和B,判断B是不是A的子结构。二叉树结点的定义如下:struct BinaryTreeNode{ int m_nValue; BinaryTreeNode *m_pLeft; BinaryTreeNode *m_pRight;};//在数A中查找与树B根结点值相同的结点,然后递归判断,查找过程也是递归bool HasSubTree(BinaryTreeN原创 2015-05-15 22:29:07 · 805 阅读 · 0 评论 -
合并两个排序的链表
题目:输入两个递增排序的链表,合并这两个链表并使新链表中的结点仍然是按照递增排序的。链表结点定义如下:struct ListNode{ int m_nValue; int m_pNext;};如下图所示,一目了然,比较两个链表的头结点,值小的则并入新的结点,如此循环,可以用递归解决。//利用递归ListNode *Merge(ListNode *phead1, ListNod原创 2015-05-14 21:31:27 · 911 阅读 · 0 评论 -
反转链表
定义一个函数,输入一个链表的头结点,反转该链表,并输入反转后链表的头结点。 链表结点定义如下:struct ListNode{ int m_nKey; struct ListNode* m_pNext;};ListNode *ReverseList(ListNode *phead){ //定义反转后链表的头结点 ListNode *pReverseHead=NULL; //指原创 2015-05-14 20:57:12 · 794 阅读 · 0 评论 -
Remove Duplicates from Sorted Array II
Follow up for "Remove Duplicates": What if duplicates are allowed at most twice?For example,Given sorted array nums = [1,1,1,2,2,3],Your function should return length = 5, with the first five el原创 2015-05-13 22:15:23 · 863 阅读 · 0 评论 -
Remove Duplicates from Sorted Array
Given a sorted array, remove the duplicates in place such that each element appear only once and return the new length.Do not allocate extra space for another array, you must do this in place with con原创 2015-05-13 21:39:21 · 987 阅读 · 0 评论 -
链表中倒数第k个结点
题目:输入一个单向链表,输出该链表中倒数第k个结点。为了符合大多数人的习惯,本题从1开始计数,即链表的尾结点是倒数第1个结点。例如一个链表有6个结点,从头开始它们的值依次是1,2,3,4,5,6。这个链表的倒数第3个结点是值为4的结点。链表结点定义如下:struct ListNode{ int m_nKey; ListNode* m_pNext;};原创 2015-05-13 21:08:10 · 827 阅读 · 0 评论 -
调整数组顺序使奇数位于偶数前面
题目:输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有的奇数位于数组的前半部分,所有的偶数位于位于数组的后半部分。解析:题目没说相对位置不变,用两个游标指向首尾,前面的偶数与后面的奇数交换即可。/*功能函数*/void ReOrderOddEven(int a[], int length){ int i,j;//定义两个游标 int temp; if原创 2015-05-13 20:31:19 · 827 阅读 · 0 评论 -
Remove Element
Given an array and a value, remove all instances of that value in place and return the new length.The order of elements can be changed. It doesn’t matter what you leave beyond the new length.//在数组中移原创 2015-05-12 21:17:29 · 860 阅读 · 1 评论 -
在O(1)时间删除链表结点
题目:给定单向链表的头指针和一个结点指针,定义一个函数在O(l)时间删除该结点。链表结点与函数的定义如下:struct ListNode{ int m_nValue; ListNode *m_pNext;};void DeleteNode(ListNode **pListHead, ListNode *pToBeDeleted);把下一个结点的内容复制到需要删除的结点上覆盖原有的内容,原创 2015-05-12 20:00:06 · 1349 阅读 · 0 评论 -
打印1到最大的n位数
题目:输入数字n,按顺序打印出从1最大的n位十进制数。比如输入3,则打印出1,2,3一直到最大的3位数即999。此题很容易误入陷阱!//第一次解法,不幸调入陷阱void print(int n){ if (n<1) { printf("Invalid Input!\n"); return; } long maxNum=(int)pow(10.0,n);//如果n很大,不原创 2015-05-11 22:40:18 · 801 阅读 · 0 评论 -
数值的整数次方
题目:实现函数double Power(double base, int exponent),求base的exponent次方。不得使用库函数,同时不需要考虑大多数问题。此题咋看非常easy,但是却很容易忽视底数为0以及指数为负数的情况,完整代码如下://全局变量,当参数出错时返回truebool g_InvalidInput=false;//判断两个double型变量是否相原创 2015-05-10 19:22:37 · 1119 阅读 · 0 评论 -
二进制中1的个数
题目:请实现一个函数,输入一个整数,输出改数二进制表示中1的个数。例如把9表示成二进制是1001,有2位是1。因此如果输入9,改函数输出2。常规解法:int CountbitOne(int n){ int count=0; while(n) { if (n&1) { count++; } n=n>>1; } return count;}最优解法思原创 2015-05-10 11:59:15 · 942 阅读 · 0 评论 -
斐波那契数列(递归和非递归实现)
递归实现是最常想到的方法,代码如下://递归方式long Fibonacci(unsigned n){ if (n==0) { return 0; } else if (n==1) { return 1; } else { return Fibonacci(n-1)+Fibonacci(n-2); }}显然递归并不是最好的方法,当n较大时效率将非常低下。原创 2015-05-10 11:26:27 · 1402 阅读 · 0 评论 -
旋转数组的最小数字
旋转数组中包含两个递增排序的子数组,有阴影背景的是第二个子数组。如下图所示:(1)把Pl指向数组的第一个数字,P2指向数组的最后一个数字。由于Pl和P2中间的数字5大于P1指向的数字,中间的数字在第一个子数组中。下一步把P1指向中间的数字。(2) Pl和P2中间的数字1小于P2指向的数字,中间的数字在第二个子数组中。下一步把P2指向中间的数字。(3)P1和P2指向两个相邻的原创 2015-05-09 17:30:51 · 1145 阅读 · 0 评论 -
用两个栈实现队列
题目:用两个栈实现一个队列。队列的声明如下,请实现它的两个函数appendTail和deleteHead,分别完成在队列尾部插入结点和在队列头部删除结点的功能。template class CQueue{public: CQueue(); ~CQueue(); void appendTail(const T &node); T deleteHead();private: st原创 2015-05-08 21:40:09 · 793 阅读 · 0 评论 -
重建二叉树
题目: 输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含童复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建出如下图所示的二叉树并输出它的头结点。二叉树结点的定义如下:struct BinaryTreeNode{ int m_nValue; Bin原创 2015-05-07 22:47:15 · 832 阅读 · 0 评论 -
【字符串】旋转字符串
题目描述给定一个字符串,要求把字符串前面的若干个字符移动到字符串的尾部,如把字符串“abcdef”前面的2个字符'a'和'b'移动到字符串的尾部,使得原字符串变成字符串“cdefab”。请写一个函数完成此功能,要求对长度为n的字符串操作的时间复杂度为 O(n),空间复杂度为 O(1)。例如,字符串 abcdef ,若要让def翻转到abc的前头,只要按照下述3个步骤操作即可:首先将原创 2015-05-05 20:04:33 · 985 阅读 · 0 评论 -
【华为2015暑期实习生上机题】仿照Excel的列编号
这是本人上个月做的,武汉地区的上机题中的第三个。仿照Excel的列编号,给出该列编号字符串,输出一个数字。例如:a对应1,z对应26,aa对应27,az对应52 ……#include #include using namespace std;//字符串到数字的转换,相当于26进制int stoi(char *s){ int n=0;//字符串长度 int i=0;//循原创 2015-05-04 11:40:56 · 1692 阅读 · 0 评论 -
逆序打印链表
用栈能很easy的解决,直接贴代码:struct ListNode{int m_nValue;ListNode *m_pNext;};void PrintListRevers(ListNode* pHead){ stack nodes; ListNode* pNode = pHead; while(pNode != NULL) {原创 2015-04-23 23:51:22 · 968 阅读 · 0 评论