本博客的《面试题目搜集系列不错》
(1)面试题目搜集1
(2)面试题目搜集2
(3)面试题目搜集3
(4)面试题目搜集4
(5)面试题目搜集5
(6)面试题目搜集6
1.有这样一个数组A,大小为n,相邻元素差的绝对值都是1。如:A={4,5,6,5,6,7,8,9,10,9}。现在,给定A和目标整数t,请找到t在A中的位置。除了依次遍历,还有更好的方法么?(来自新浪微博陈利人)
解法:数组第一个数为array[0], 要找的数为y,设t = abs(y - array[0])。由于每个相邻的数字之差的绝对值为1。故第t个位置之前的数肯定都比y小。因此直接定位到array[t],重新计算t,t = abs(y – array[t]),再重复上述步骤即可。这种算法主要利用了当前位置的数与查找数的差来实现跨越式搜索。算法效率要比遍历数组的算法要高一些,并且易于实现。
#include <iostream>
#include <cmath>
#include <exception>
using namespace std;
typedef int Index;
int FindNum(int arr[],int len,int target)
{
if(!arr||len<0)
throw new runtime_error("Invalid Input");
Index iter = abs(arr[0]-target);
while(iter < len){
if(arr[iter] == target)
return iter;
iter += abs(arr[iter] - target);
}
return -1;
}
void PrintArray(int arr[],int len)
{
if(!arr||len<0)
throw new runtime_error("Invalid Input");
for(Index iter=0; iter<len; ++iter){
cout<<arr[iter]<<" ";
}
cout<<endl;
}
int main()
{
const int ARR_MAX = 10;
int arr[ARR_MAX]={4,5,6,5,6,7,8,9,10,9};
PrintArray(arr,ARR_MAX);
int target = 5;
cout<<target<<"在数组中的索引为:";
cout<<FindNum(arr,ARR_MAX,target)<<endl;
target = 11;
cout<<target<<"在数组中的索引为:";
cout<<FindNum(arr,ARR_MAX,target)<<endl;
system("pause");
return 0;
}
2.一个大小为n的数组,里面的数都属于范围[0, n-1],有不确定的重复元素,找到至少一个重复元素,要求O(1)空间和O(n)时间。(google笔试题)
#include <iostream>
#include <cmath>
#include <exception>
using namespace std;
typedef int Index;
void Swap(int &a, int &b)
{
int temp = a;
a = b;
b = temp;
}
//解法1
// int FindNotReaptedNum(int arr[],int len)
// {
// if(!arr||len<0)
// throw new runtime_error("Invalid Input");
//
// for(int i=0; i<len; ++i){
// while(arr[i] != i){
// if(arr[i] == arr[arr[i]])
// return arr[i];
// Swap(arr[i],arr[arr[i]]);
// }
// }
//
// return -1;
// }
//解法2
int FindNotReaptedNum(int arr[],int len)
{
if(!arr||len<0)
throw new runtime_error("Invalid Input");
for(int i=0; i<len; ++i){
if(arr[i] > 0){
if(arr[arr[i]]<0)
return arr[i];
arr[arr[i]] = -arr[arr[i]];
}
else{
if(arr[-arr[i]]<0)
return -arr[i];
arr[-arr[i]] = -arr[-arr[i]];
}
}
return -1;
}
void PrintArray(int arr[],int len)
{
if(!arr||len<0)
throw new runtime_error("Invalid Input");
for(Index iter=0; iter<len; ++iter){
cout<<arr[iter]<<" ";
}
cout<<endl;
}
int main()
{
const int ARR_MAX = 10;
int arr[ARR_MAX]={2,5,3,5,6,7,8,9,10,1};
PrintArray(arr,ARR_MAX);
cout<<"在数组重复的数为:";
cout<<FindNotReaptedNum(arr,ARR_MAX)<<endl;
system("pause");
return 0;
}
本题的解法参考morewindow,详细可以查看原文:google面试题解法1;google面试题解法2
3.KMP算法编写(某IT公司面试)
#include <iostream>
#include <string>
using namespace std;
const int MAX = 10;
int next[MAX] = {0};
void GetNext(string pattern)
{
int j = 0;
int k = -1;
int lengthP = pattern.size();
next[0] = -1;
while(j < lengthP){
if(k == -1||pattern[j] == pattern[k]){
++k;
++j;
next[j] = k;
}
else k = next[k];
}
}
//改进的算法
// void GetNext(string pattern)
// {
// int j = 0;
// int k = -1;
// int lengthP = pattern.size();
// next[0] = -1;
//
// while(j < lengthP){
// if(k == -1||pattern[j] == pattern[k]){
// ++k;
// ++j;
// if(pattern[k] == pattern[j])
// next[j] = next[k];
// else next[j] = k;
// }
// else k = next[k];
// }
// }
int FindStr(string target,string pattern)
{
int lengthP = pattern.size();
int lengthT = target.size();
int pPos = 0;
int tPos = 0;
GetNext(pattern);
while(pPos < lengthP && tPos < lengthT){
if(pPos == -1||target[tPos] == pattern[pPos]){
++pPos;
++tPos;
}
else
pPos = next[pPos];
}
if(pPos < lengthP - 1)return - 1;
else return tPos - lengthP;
}
void PrintArray(int arr[],int len)
{
for(int i=0; i<len; ++i)
cout<<arr[i]<<" ";
cout<<endl;
}
int main()
{
string pattern("abaabcac");
string target("aadfdfdfabaabcacddadsdf");
GetNext(pattern);
PrintArray(next,pattern.size());
cout<<FindStr(target,pattern)<<endl;
system("pause");
return 0;
}
4.长度为n的数组乱序存放着 0 至n-1. 现在只能进行 0 与其他数的swap,请设计并实现排序。(google的一道笔试题)
#include <iostream>
using namespace std;
void Sort(int arr[],int len)
{
for(int i=0; i<len; ++i){
if(arr[i] != i){
swap(arr[0],arr[i]);
while(arr[0]!=0){
swap(arr[0],arr[arr[0]]);
}
}
}
}
void PrintArray(int arr[],int len)
{
for(int i=0; i<len; ++i){
cout<<arr[i]<<" ";
}
cout<<endl;
}
int main()
{
const int MAX = 5;
int arr[MAX] = {0,2,1,4,3};
PrintArray(arr,MAX);
Sort(arr,MAX);
PrintArray(arr,MAX);
system("pause");
return 0;
}
该题不知道对不对,测试用例是通过的,也是跟我同宿舍的warringh得出了这个答案。
这个题思路:首先把arr[0]的位置换到应该在的位置,然后arr[arr[0]]换到arr[0],然后又通过swap(arr[0],arr[arr[0]])将
arr[arr[0]]换到它应该在的位置,如此循环。但是这存在一个小的问题,就像上面代码给的案例{0,2,1,4,3},,此时arr[0]已经出现在其位置上了,这就需要后面遍历一个元素将其交换到arr[0]这个位置上来。交换几步后发现:该数组出现这么一种情况{0,1,2,4,3},前面三个已经排好,后面两个没排好,此时向后遍历将4与0元素交换,继续进行就能得到想要的答案。
5.如何判断栈中增长方向
#include <stdio.h>
#include <stdlib.h>
void func1();
void func2(int *a);
int main(int argc, char** argv) {
func1();
return (EXIT_SUCCESS);
}
void func1(){
int a = 0;
func2(&a);
}
void func2(int *a){
int b = 0;
printf("%x\n%x\n",a,&b);
}
这段代码只所以能够判断栈的增长方向,这和调用函数时栈的使用方法是分不开的,系统在调用函数时,函数内部的局部变量会入栈(入栈顺序和函数内的变量申明顺序可能不一样, 这和编译器有一定的关系,所以不能通过一个函数内的多个变量在栈中的地址来判断栈的增长方向),这里涉及两个函数调用,第一个函数func1中申明了一个变量,然后将指向其的指针传递给函数func2,然后再在func2中申明一个变量,打印出两个变量的地址,比较地址的大小,就可知道栈的增长方向了,如果func1里的变量地址比func2里的变量地址大,则说明栈的增长方向是由高地址向低地址增长的,反之,则说明栈的增长方向是由低地址向高地址增长的,以上程序要我的机器上运行的结果如下(程序在不同时刻运行,会有不同的输出,所以大家运行的结果会和下面的结果不同,不过这没有关系,大家只要比较两个输出值的大小,就能进行方向判定了):
bfdbf0ac
bfdbf07c
另一张解法:
static int stack_dir;
static void find_stack_direction (void) {
static char *addr = NULL; /* address of first
`dummy', once known */
char dummy; /* to get stack address */
if (addr == NULL)
{ /* initial entry */
addr = &dummy;
find_stack_direction (); /* recurse once */
}
else /* second entry */
if (&dummy > addr)
stack_dir = 1; /* stack grew upward */
else
stack_dir = -1; /* stack grew downward */
}
int main(void)
{
find_stack_direction();
if(stack_dir==1)
puts("stack grew upward");
else
puts("stack grew downward");
return 0;
}
find_stack_direction函数使用函数递归的方法
第一次进入,由于addr为NULL,所以将字符变量dummy的地址赋值给静态变量addr
第二次进入,由于静态变量addr已赋了值,所以进入 "Second entry."
接着,将第二次进入的dummy地址和第一次进入的dummy地址相比较
如果值为正,则堆栈向高地址增长;否则,堆栈向低地址增长