计算机笔试/面试题
【字符串】
1、输入一个字符串,打印出该字符串中字符的所有排列。
例如输入字符串abc,则输出由字符a、b、c所能排列出来的所有字符串abc、acb、bac、bca、cab和cba。
2、有一个由大小写组成的字符串,现在需要对他进行修改,将其中的所有小写字母排在大写字母的前面
(大写或小写字母之间不要求保持原来次序),如有可能尽量选择时间和空间效率高的算法。
c语言函数原型void proc(char *str),也可以采用你自己熟悉的语言。
3、编写反转字符串的程序,要求优化速度、优化空间。
4、用C语言实现函数void * memmove(void *dest, const void *src, size_t n)。
memmove函数的功能是拷贝src所指的内存内容前n个字节到dest所指的地址上。
分析:由于可以把任何类型的指针赋给void类型的指针,这个函数主要是实现各种数据类型的拷贝。
5、编程找出两个字符串中最大公共子字符串,如"abccade", "dgcadde"的最大子串为"cad"。
6、输入一个字符串,输出该字符串中对称的子字符串的最大长度。
比如输入字符串"google",由于该字符串里最长的对称子字符串是"goog",因此输出4。
7、字符串原地压缩。题目描述:“eeeeeaaaff" 压缩为 "e5a3f2",请编程实现。
8、请以回溯与不回溯算法实现字符串匹配。
9、输入一个英文句子,翻转句子中单词的顺序,但单词内字符的顺序不变。句子中单词以空格符隔开。
为简单起见,标点符号和普通字母一样处理。
例如:输入"I am a student.",则输出"student. a am I"。
10、在一个字符串中找到第一个只出现一次的字符。如输入abaccdeff,则输出b。
11、写一个函数,它的原形是int continumax(char *outputstr,char *intputstr)
功能:
在字符串中找出连续最长的数字串,并把这个串的长度返回,并把这个最长数字串付给其中一个函数参数outputstr所指内存。
例如:"abcd12345ed125ss123456789"的首地址传给intputstr后,函数将返回9,outputstr所指的值为123456789。
12、定义字符串的左旋转操作:把字符串前面的若干个字符移动到字符串的尾部。
如:把字符串abcdef左旋转2位得到字符串cdefab。请实现字符串左旋转的函数。
要求时间对长度为n的字符串操作的复杂度为O(n),辅助内存为O(1)。
13、有n个长为m+1的字符串,如果某个字符串的最后m个字符与某个字符串的前m个字符匹配,则两个字符串可以联接。
问这n个字符串最多可以连成一个多长的字符串,如果出现循环,则返回错误。
14、如果字符串一的所有字符按其在字符串中的顺序出现在另外一个字符串二中,则字符串一称之为字符串二的子串。
注意,并不要求子串(字符串一)的字符必须连续出现在字符串二中。
请编写一个函数,输入两个字符串,求它们的最长公共子串,并打印出最长公共子串。
例如:输入两个字符串BDCABA和ABCBDAB,字符串BCBA和BDAB都是是它们的最长公共子串,
则输出它们的长度4,并打印任意一个子串。
分析:求最长公共子串(Longest Common Subsequence, LCS)是一道非常经典的动态规划题。
15、输入两个字符串,从第一字符串中删除第二个字符串中所有的字符。
例如,输入"They are students."和"aeiou",则删除之后的第一个字符串变成"Thy r stdnts."。
16、一个文件,内含一千万行字符串,每个字符串在1K以内,要求找出所有相反的串对,如abc和cba。
17、给出一个函数来复制两个字符串A和B。字符串A的后几个字节和字符串B的前几个字节重叠。
18、已知一个字符串,比如asderwsde,寻找其中的一个子字符串比如sde的个数,如果没有返回0,有的话返回子字符串的个数。
19、求最大连续递增数字串(如"ads3sl456789DF3456ld345AA"中的"456789")。
20、实现strstr功能,即在父串中寻找子串首次出现的位置。
21、编码完成下面的处理函数。
函数将字符串中的字符'*'移到串的前部分,前面的非'*'字符后移,但不能改变非'*'字符的先后顺序,函数返回串中字符'*'的数量。
如原始串为:ab**cd**e*12,处理后为*****abcde12,函数并返回值为5。(要求使用尽量少的时间和辅助空间)
22、删除字符串中的数字并压缩字符串。如字符串”abc123de4fg56”处理后变为”abcdefg”。注意空间和效率。
23、求两个串中的第一个最长子串(神州数码以前试题)。如"abractyeyt","dgdsaeactyey"的最大子串为"actyet"。
【栈、链表、树、图】
1、编写一个程序,把一个有序整数数组放到二叉树中。
2、编程实现从顶部开始逐层打印二叉树节点数据。[参考]
3、编程实现单链表逆转。
4、设计一个算法,找出二叉树上任意两个结点的最近共同父结点。复杂度不能为O(n2)。
5、二叉排序树中,令f = (最大值+最小值) / 2,设计一个算法,找出距离f值最近、大于f值的结点。复杂度不能为O(n2)。
6、有双向循环链表结点定义为:
struct node
{
int data;
struct node *front,*next;
};
有两个双向循环链表A,B,知道其头指针为:pHeadA、pHeadB,请写一函数将两链表中data值相同的结点删除。
7、输入一个链表的头结点,从尾到头反过来输出每个结点的值。链表结点定义如下:
struct ListNode
{
int m_nKey;
ListNode* m_pNext;
};
8、输入一棵二元查找树,将该二元查找树转换成一个排序的双向链表。
要求不能创建任何新的结点,只调整指针的指向。
10
/ \
6 14
/ \ / \
4 8 12 16
转换成双向链表
4=6=8=10=12=14=16。
首先我们定义的二元查找树 节点的数据结构如下:
struct BSTreeNode
{
int m_nValue; // value of node
BSTreeNode *m_pLeft; // left child of node
BSTreeNode *m_pRight; // right child of node
}; [参考]
9、设计包含min函数的栈。
定义栈的数据结构,要求添加一个min函数,能够得到栈的最小元素。
要求函数min、push以及pop的时间复杂度都是O(1)。
10、输入一个整数和一棵二元树。从树的根结点开始往下访问一直到叶结点所经过的所有结点形成一条路径。
打印出和与输入整数相等的所有路径。
例如 输入整数22和如下二元树
10
/ \
5 12
/ \
4 7
则打印出两条路径:10, 12和10, 5, 7。
二元树节点的数据结构定义为:
struct BinaryTreeNode // a node in the binary tree
{
int m_nValue; // value of node
BinaryTreeNode *m_pLeft; // left child of node
BinaryTreeNode *m_pRight; // right child of node
};
11、给出俩个单向链表的头指针,比如h1,h2,判断这俩个链表是否相交。为了简化问题,我们假设俩个链表均不带环。
问题扩展:
(1) 如果链表可能有环列?
(2) 如果需要求出俩个链表相交的第一个节点列?
12、输入一个整数数组,判断该数组是不是某二元查找树的后序遍历的结果。
如果是返回true,否则返回false。
例如输入5、7、6、9、11、10、8,由于这一整数序列是如下树的后序遍历结果:
8
/ \
6 10
/ \ / \
5 7 9 11
因此返回true。
如果输入7、4、6、5,没有哪棵树的后序遍历的结果是这个序列,因此返回false。
13、如果我们把二叉树看成一个图,父子节点之间的连线看成是双向的,我们姑且定义"距离"为两节点之间边的个数。
写一个程序,求一棵二叉树中相距最远的两个节点之间的距离。
14、输入一个单向链表,输出该链表中倒数第k个结点。链表的倒数第0个结点为链表的尾指针。
链表结点定义如下:
struct ListNode
{
int m_nKey;
ListNode* m_pNext;
};
15、输入一颗二元查找树,将该树转换为它的镜像,即在转换后的二元查找树中,左子树的结点都大于右子树的结点。
用递归和循环两种方法完成树的镜像转换。
例如输入:
8
/ \
6 10
/\ /\
5 7 9 11
输出:
8
/ \
10 6
/ \/ \
11 97 5
定义二元查找树的结点为:
struct BSTreeNode
{
int m_nValue; // value of node
BSTreeNode *m_pLeft; // left child of node
BSTreeNode *m_pRight; // right child of node
}; [参考]
16、求一个二叉树中任意两个节点间的最大距离,两个节点的距离的定义是 这两个节点间边的个数。
比如某个孩子节点和父节点间的距离是1,和相邻兄弟节点间的距离是2,优化时间空间复杂度。
17、求一个有向连通图的割点,割点的定义是,如果除去此节点和与其相关的边,有向图不再连通,描述算法。
18、设计一个栈结构,满足一下条件:min,push,pop操作的时间复杂度为O(1)。
19、请修改append函数,利用这个函数实现:
两个非降序链表的并集,1->2->3 和 2->3->5 并为 1->2->3->5
另外只能输出结果,不能修改两个链表的数据。
20、递归和非递归俩种方法实现二叉树的前序遍历。
21、输入一棵二元树的根结点,求该树的深度。
从根结点到叶结点依次经过的结点(含根、叶结点)形成树的一条路径,最长路径的长度为树的深度。
22、用俩个栈实现队列,某队列的声明如下:
template<typename T> class CQueue
{
public:
CQueue() {}
~CQueue() {}
void appendTail(const T& node); // append a element to tail
void deleteHead(); // remove a element from head
private:
T m_stack1;
T m_stack2;
};
23、给定链表的头指针和一个结点指针,在O(1)时间删除该结点。链表结点的定义如下:
struct ListNode
{
int m_nKey;
ListNode* m_pNext;
};
函数的声明如下:void DeleteNode(ListNode* pListHead, ListNode* pToBeDeleted);
24、两个单向链表,找出它们的第一个公共结点。
链表的结点定义为:
struct ListNode
{
int m_nKey;
ListNode* m_pNext;
};
25、用递归颠倒一个栈。例如输入栈{1, 2, 3, 4, 5},1在栈顶。颠倒之后的栈为{5, 4, 3, 2, 1},5处在栈顶。
26、二叉树的结点定义如下:
struct TreeNode
{
int m_nvalue;
TreeNode* m_pLeft;
TreeNode* m_pRight;
};
输入二叉树中的两个结点,输出这两个结点在数中最低的共同父结点。
27、有一个复杂链表,其结点除了有一个m_pNext指针指向下一个结点外,还有一个m_pSibling指向链表中的任一结点或者NULL。
其结点的C++定义如下:
struct ComplexNode
{
int m_nValue;
ComplexNode* m_pNext;
ComplexNode* m_pSibling;
};
下图是一个含有5个结点的该类型复杂链表。
图中实线箭头表示m_pNext指针,虚线箭头表示m_pSibling指针。为简单起见,指向NULL的指针没有画出。
请完成函数ComplexNode* Clone(ComplexNode* pHead),以复制一个复杂链表。
28、给定单链表、检测是否有环。
29、给定两个单链表(head1, head2),检测两个链表是否有交点,如果有返回第一个交点。
30、给定单链表(head),如果有环的话请返回从头结点进入环的第一个节点。
31、只给定单链表中某个结点p(并非最后一个结点,即p->next!=NULL)指针,删除该结点。
32、只给定单链表中某个结点p(非空结点),在p前面插入一个结点。
33、编写实现链表排序的一种算法。说明为什么你会选择用这样的方法?
34、编写实现数组排序的一种算法。说明为什么你会选择用这样的方法?
35、怎样编写一个程序,把一个有序整数数组放到二叉树中?
【数组和集合】
1、有一个整数数组,请求出两两之差绝对值最小的值。
2、一个整数数列,元素取值可能是1~N(N是一个较大的正整数)中的任意一个数,相同数值不会重复出现。
设计一个算法,找出数列中符合条件的数对的个数,满足数对中两数的和等于N+1。复杂度不能为O(n2)。
3、给定一个集合A=[0,1,3,8](该集合中的元素都是在0,9之间的数字,但未必全部包含),指定任意一个正整数K,
请用A中的元素组成一个大于K的最小正整数。比如,A=[1,0] K=21 那么输出结构应该为100。
4、一个有序数列,序列中的每一个值都能够被2或者3或者5所整除,1是这个序列的第一个元素。求第1500个值是多少?
5、1-1000放在含有1001个元素的数组中,只有唯一的一个元素值重复,其它均只出现一次。
每个数组元素只能访问一次,设计一个算法,将它找出来,不用辅助存储空间。
6、一个含n个元素的整数数组至少存在一个重复数,请编程实现,在O(n)时间内找出其中任意一个重复数。
7、输入a1,a2,...,an,b1,b2,...,bn, 在O(n)的时间,O(1)的空间将这个序列顺序改为a1,b1,a2,b2,a3,b3,...,an,bn,
且不需要移动,通过交换完成,只需一个交换空间。
8、给定一个存放整数的数组,重新排列数组使得数组左边为奇数,右边为偶数。
要求:空间复杂度O(1),时间复杂度为O(n)。
9、输入一个整形数组,数组里有正数也有负数。数组中连续的一个或多个整数组成一个子数组,每个子数组都有一个和。
求所有子数组的和的最大值。要求时间复杂度为O(n)。
例如:输入的数组为1, -2, 3, 10, -4, 7, 2, -5,和最大的子数组为3, 10, -4, 7, 2,因此输出为该子数组的和18。
10、输入一个已经按升序排序过的数组和一个数字,在数组中查找两个数,使得它们的和正好是输入的那个数字。
要求:时间复杂度是O(n)。如果有多对数字的和等于输入的数字,输出任意一对即可。
例如:输入数组1、2、4、7、11、15和数字15。由于4+11=15,因此输出4和11。
11、有两个序列a,b,大小都为n,序列元素的值任意整数,无序;
要求:通过交换a,b中的元素,使[序列a元素的和]与[序列b元素的和]之间的差最小。
例如:
var a=[100,99,98,1,2, 3];
var b=[1, 2, 3, 4,5,40];
12、求一个矩阵中最大的二维矩阵(元素和最大)。如:
1 2 0 3 4
2 3 4 5 1
1 1 5 3 0
中最大的是:
4 5
5 3
要求:(1)写出算法;(2)分析时间复杂度;(3)用C写出关键代码。
13、一个整数数组,长度为n,将其分为m份,使各份的和相等,求m的最大值。
比如{3,2,4,3,6} 可以分成{3,2,4,3,6} m=1;
{3,6}{2,4,3} m=2
{3,3}{2,4}{6} m=3 所以m的最大值为3
14、求一个数组的最长递减子序列 比如{9,4,3,2,5,4,3,2}的最长递减子序列为{9,5,4,3,2}
15、如何对n个数进行排序,要求时间复杂度O(n),空间复杂度O(1)。
16、输入一个正数n,输出所有和为n连续正数序列。
例如:输入15,由于1+2+3+4+5=4+5+6=7+8=15,所以输出3个连续序列1-5、4-6和7-8。
17、给定一个存放整数的数组,重新排列数组使得数组左边为奇数,右边为偶数。
要求:空间复杂度O(1),时间复杂度为O(n)。
18、一个整型数组里除了两个数字之外,其他的数字都出现了两次。
请写程序找出这两个只出现一次的数字。要求时间复杂度是O(n),空间复杂度是O(1)。
19、输入一个正整数数组,将它们连接起来排成一个数,输出能排出的所有数字中最小的一个。
例如输入数组{32, 321},则输出这两个能排成的最小数字32132。
请给出解决问题的算法,并证明该算法。
20、把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。
输入一个排好序的数组的一个旋转,输出旋转数组的最小元素。
例如数组{3, 4, 5, 1, 2}为{1, 2, 3, 4, 5}的一个旋转,该数组的最小值为1。
21、数组中有一个数字出现的次数超过了数组长度的一半,找出这个数字。
22、一个int数组,里面数据无任何限制,要求求出所有这样的数a[i],其左边的数都小于等于它,右边的数都大于等于它。
能否只用一个额外数组和少量其它空间实现。
23、在一个int数组里查找这样的数,它大于等于左侧所有数,小于等于右侧所有数。
24、求随机数构成的数组中找到长度大于=3的最长的等差数列,输出等差数列由小到大。
格式:
输入[1,3,0,5,-1,6]
输出[-1,1,3,5]
要求时间复杂度,空间复杂度尽量小。
25、递归法求数组中的最大值。[参考]
26、用递归的方法判断整数组a[N]是不是升序排列。
27、计算数组中连续元素和的最大值。[参考]
【其它】
1、1024!末尾有多少个0?[参考]
2、编程实现两个正整数的除法(不能用除法操作符)。
3、请定义一个宏,比较两个数a、b的大小,不能使用大于、小于、if语句。
4、两个数相乘,小数点后位数没有限制,请写一个高精度算法。
5、编程实现把十进制数(long型)分别以二进制和十六进制形式输出,不能使用printf系列。
6、输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字。
例如:如果输入如下矩阵:
1 2 3 4
5 6 7 8
9 10 11 12
13 14 15 16
则依次打印出数字1, 2, 3, 4, 8, 12, 16, 15, 14, 13, 9, 5, 6, 7, 11, 10。
7、用1、2、2、3、4、5这六个数字,写一个main函数,打印出所有不同的排列。
如:512234、412345等,要求:"4"不能在第三位,"3"与"5"不能相连。
8、求两个或N个数的最大公约数和最小公倍数。
9、如果一个整数能够表示成两个或多个素数之和,则得到一个素数和分解式。
对于一个给定的整数,输出所有这种素数和分解式。
注意,对于同构的分解只输出一次(比如5只有一个分解2 + 3,而3 + 2是2 + 3的同构分解式)。
例如,对于整数8,可以作为如下三种分解:
(1) 8 = 2 + 2 + 2 + 2
(2) 8 = 2 + 3 + 3
(3) 8 = 3 + 5
10、输入n个整数,输出其中最小的k个。
例如输入1,2,3,4,5,6,7和8这8个数字,则最小的4个数字为1,2,3和4。
11、求1+2+…+n
要求不能使用乘除法、for、while、if、else、switch、case等关键字以及条件判断语句(A ? B : C)。
12、定义Fibonacci数列如下:
0 if n = 0
f(n)= 1 if n = 1
f(n-1)+f(n-2) if n >= 2
输入n,用最快的方法求该数列的第n项。[参考]
13、输入两个整数 n 和 m,从数列1,2,3.......n 中 随意取几个数,使其和等于m。
要求将其中所有的可能组合列出来。
14、输入一个整数n,求从1到n这n个整数的十进制表示中1出现的次数。
15、对于一个整数矩阵,存在一种运算,对矩阵中任意元素加一时,需要其相邻(上下左右)某一个元素也加一。
现给出一正数矩阵,判断其是否能够由一个全零矩阵经过上述运算得到。
16、四对括号可以有多少种匹配排列方式?比如两对括号可以有两种:()()和(())
17、我们把只包含因子2、3和5的数称作丑数(Ugly Number)。
例如:6、8都是丑数,但14不是,因为它包含因子7。习惯上我们把1当做是第一个丑数。
求按从小到大的顺序的第1500个丑数。
18、输入数字n,按顺序输出从1最大的n位10进制数。比如输入3,则输出1、2、3一直到最大的3位数即999。
19、大整数数相乘的问题。