天天看点

程序员面试金典算法题空格替换基本字符串压缩确定字符互异原串翻转确定两串乱序同构像素翻转清除行列翻转子串访问单个节点的删除链表分割链式A+B回文链表双栈排序二叉树平衡检查输出单层结点检查是否为BST寻找下一个结点二进制插入二进制小数最接近的数整数转化奇偶位交换找出缺失的整数像素设定第k个数碰撞的蚂蚁上楼梯机器人走方格I机器人走方格II魔术索引I魔术索引II

题目描述

请编写一个方法,将字符串中的空格全部替换为“%20”。假定该字符串有足够的空间存放新增的字符,并且知道字符串的真实长度(小于等于1000),同时保证字符串由大小写的英文字母组成。

给定一个string inistring 为原始的串,以及串的长度 int len, 返回替换后的string。

测试样例:

“mr john smith”,13

返回:”mr%20john%20smith”

”hello world”,12

返回:”hello%20%20world”

利用字符重复出现的次数,编写一个方法,实现基本的字符串压缩功能。比如,字符串“aabcccccaaa”经压缩会变成“a2b1c5a3”。若压缩后的字符串没有变短,则返回原先的字符串。

给定一个string inistring为待压缩的串(长度小于等于3000),保证串内字符均由大小写英文字母组成,返回一个string,为所求的压缩后或未变化的串。

测试样例

“aabcccccaaa”

返回:”a2b1c5a3”

“welcometonowcoderrrrr”

返回:”welcometonowcoderrrrr”

请实现一个算法,确定一个字符串的所有字符是否全都不同。这里我们要求不允许使用额外的存储结构。

给定一个string inistring,请返回一个bool值,true代表所有字符全都不同,false代表存在相同的字符。保证字符串中的字符为ascii字符。字符串的长度小于等于3000。

“aeiou”

返回:true

“barackobama”

返回:false

请实现一个算法,在不使用额外数据结构和储存空间的情况下,翻转一个给定的字符串(可以使用单个过程变量)。

给定一个string inistring,请返回一个string,为翻转后的字符串。保证字符串的长度小于等于5000。

“this is nowcoder”

返回:”redocwon si siht”

给定两个字符串,请编写程序,确定其中一个字符串的字符重新排列后,能否变成另一个字符串。这里规定大小写为不同字符,且考虑字符串重点空格。

给定一个string stringa和一个string stringb,请返回一个bool,代表两串是否重新排列后可相同。保证两串的长度都小于等于5000。

“this is nowcoder”,”is this nowcoder”

“here you are”,”are you here”

有一副由nxn矩阵表示的图像,这里每个像素用一个int表示,请编写一个算法,在不占用额外内存空间的情况下(即不使用缓存矩阵),将图像顺时针旋转90度。

给定一个nxn的矩阵,和矩阵的阶数n,请返回旋转后的nxn矩阵,保证n小于等于500,图像元素小于等于256。

[[1,2,3],[4,5,6],[7,8,9]],3

返回:[[7,4,1],[8,5,2],[9,6,3]]

解析:首先沿对角线折叠,然后交换列

请编写一个算法,若mxn矩阵中某个元素为0,则将其所在的行与列清零。

给定一个mxn的int[][]矩阵(c++中为vector>)mat和矩阵的阶数n,请返回完成操作后的int[][]矩阵(c++中为vector>),保证n小于等于300,矩阵中的元素为int范围内。

[[1,2,3],[0,1,2],[0,0,1]]

返回:[[0,0,3],[0,0,0],[0,0,0]]

假定我们都知道非常高效的算法来检查一个单词是否为其他字符串的子串。请将这个算法编写成一个函数,给定两个字符串s1和s2,请编写代码检查s2是否为s1旋转而成,要求只能调用一次检查子串的函数。

给定两个字符串s1,s2,请返回bool值代表s2是否由s1旋转而成。字符串中字符为英文字母和空格,区分大小写,字符串长度小于等于1000。

“hello world”,”worldhello ”

“waterbottle”,”erbottlewat”

实现一个算法,删除单向链表中间的某个结点,假定你只能访问该结点。

给定带删除的节点,请执行删除操作,若该节点为尾节点,返回false,否则返回true

编写代码,以给定值x为基准将链表分割成两部分,所有小于x的结点排在大于或等于x的结点之前

给定一个链表的头指针 listnode* phead,请返回重新排列后的链表的头指针。

有两个用链表表示的整数,每个结点包含一个数位。这些数位是反向存放的,也就是个位排在链表的首部。编写函数对这两个整数求和,并用链表形式返回结果。

给定两个链表listnode* a,listnode* b,请返回a+b的结果(listnode*)。

{1,2,3},{3,2,1}

返回:{4,4,4}

请编写一个函数,检查链表是否为回文。

给定一个链表listnode* phead,请返回一个bool,代表链表是否为回文。

{1,2,3,2,1}

{1,2,3,2,3}

请编写一个程序,按升序对栈进行排序(即最大元素位于栈顶),要求最多只能使用一个额外的栈存放临时数据,但不得将元素复制到别的数据结构中。

给定一个int[] numbers(c++中为vector),其中第一个元素为栈顶,请返回排序后的栈。请注意这是一个栈,意味着排序过程中你只能访问到第一个元素。

[1,2,3,4,5]

返回:[5,4,3,2,1]

实现一个函数,检查二叉树是否平衡,平衡的定义如下,对于树中的任意一个结点,其两颗子树的高度差不超过1。

给定指向树根结点的指针treenode* root,请返回一个bool,代表这棵树是否平衡。

对于一棵二叉树,请设计一个算法,创建含有某一深度上所有结点的链表。

给定二叉树的根结点指针treenode* root,以及链表上结点的深度,请返回一个链表listnode,代表该深度上所有结点的值,请按树上从左往右的顺序链接,保证深度不超过树的高度,树上结点的值为非负整数且不超过100000。

请实现一个函数,检查一棵二叉树是否为二叉查找树。

给定树的根结点指针treenode* root,请返回一个bool,代表该树是否为二叉查找树。

请设计一个算法,寻找二叉查找树中指定结点的下一个结点(即中序遍历的后继)。

给定树的根结点指针treenode* root和结点的值int p,请返回值为p的结点的后继结点的值。保证结点的值大于等于零小于等于100000且没有重复值,若不存在后继返回-1。

有两个32位整数n和m,请编写算法将m的二进制数位插入到n的二进制的第j到第i位,其中二进制的位数从低位数到高位且以0开始。

给定两个数int n和int m,同时给定int j和int i,意义如题所述,请返回操作后的数,保证n的第j到第i位均为零,且m的二进制位数小于等于j-i+1。

1024,19,2,6

返回:1100

有一个介于0和1之间的实数,类型为double,返回它的二进制表示。如果该数字无法精确地用32位以内的二进制表示,返回“error”。

给定一个double num,表示0到1的实数,请返回一个string,代表该数的二进制表示或者“error”。

0.625

返回:0.101

有一个正整数,请找出其二进制表示中1的个数相同、且大小最接近的那两个数。(一个略大,一个略小)

给定正整数int x,请返回一个vector,代表所求的两个数(小的在前)。保证答案存在。

2

返回:[1,4]

编写一个函数,确定需要改变几个位,才能将整数a转变成整数b。

给定两个整数int a,int b。请返回需要改变的数位个数。

10,5

返回:4

请编写程序交换一个数的二进制的奇数位和偶数位。(使用越少的指令越好)

给定一个int x,请返回交换后的数int。

10

返回:5

数组a包含了0到n的所有整数,但其中缺失了一个。对于这个问题,我们设定限制,使得一次操作无法取得数组number里某个整数的完整内容。唯一的可用操作是询问数组中第i个元素的二进制的第j位(最低位为第0位),该操作的时间复杂度为常数,请设计算法,在o(n)的时间内找到这个数。

给定一个数组number,即所有剩下的数按从小到大排列的二进制各位的值,如a[0][1]表示剩下的第二个数二进制从低到高的第二位。同时给定一个int n,意义如题。请返回缺失的数。

[[0],[0,1]]

返回:1

有一个单色屏幕储存在一维数组中,其中数组的每个元素代表连续的8位的像素的值,请实现一个函数,将第x到第y个像素涂上颜色(像素标号从零开始),并尝试尽量使用最快的办法。

给定表示屏幕的数组screen(数组中的每个元素代表连续的8个像素,且从左至右的像素分别对应元素的二进制的从低到高位),以及int x,int y,意义如题意所述,保证输入数据合法。请返回涂色后的新的屏幕数组。

[0,0,0,0,0,0],0,47

返回:[255,255,255,255,255,255]

或者

有一些数的素因子只有3、5、7,请设计一个算法,找出其中的第k个数。

给定一个数int k,请返回第k个数。保证k小于等于100。

3

返回:7

解析:

1. 初始化结果res=1和队列q3,q5,q7

2. 分别往q3,q5,q7插入1*3,1*5,1*7

3. 求出三个队列的队头元素中最小的那个x,更新结果res=x

4. 如果x在:

q3中,那么从q3中移除x,并向q3,q5,q7插入3*x,5*x,7*x

q5中,那么从q5中移除x,并向q5,q7插入5*x,7*x

q7中,那么从q7中移除x,并向q7插入7*x

5. 重复步骤3-5,直到找到第k个满足条件的数

在n个顶点的多边形上有n只蚂蚁,这些蚂蚁同时开始沿着多变形的边爬行,请求出这些蚂蚁相撞的概率。(这里的相撞是指存在任意两只蚂蚁会相撞)

给定一个int n(3<=n<=10000),代表n变形和n只蚂蚁,请返回一个double,为相撞的概率。

返回:0.75

有个小孩正在上楼梯,楼梯有n阶台阶,小孩一次可以上1阶、2阶、3阶。请实现一个方法,计算小孩有多少种上楼的方式。为了防止溢出,请将结果mod 1000000007

给定一个正整数int n,请返回一个数,代表上楼的方式数。保证n小于等于100000。

1

ac代码:

有一个xxy的网格,一个机器人只能走格点且只能向右或向下走,要从左上角走到右下角。请设计一个算法,计算机器人有多少种走法。

给定两个正整数int x,int y,请返回机器人的走法数目。保证x+y小于等于12。

2,2

返回:2

有一个xxy的网格,一个机器人只能走格点且只能向右或向下走,要从左上角走到右下角。请设计一个算法,计算机器人有多少种走法。注意这次的网格中有些障碍点是不能走的。

给定一个int[][] map(c++ 中为vector >),表示网格图,若map[i][j]为1则说明该点不是障碍点,否则则为障碍。另外给定int x,int y,表示网格的大小。请返回机器人从(0,0)走到(x - 1,y - 1)的走法数,为了防止溢出,请将结果mod 1000000007。保证x和y均小于等于50

在数组a[0..n-1]中,有所谓的魔术索引,满足条件a[i]=i。给定一个升序数组,元素值各不相同,编写一个方法,判断在数组a中是否存在魔术索引。请思考一种复杂度优于o(n)的方法。

给定一个int数组a和int n代表数组大小,请返回一个bool,代表是否存在魔术索引。

在数组a[0..n-1]中,有所谓的魔术索引,满足条件a[i]=i。给定一个不下降序列,元素值可能相同,编写一个方法,判断在数组a中是否存在魔术索引。请思考一种复杂度优于o(n)的方法。

[1,1,3,4,5]

继续阅读