微软、谷歌、百度等公司经典面试100题[第1-60题]——自己的实现
2011-03-14 13:18
756 查看
题目来源自http://blog.csdn.net/v_JULY_v/archive/2011/03/09/6234496.aspx
1、有一个整数数组,请求出两两之差绝对值最小的值,
记住,只要得出最小值即可,不需要求出是哪两个数
2、写一个函数,检查字符是否是整数,如果是,返回其整数值。
(或者:怎样只用4行代码编写出一个从字符串到长整形的函数)
http://blog.csdn.net/cadcisdhht/archive/2011/02/21/6197041.aspx
3、给出一个函数来输出一个字符串的所有排列。
4、请编写实现malloc()内存分配函数功能一样的代码。
给出一个函数来复制两个字符串A和B。字符串A的后几个字节和字符串B的前几个字节重叠。
http://lklkdawei.blog.163.com/blog/static/32574109200881445518891/
不会做!
5、怎样编写一个程序,把一个有序整数数组放到二叉树中?
6、怎样从顶部开始逐层打印二叉树结点数据?请编程。
两题的答案下面代码!
7、怎样把一个链表掉个顺序(也就是反序,注意链表的边界条件并考虑空链表)?
8、请编写能直接实现int atoi(const char * pstr)函数功能的代码。
9、编程实现两个正整数的除法
编程实现两个正整数的除法,当然不能用除法操作符。
// return x/y.
int div(const int x, const int y)
{
....
}
10、在排序数组中,找出给定数字的出现次数
比如 [1, 2, 2, 2, 3] 中2的出现次数是3次。
[b]11、平面上N个点,每两个点都确定一条直线,
求出斜率最大的那条直线所通过的两个点(斜率不存在的情况不考虑)。时间效率越高越好。[/b]
不会!
[b]12、一个整数数列,元素取值可能是0~65535中的任意一个数,相同数值不会重复出现。0是例外,可以反复出现。
请设计一个算法,当你从该数列中随意选取5个数值,判断这5个数值是否连续相邻。
注意:
- 5个数值允许是乱序的。比如: 8 7 5 0 6
- 0可以通配任意数值。比如:8 7 5 0 6 中的0可以通配成9或者4
- 0可以多次出现。
- 复杂度如果是O(n2)则不得分。[/b]
13、设计一个算法,找出二叉树上任意两个结点的最近共同父结点。
复杂度如果是O(n2)则不得分。
14、一棵排序二叉树,令 f=(最大值+最小值)/2,
设计一个算法,找出距离f值最近、大于f值的结点。
复杂度如果是O(n2)则不得分。
[b]15、一个整数数列,元素取值可能是1~N(N是一个较大的正整数)中的任意一个数,相同数值不会重复出现。
设计一个算法,找出数列中符合条件的数对的个数,满足数对中两数的和等于N+1。
复杂度最好是O(n),如果是O(n2)则不得分.[/b]
谷歌八道面试题
16、正整数序列Q中的每个元素都至少能被正整数a和b中的一个整除,现给定a和b,需要计算出Q中的前几项,例如,当a=3,b=5,N=6时,序列为3,5,6,9,10,12
(1)、设计一个函数void generate(int a,int b,int N ,int * Q)计算Q的前几项
(2)、设计测试数据来验证函数程序在各种输入下的正确性。
17、有一个由大小写组成的字符串,现在需要对他进行修改,将其中的所有小写字母排在答谢字母的前面(大写或小写字母之间不要求保持原来次序),如有可能尽量选择时间和空间效率高的算法 c语言函数原型void proc(char *str) 也可以采用你自己熟悉的语言
18、如何随机选取1000个关键字
给定一个数据流,其中包含无穷尽的搜索关键字(比如,人们在谷歌搜索时不断输入的关键字)。如何才能从这个无穷尽的流中随机的选取1000个关键字?
定义长度为1000的数组。
对于数据流中的前1000个关键字,显然都要放到数组中。
对于数据流中的的第n(n>1000)个关键字,我们知道这个关键字被随机选中的概率为 1000/n。所以我们以 1000/n 的概率用这个关键 字去替换数组中的随机一个。这样就可以保证所有关键字都以 1000/n的概率被选中。
对于后面的关键字都进行这样的处理,这样我们就可以保证数组中总是保存着1000个随机关键字。
19、判断一个自然数是否是某个数的平方
说明:当然不能使用开方运算。
假设待判断的数字是
N。
方法1:
遍历从1到N的数字,求取平方并和N进行比较。
如果平方小于N,则继续遍历;如果等于N,则成功退出;如果大于N,则失败退出。
复杂度为O(n^0.5)。
方法2:
使用二分查找法,对1到N之间的数字进行判断。
复杂度为O(log
n)。
方法3:
由于
(n+1)^2
=n^2 + 2n + 1,
= ...
= 1 + (2*1 + 1)
+ (2*2 + 1) + ... + (2*n + 1)
注意到这些项构成了等差数列(每项之间相差2)。
所以我们可以比较 N-1, N - 1
- 3, N - 1 - 3 - 5 ... 和0的关系。
如果大于0,则继续减;如果等于0,则成功退出;如果小于
0,则失败退出。
复杂度为O(n^0.5)。不过方法3中利用加减法替换掉了方法1中的乘法,所以速度会更快些。
21、1024! 末尾有多少个0?
末尾0的个数取决于乘法中因子2和5的个数。显然乘法中因子2的个数大于5的个数,所以我们只需统计因子5的个数。
是5的倍数的数有:
1024 / 5 = 204个
是25的倍数的数有:1024 / 25 = 40个
是125的倍数的数有:1024 / 125 =
8个
是625的倍数的数有:1024 / 625 = 1个
所以1024! 中总共有204+40+8+1=253个因子5。
也就是说1024!
末尾有253个0。
23、Google2009华南地区笔试题
给定一个集合A=[0,1,3,8](该集合中的元素都是在0,9之间的数字,但未必全部包含),
指定任意一个正整数K,请用A中的元素组成一个大于K的最小正整数。
比如,A=[1,0] K=21 那么输出结构应该为100。
这个问题,应该逼近法
数组 数组biaozhi[0..9] biaozhi[i]=true 则表示i包含在集合中,0<=i<=9;
从整数k的高位往底位判断
设k当前位的数值为i,
if biaozhi[i]=true
{
进行下一位判断;
}
else //biaozhi[i]=false
{
当集合中有比i大的值记为m,则 把k的当前位用m代替,从k位下一位往个位用集合中最小值填充
当集合中没有比i大的值,则从k的上1位回溯
}
26、有一根27厘米的细木杆,在第3厘米、7厘米、11厘米、17厘米、23厘米这五个位置上各有一只蚂蚁。
木杆很细,不能同时通过一只蚂蚁。开始时,蚂蚁的头朝左还是朝右是任意的,它们只会朝前走或调头,但不会后退。
当任意两只蚂蚁碰头时,两只蚂蚁会同时调头朝反方向走。假设蚂蚁们每秒钟可以走一厘米的距离。
编写程序,求所有蚂蚁都离开木杆的最小时间和最大时间。
解析:可以采用鬼魂算法,鬼魂的意思就是“传递能量”,“穿透”。
首先判断最靠近中间点的蚂蚁,用程序很好判断,就是11厘米处的蚂蚁,其实这个蚂蚁,最快的时间就是最小时间。
其次判断最靠外面的蚂蚁,用程序很好判断,就是3厘米处的蚂蚁,其实这个蚂蚁,最慢的时间就是最大时间。
其他蚂蚁无视就可以了。
答案:最大时间是27-3=24,最小时间是11-0=11。
雅虎三道面试题
34、编程实现:把十进制数(long型)分别以二进制和十六进制形式输出,不能使用printf系列
35、编程实现:找出两个字符串中最大公共子字符串,如"abccade","dgcadde"的最大子串为"cad"
38、顺时针打印矩阵
题目:输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字。
例如:如果输入如下矩阵:
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。
分析:包括Autodesk、EMC在内的多家公司在面试或者笔试里采用过这道题。
39、对称子字符串的最大长度
题目:输入一个字符串,输出该字符串中对称的子字符串的最大长度。
比如输入字符串“google”,由于该字符串里最长的对称子字符串是“goog”,因此输出4。
分析:可能很多人都写过判断一个字符串是不是对称的函数,这个题目可以看成是该函数的加强版。
40、用1、2、2、3、4、5这六个数字,写一个main函数,打印出所有不同的排列,
如:512234、412345等,要求:"4"不能在第三位,"3"与"5"不能相连.
48、找出数组中唯一的重复元素
1-1000放在含有1001个元素的数组中,只有唯一的一个元素值重复,其它均只出现一次.
每个数组元素只能访问一次,设计一个算法,将它找出来;不用辅助存储空间,
能否设计一个算法实现?
50、一道SPSS笔试题求解
题目:输入四个点的坐标,求证四个点是不是一个矩形
关键点:
1.相邻两边斜率之积等于-1,
2.矩形边与坐标系平行的情况下,斜率无穷大不能用积判断。
3.输入四点可能不按顺序,需要对四点排序。
取值为【1,n-1】含n个元素的整数数组至少存在一个重复数,O(n)时间内找出其中任意一个重复数
1、有一个整数数组,请求出两两之差绝对值最小的值,
记住,只要得出最小值即可,不需要求出是哪两个数
#include <iostream> #include <cassert> #include <ctime> #include <iterator> using namespace std; /************************************************************************/ /* 函数功能:有一个整数数组,请求出两两之差绝对值最小的值 思路:两个for循环,记录每次的最小值,复杂度为o(N) */ /************************************************************************/ int GetMinDiff(int arr[], int length) { assert(length >=2 ); int min = abs(arr[1] - arr[0]); for (int i=0; i<length-1; i++) { for (int j=i+1; j<length; j++) { if(abs(arr[j] - arr[i]) < min) min = abs(arr[j] - arr[i]); } } return min; } /************************************************************************/ /* 方法2:先对数组排序(快速排序),然后求两两差值的最小值,复杂度为O(lgN + N)* / /************************************************************************/ int cmp(const void *a, const void *b) { return *(int *)a - *(int *)b; } int GetMinDiff2(int arr[], int length) { qsort(arr, 10, sizeof(arr[0]), cmp); assert(length >= 2); int min = abs(arr[1] - arr[0]); for (int i=3; i<length; i++) { if (abs(arr[i] - arr[i-1]) < min) min = abs(arr[i] - arr[i-1]); } return min; } int main() { int arr[10]; srand((unsigned int)time(NULL)); for(int i=0; i<10; i++) arr[i] = rand()%100; copy(arr, arr+10, ostream_iterator<int>(cout, " ")); cout<<endl; int minDiff = GetMinDiff(arr, 10); cout<<minDiff<<endl; minDiff = GetMinDiff(arr, 10); cout<<minDiff<<endl; }
2、写一个函数,检查字符是否是整数,如果是,返回其整数值。
(或者:怎样只用4行代码编写出一个从字符串到长整形的函数)
http://blog.csdn.net/cadcisdhht/archive/2011/02/21/6197041.aspx
3、给出一个函数来输出一个字符串的所有排列。
#include <iostream> #include <cassert> #include <ctime> #include <iterator> using namespace std; void swap(char *str, int i, int j) { char temp = str[i]; str[i] = str[j]; str[j] = temp; } /************************************************************************/ /* 函数功能:递归求全排列 */ /************************************************************************/ void GetQuanPaiLie(char *str, int current, int length) { if(current == length-1) cout<<str<<endl; else { for (int i=current; i<length; i++) { swap(str, current, i); GetQuanPaiLie(str, current+1, length); swap(str, current, i); } } } int main() { char str[] = "abc"; GetQuanPaiLie(str, 0, 3); }
4、请编写实现malloc()内存分配函数功能一样的代码。
给出一个函数来复制两个字符串A和B。字符串A的后几个字节和字符串B的前几个字节重叠。
http://lklkdawei.blog.163.com/blog/static/32574109200881445518891/
不会做!
5、怎样编写一个程序,把一个有序整数数组放到二叉树中?
6、怎样从顶部开始逐层打印二叉树结点数据?请编程。
两题的答案下面代码!
#include <iostream> #include <deque> using namespace std; struct TNode { int element; TNode* left; TNode* right; TNode(int ele = 0, TNode* l = NULL, TNode* t= NULL) :element(ele), left(l), right(t){} }; /************************************************************************/ /*函数功能:将一个有序整数数组放到二叉树中 */ /************************************************************************/ TNode* ConvertArrayToBinaryTree(int arr[], int current, int legth) { TNode *root = NULL; if (current < legth) { root = new TNode(arr[current]); if(2*current + 1 < legth) root->left = ConvertArrayToBinaryTree(arr, 2*current + 1, legth); if(2*current + 2 < legth) root->right = ConvertArrayToBinaryTree(arr, 2*current + 2, legth); } return root; } /************************************************************************/ /* 函数功能:从顶部开始逐层打印二叉树结点数据(借助队列实现) */ /************************************************************************/ void levelOutPut(TNode* root) { if(root == NULL) return; deque<TNode*> d; d.push_back(root); while(!d.empty()) { cout<<d.front()->element<<" "; if(d.front()->left != NULL) d.push_back(d.front()->left); if (d.front()->right != NULL) d.push_back(d.front()->right); d.pop_front(); } } int main() { int arr[10]; for (int i=0; i<10; i++) arr[i] = i+1; TNode *root = ConvertArrayToBinaryTree(arr, 0, sizeof(arr)/sizeof(arr[0])); cout<<"层次输出二叉树:"<<endl; levelOutPut(root); cout<<endl; }
7、怎样把一个链表掉个顺序(也就是反序,注意链表的边界条件并考虑空链表)?
#include <iostream> #include <deque> using namespace std; struct Node { int element; Node* pNext; Node(int ele, Node *next = NULL) { element = ele; pNext = next; } }; /************************************************************************/ /* 函数功能:构建单链表 */ /************************************************************************/ Node* BuildList(int arr[], int length) { Node* head = NULL; //头结点 if(length > 0) { head = new Node(arr[0]); Node* curr = head; Node* newNode = NULL; //新创建的节点 for (int i=1; i<length; i++) { newNode = new Node(arr[i]); curr->pNext = newNode; curr = newNode; } } return head; } //函数功能:输出单链表 void PrintList(Node* head) { Node *temp = head; while (temp != NULL) { cout<<temp->element<<" "; temp = temp->pNext; } cout<<endl; } //函数功能:反转单链表 Node* ReverseList(Node* head) { if((head == NULL) || (head->pNext == NULL)) //0个或1个结点 return head; Node* p = NULL; Node* tempHead = head; while (tempHead->pNext != NULL) { p = tempHead->pNext; tempHead->pNext = p->pNext; p->pNext = head; head = p; } return head; } int main() { int arr[10]; for(int i=0; i<10; i++) arr[i] = i + 1; Node *head = BuildList(arr, 10); cout<<"反转前:"<<endl; PrintList(head); cout<<"反转前:"<<endl; head = ReverseList(head); PrintList(head); }
8、请编写能直接实现int atoi(const char * pstr)函数功能的代码。
#include <iostream> #include <cassert> using namespace std; int Myatoi(const char *pstr) { assert(pstr != NULL); //判断不为空 const char *temp = pstr; while (*temp == ' ') // 去除开头的空字符 temp++; int result = 0; int flag = 1; // 正负值标志位 if(*temp == '-') //若为负数 { flag = -1; temp++; } while (*temp != '/0') { result = result * 10 + (*temp - '0'); temp++; } return result * flag; } int main() { const char* str1 = "1234"; const char* str2 = "-567"; const char* str3 = " 455"; const char* str4 = " -45677"; cout<<Myatoi(str1)<<endl; cout<<Myatoi(str2)<<endl; cout<<Myatoi(str3)<<endl; cout<<Myatoi(str4)<<endl; }
9、编程实现两个正整数的除法
编程实现两个正整数的除法,当然不能用除法操作符。
// return x/y.
int div(const int x, const int y)
{
....
}
#include <iostream> using namespace std; /************************************************************************/ /* 函数功能:编程实现两个正整数的除法,当然不能用除法操作符 ×/ /************************************************************************/ int Mydiv(const int x, const int y) { int result = 0; int temp = x; while (temp >= y) { result++; temp = temp - y; } return result; } int main() { cout<<Mydiv(20, 4)<<endl; cout<<Mydiv(20, 7)<<endl; }
10、在排序数组中,找出给定数字的出现次数
比如 [1, 2, 2, 2, 3] 中2的出现次数是3次。
#include <iostream> using namespace std; /************************************************************************/ /* 函数功能:在排序数组中,找出给定数字的出现次数 比如 [1, 2, 2, 2, 3] 中2的出现次数是3次。 陷阱:一个看到题,首先想到的方法是进行遍历统计,这样时间复杂度为O(N), 但是题目明确说明是“排序数组”,所以使用二分查找的方法分别找出给定数字 的开始和结束位置,最坏情况下时间复杂度为O(logn)。×/ /************************************************************************/ //函数功能:返回最后一个等于x的位置 int getUpper(int arr[], int length, int x) { int low = 0; int high = length - 1; int mid = 0; while (low <= high) { mid = (low + high) / 2; if(arr[mid] <= x) //向后查找 low = mid + 1; else high = mid - 1; } return high; } //函数功能:返回第一个等于x的位置 int getLower(int arr[], int length, int x) { int low = 0; int high = length - 1; int mid = 0; while (low <= high) { mid = (low + high) / 2; if(arr[mid] >= x) //向前查找 high = mid - 1; else low = mid + 1; } return low; } //函数功能:返回x的次数 int GetTimes(int arr[], int length, int x) { int low = getLower(arr, length, x); int high = getUpper(arr, length, x); return (high - low + 1); } int main() { int arr[] = {1, 2, 2, 2, 3}; cout<<GetTimes(arr, sizeof(arr)/sizeof(arr[0]), 2)<<endl;; }
[b]11、平面上N个点,每两个点都确定一条直线,
求出斜率最大的那条直线所通过的两个点(斜率不存在的情况不考虑)。时间效率越高越好。[/b]
不会!
[b]12、一个整数数列,元素取值可能是0~65535中的任意一个数,相同数值不会重复出现。0是例外,可以反复出现。
请设计一个算法,当你从该数列中随意选取5个数值,判断这5个数值是否连续相邻。
注意:
- 5个数值允许是乱序的。比如: 8 7 5 0 6
- 0可以通配任意数值。比如:8 7 5 0 6 中的0可以通配成9或者4
- 0可以多次出现。
- 复杂度如果是O(n2)则不得分。[/b]
/************************************************************************/ /* 算法思想: 1、找到非零最大值a,找到非零最小值b O(1) 2,计算s=a-b O(1) 3, s>4 则不连续相邻, s<=4 连续相邻 O(1) 代价为O(1) */ /************************************************************************/
13、设计一个算法,找出二叉树上任意两个结点的最近共同父结点。
复杂度如果是O(n2)则不得分。
#include "stdafx.h" #include <iostream> #include <vector> #include <deque> #include <iterator> using namespace std; struct TNode { int element; TNode* left; TNode* right; TNode(int ele = 0, TNode* l = NULL, TNode* t= NULL) :element(ele), left(l), right(t){} }; /************************************************************************/ /*函数功能:将一个有序整数数组放到二叉树中 */ /************************************************************************/ TNode* ConvertArrayToBinaryTree(int arr[], int current, int legth) { TNode *root = NULL; if (current < legth) { root = new TNode(arr[current]); if(2*current + 1 < legth) root->left = ConvertArrayToBinaryTree(arr, 2*current + 1, legth); if(2*current + 2 < legth) root->right = ConvertArrayToBinaryTree(arr, 2*current + 2, legth); } return root; } /************************************************************************/ /*函数功能:输出根节点到给定节点pNode的路径 */ /************************************************************************/ void PrintPath(TNode* root, vector<int> vec, TNode *pNode) { if(root == NULL) return; TNode* temp = root; vec.push_back(temp->element); if(temp == pNode) { for(size_t i = 0; i < vec.size(); ++i) cout<<vec.at(i)<<" "; cout<<endl; return; } else { PrintPath(root->left, vec, pNode); PrintPath(root->right, vec, pNode); } } /************************************************************************/ /*函数功能:获取根节点到给定节点pNode的路径 */ /************************************************************************/ void GetPath(TNode* root, vector<int> vec, TNode *pNode, vector<int>& path) { if(root == NULL) return; TNode* temp = root; vec.push_back(temp->element); if(temp == pNode) { for (size_t i = 0; i < vec.size(); ++i) path.push_back(vec.at(i)); return; } else { GetPath(root->left, vec, pNode, path); GetPath(root->right, vec, pNode, path); } } /************************************************************************/ /* 函数功能:出二叉树上任意两个结点的最近共同父结点 */ /************************************************************************/ int GetCommonParentNode(TNode* root, TNode *node1, TNode* node2) { vector<int> path1, path2, path; GetPath(root, path, node1, path1); GetPath(root, path, node2, path2); //找第一个不相同的节点 size_t index1 = 0; size_t index2 = 0; while ((index2 < path2.size()) && (index1 < path1.size())) { if(path1.at(index1) != path2.at(index2)) break; index2++; index1++; } return path1[index1 - 1]; } int main() { int arr[10]; for (int i=0; i<10; i++) arr[i] = i+1; TNode *root = ConvertArrayToBinaryTree(arr, 0, sizeof(arr)/sizeof(arr[0])); TNode *pNode = root->left->left->right; vector<int> vec; PrintPath(root, vec, pNode); TNode *node1 = root->left->left->left; TNode *node2 = root->left->right; int res = GetCommonParentNode(root, node1, node2); cout<<res<<endl; }
14、一棵排序二叉树,令 f=(最大值+最小值)/2,
设计一个算法,找出距离f值最近、大于f值的结点。
复杂度如果是O(n2)则不得分。
[b]15、一个整数数列,元素取值可能是1~N(N是一个较大的正整数)中的任意一个数,相同数值不会重复出现。
设计一个算法,找出数列中符合条件的数对的个数,满足数对中两数的和等于N+1。
复杂度最好是O(n),如果是O(n2)则不得分.[/b]
#include <iostream> #include <cstdlib> using namespace std; /* 先排序,复杂度O(nlgn),然后用两个指示器(front和back)分别指向第一个和最后一个元素, 如果A[front]+A[back]>N+1,则back--; 如果A[front]+A[back]=N+1,则计数器加1,back--,同时front++; 如果A[front]+A[back] <N+1,则front++; 重复上述步骤,O(n)时间找到所有数对,总体复杂度为O(nlgn) */ //比较函数 int cmp(const void *a, const void *b) { return *(int *)a - *(int *)b; } int GetCount(int arr[], int length) { qsort(arr, length, sizeof(int), cmp); int count = 0; int low = 0; int high = length - 1; int N = arr[high]; while(low <= high) { if(arr[low] + arr[high] < N+1) low++; else if (arr[low] + arr[high] > N+1) high--; else { count++; cout<<arr[low]<<" "<<arr[high]<<endl; low++; high--; } } return count; } int main() { int arr[] = {4, 5, 7, 8, 9, 1, 10, 13, 16}; int length = sizeof(arr) / sizeof(arr[0]); int num = GetCount(arr, length); cout<<"个数为: "<<num<<endl; }
谷歌八道面试题
16、正整数序列Q中的每个元素都至少能被正整数a和b中的一个整除,现给定a和b,需要计算出Q中的前几项,例如,当a=3,b=5,N=6时,序列为3,5,6,9,10,12
(1)、设计一个函数void generate(int a,int b,int N ,int * Q)计算Q的前几项
(2)、设计测试数据来验证函数程序在各种输入下的正确性。
#include <iostream> #include <iterator> #include <cassert> using namespace std; void generate(int a, int b, int N, int * Q) { int num = 0; //计数 int index = 1; while (num < N) { if ((index%a == 0) || ( index%b == 0)) //若index满足条件。放到数组Q { Q[num++] = index; } index++; } } int main() { int N = 6; int *arr = new int ; generate(3, 5, 6, arr); copy(arr, arr+N, ostream_iterator<int>(cout, " ")); cout<<endl; }
17、有一个由大小写组成的字符串,现在需要对他进行修改,将其中的所有小写字母排在答谢字母的前面(大写或小写字母之间不要求保持原来次序),如有可能尽量选择时间和空间效率高的算法 c语言函数原型void proc(char *str) 也可以采用你自己熟悉的语言
#include <iostream> #include <iterator> #include <cassert> using namespace std; void proc(char *str) { assert(str != NULL); int length = strlen(str); char *begin = str; char *end = str + length - 1; while(begin < end) { while (islower(*begin)) begin++; while (isupper(*end)) end--; char temp = *begin; *begin = *end; *end = temp; begin++; end--; } } int main() { char str[] = "aDsfGGrr"; proc(str); cout<<str<<endl; }
18、如何随机选取1000个关键字
给定一个数据流,其中包含无穷尽的搜索关键字(比如,人们在谷歌搜索时不断输入的关键字)。如何才能从这个无穷尽的流中随机的选取1000个关键字?
定义长度为1000的数组。
对于数据流中的前1000个关键字,显然都要放到数组中。
对于数据流中的的第n(n>1000)个关键字,我们知道这个关键字被随机选中的概率为 1000/n。所以我们以 1000/n 的概率用这个关键 字去替换数组中的随机一个。这样就可以保证所有关键字都以 1000/n的概率被选中。
对于后面的关键字都进行这样的处理,这样我们就可以保证数组中总是保存着1000个随机关键字。
19、判断一个自然数是否是某个数的平方
说明:当然不能使用开方运算。
假设待判断的数字是
N。
方法1:
遍历从1到N的数字,求取平方并和N进行比较。
如果平方小于N,则继续遍历;如果等于N,则成功退出;如果大于N,则失败退出。
复杂度为O(n^0.5)。
方法2:
使用二分查找法,对1到N之间的数字进行判断。
复杂度为O(log
n)。
方法3:
由于
(n+1)^2
=n^2 + 2n + 1,
= ...
= 1 + (2*1 + 1)
+ (2*2 + 1) + ... + (2*n + 1)
注意到这些项构成了等差数列(每项之间相差2)。
所以我们可以比较 N-1, N - 1
- 3, N - 1 - 3 - 5 ... 和0的关系。
如果大于0,则继续减;如果等于0,则成功退出;如果小于
0,则失败退出。
复杂度为O(n^0.5)。不过方法3中利用加减法替换掉了方法1中的乘法,所以速度会更快些。
21、1024! 末尾有多少个0?
末尾0的个数取决于乘法中因子2和5的个数。显然乘法中因子2的个数大于5的个数,所以我们只需统计因子5的个数。
是5的倍数的数有:
1024 / 5 = 204个
是25的倍数的数有:1024 / 25 = 40个
是125的倍数的数有:1024 / 125 =
8个
是625的倍数的数有:1024 / 625 = 1个
所以1024! 中总共有204+40+8+1=253个因子5。
也就是说1024!
末尾有253个0。
23、Google2009华南地区笔试题
给定一个集合A=[0,1,3,8](该集合中的元素都是在0,9之间的数字,但未必全部包含),
指定任意一个正整数K,请用A中的元素组成一个大于K的最小正整数。
比如,A=[1,0] K=21 那么输出结构应该为100。
这个问题,应该逼近法
数组 数组biaozhi[0..9] biaozhi[i]=true 则表示i包含在集合中,0<=i<=9;
从整数k的高位往底位判断
设k当前位的数值为i,
if biaozhi[i]=true
{
进行下一位判断;
}
else //biaozhi[i]=false
{
当集合中有比i大的值记为m,则 把k的当前位用m代替,从k位下一位往个位用集合中最小值填充
当集合中没有比i大的值,则从k的上1位回溯
}
// Google.cpp : Defines the entry point for the console application. // #include "stdafx.h" #include <iostream> #include <set> #include <stack> #include <list> using namespace std; int GetMinK(set<int> inputSet, int K) { //求整数K的位数,并将每一位存储到stack中 int n = 0; stack<int> s; while (K != 0) { n++; s.push(K%10); K /= 10; } list<int> result; for (int i=0; i<n; i++) { while (!s.empty() && inputSet.find(s.top()) != inputSet.end()) //集合中存在整数第i位(高位为第0位)的元素值 { result.push_back(s.top()); s.pop(); } if (s.empty() == true) //若各位都在集合inputSet中 { set<int>::iterator iter; while (!result.empty()) { iter = inputSet.upper_bound(result.back()); while (!result.empty() && iter == inputSet.end()) { result.pop_back(); iter = inputSet.upper_bound(result.back()); } if(!result.empty()) { result.pop_back(); result.push_back(*iter); for (int j= result.size(); j<n; j++) result.push_back(*inputSet.begin()); break; } if(result.empty()) { iter = inputSet.upper_bound(0); result.push_back(*iter); for(int j=0; j<n; j++) result.push_back(*inputSet.begin()); break; } } } else { if (inputSet.find(s.top()) == inputSet.end()) //集合中不存在整数第i位(高位为第0位)的元素值 { set<int>::iterator iter = inputSet.lower_bound(s.top()); if (iter != inputSet.end()) //集合中存在比整数第i位(高位为第0位)大的元素值 { result.push_back(*iter); for (int j=i+1; j<n; j++) result.push_back(*inputSet.begin()); break; } if (iter == inputSet.end()) //集合中不存在比整数第i位(高位为第0位)大的元素值 { if(result.empty() == true) //若第一位不存在集合中 { iter = inputSet.upper_bound(0); result.push_back(*iter); for(int j=0; j<n; j++) result.push_back(*inputSet.begin()); break; } else { while(!result.empty()) //进行回退 { iter = inputSet.upper_bound(result.back()); if(iter == inputSet.end()) { result.pop_back(); i--; } else { result.pop_back(); result.push_back(*iter); for (int j=i+1; j<n; j++) result.push_back(*inputSet.begin()); break; } } break; } } } } } if (s.empty() == true) { } int res = 0; while (!result.empty()) { res = res * 10 + result.front(); result.pop_front(); } return res; } int _tmain(int argc, _TCHAR* argv[]) { set<int> s; s.insert(1); s.insert(0); int res = GetMinK(s, 21); cout<<res<<endl; return 0; }
26、有一根27厘米的细木杆,在第3厘米、7厘米、11厘米、17厘米、23厘米这五个位置上各有一只蚂蚁。
木杆很细,不能同时通过一只蚂蚁。开始时,蚂蚁的头朝左还是朝右是任意的,它们只会朝前走或调头,但不会后退。
当任意两只蚂蚁碰头时,两只蚂蚁会同时调头朝反方向走。假设蚂蚁们每秒钟可以走一厘米的距离。
编写程序,求所有蚂蚁都离开木杆的最小时间和最大时间。
解析:可以采用鬼魂算法,鬼魂的意思就是“传递能量”,“穿透”。
首先判断最靠近中间点的蚂蚁,用程序很好判断,就是11厘米处的蚂蚁,其实这个蚂蚁,最快的时间就是最小时间。
其次判断最靠外面的蚂蚁,用程序很好判断,就是3厘米处的蚂蚁,其实这个蚂蚁,最慢的时间就是最大时间。
其他蚂蚁无视就可以了。
答案:最大时间是27-3=24,最小时间是11-0=11。
雅虎三道面试题
34、编程实现:把十进制数(long型)分别以二进制和十六进制形式输出,不能使用printf系列
#include "stdafx.h" #include <iostream> using namespace std; /************************************************************************/ /* 函数功能:把十进制数(long型)分别以二进制 */ /************************************************************************/ void LongTo2(long n) { if(0 == n) return; else { LongTo2(n/2); cout<<n%2; } } /************************************************************************/ /* 函数功能:把十进制数(long型)分别以16进制 */ /************************************************************************/ const char arr[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; void LongTo16(long n) { if(0 == n) return; else { LongTo16(n/16); cout<<arr[n%16]; } } int main() { LongTo2(56); cout<<endl; LongTo16(256); cout<<endl; }
35、编程实现:找出两个字符串中最大公共子字符串,如"abccade","dgcadde"的最大子串为"cad"
#include "stdafx.h" #include <iostream> using namespace std; /************************************************************************/ /* 函数功能:找出两个字符串中最大公共子字符串,如"abccade","dgcadde"的最大 子串为"cad"*/ /************************************************************************/ void GetMaxCommonSubString(const char *str1, const char *str2, char* &subString) { int length1 = strlen(str1); int length2 = strlen(str2); int max = 0; //存储最大值 int start = 0;//最大公共字串在str1中开始的位置 for (int i=0; i<length1; i++) { for (int j=0; j<length2; j++) { int temp1 = i; //每次查找的开始位置 int temp2 = j; int number = 0; //统计个数 while ((str1[temp1] == str2[temp2]) && (temp2 < length2) && (temp1 < length1)) //开始找公共字串 { number++; temp1++; temp2++; } if (number > max) //判断是否是最大的 { max = number; start = i; } } } strncpy(subString, str1 + start, max); //拷贝到subString中 } int main() { const char* str1 = "abccade"; const char* str2 = "dgcadde"; int length = (strlen(str1) <= strlen(str2) ? strlen(str1) : strlen(str2)); char *str = new char[length]; memset(str, '/0', length+1); GetMaxCommonSubString(str1, str2, str); cout<<str<<endl; }
38、顺时针打印矩阵
题目:输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字。
例如:如果输入如下矩阵:
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。
分析:包括Autodesk、EMC在内的多家公司在面试或者笔试里采用过这道题。
#include <iostream> using namespace std; /************************************************************************/ /*函数功能:顺时针打印矩阵,m表示矩阵的行,n表示矩阵的列 */ /************************************************************************/ void PrintMatrix(int **matrix, int m, int n) { int numbers = m * n; int num = 0; for (int i=0; i<=m/2; i++) { for (int j=i; j<n-i; j++, num++) printf("%d ", matrix[i][j]); //打印上边的行 for (int k=i+1; k<m-i-1; k++, num++) { if(num >= numbers) break; printf("%d ", matrix[k][n-i-1]); //打印右边的列 } for (int j=n-i-1; j>=i; j--, num++) { if(num >= numbers) break; printf("%d ", matrix[m-i-1][j]); //打印下边的行 } for(int k= m-i-2; k>i; k--, num++) { if(num > numbers) break; printf("%d ", matrix[k][i]); //打印左边的行 } } printf("/n"); } int main() { int **matrix; const int M = 5; const int N = 4; matrix = new int*[M]; for (int i=0; i<M; i++) matrix[i] = new int ; int k = 1; for(int i=0; i<M; i++) for(int j=0; j<N; j++) matrix[i][j] = k++; PrintMatrix(matrix, M, N); }
39、对称子字符串的最大长度
题目:输入一个字符串,输出该字符串中对称的子字符串的最大长度。
比如输入字符串“google”,由于该字符串里最长的对称子字符串是“goog”,因此输出4。
分析:可能很多人都写过判断一个字符串是不是对称的函数,这个题目可以看成是该函数的加强版。
#include <iostream> #include <cassert> using namespace std; /************************************************************************/ /* 函数功能:判断low和high之间的字符串是否是对称的 */ /************************************************************************/ bool isDuiChen(const char* low, const char* high) { while (low < high) { if (*low == *high) { low++; high--; } else return false; } return true; } /************************************************************************/ /* 函数功能:求字符串str中对称字符串的最大长度,result存放该字串 */ /************************************************************************/ int getMaxLength(const char* str, char* result) { assert(str != NULL); int len = strlen(str); int max = 0; int start = 0; for (int i=0; i<len-1; i++) { for (int j= i+1; j<len; j++) { if (isDuiChen(str+i, str+j)) { if((j - i + 1) > max) { max = j - i + 1; start = i; } } } } strncpy(result, str + start, max); return max; } int main() { const char *str = "googleyanggnay"; int len = strlen(str); char *result = new char[len + 1]; memset(result, '/0', len + 1); int max = getMaxLength(str, result); printf("最大的对称字串为:%s, 长度为: %d/n", result, max); }
40、用1、2、2、3、4、5这六个数字,写一个main函数,打印出所有不同的排列,
如:512234、412345等,要求:"4"不能在第三位,"3"与"5"不能相连.
#include <iostream> using namespace std; char result[7] = {'/0'}; void PrintSpecialPaiLie(char *str, int curPos, int n) { if (curPos == n) { if ((str[3] != '4') && (strstr(str, "35") == NULL)) //对输出进行过滤 printf("%s/n", str); } else { for (int i = curPos; i<n; i++) { swap(str[0], str[i]); PrintSpecialPaiLie(str, curPos + 1, n); swap(str[0], str[i]); } } } int main() { char str[] = "122345"; int N = sizeof(str) / sizeof(char) - 1; //减1是因为str中含有字符'/0'; PrintSpecialPaiLie(str, 0, N); }
48、找出数组中唯一的重复元素
1-1000放在含有1001个元素的数组中,只有唯一的一个元素值重复,其它均只出现一次.
每个数组元素只能访问一次,设计一个算法,将它找出来;不用辅助存储空间,
能否设计一个算法实现?
#include <iostream> using namespace std; /* 算法思想:统计数组的全部元素之和sum,然后根据等差数列求出1到upperBound这些 数字的和n,然后重复的数字为sum-n。 */ int findDuplicateElement(int arr[], int upperBound) { int sum = 0; for(int i = 0; i < upperBound + 1 ; i++) sum += arr[i]; return sum - (1 + upperBound) * upperBound / 2; } int main() { const int NUMBERS = 1001; int arr[NUMBERS]; for(int i = 0; i < NUMBERS; ++i) arr[i] = i + 1; arr[NUMBERS - 1] = 520; //设定重复元素 int result = findDuplicateElement(arr, NUMBERS - 1); cout<<"重复元素为: "<<result<<endl; }
50、一道SPSS笔试题求解
题目:输入四个点的坐标,求证四个点是不是一个矩形
关键点:
1.相邻两边斜率之积等于-1,
2.矩形边与坐标系平行的情况下,斜率无穷大不能用积判断。
3.输入四点可能不按顺序,需要对四点排序。
// ww.cpp : Defines the entry point for the console application. // #include "stdafx.h" #include <iostream> #include <algorithm> using namespace std; //向量的类 struct Vector { int x; int y; Vector(){} Vector(int _x, int _y) { x = _x; y = _y; } bool operator* (const Vector& other) //定义两个向量相乘 { if((x * other.x + y * other.y) == 0) return true; return false; } }; //点的类 struct Point { int x; int y; Point(){} Point(int _x, int _y) { x = _x; y = _y; } Vector operator- (const Point& other) //定义两个点相减 { return Vector(other.x - x, other.y - y); } }; bool cmp(const Point& lv, const Point& rv) { return ((lv.x < rv.x) || (lv.x == rv.x && lv.y < rv.y)); } //判断四个点是否构成矩形 bool IsRectangle(Point arr[4]) { sort(arr, arr + 4, cmp); Vector v01 = arr[1] - arr[0]; Vector v03 = arr[2] - arr[0]; if(v03 * v01 == false) return false; Vector v21 = arr[0] - arr[1]; Vector v23 = arr[3] - arr[1]; if(v21 * v23 == false) return false; Vector v32 = arr[0] - arr[2]; Vector v34 = arr[3] - arr[2]; if(v32 * v34 == false) return false; Vector v41 = arr[1] - arr[3]; Vector v43 = arr[2] - arr[3]; if (v41 * v43 == false) return false; return true; } int _tmain(int argc, _TCHAR* argv[]) { Point arr[4] = {Point(1, 0), Point(0, 6), Point(-1, 0), Point(0, -1)}; if (IsRectangle(arr)) cout<<"是矩形"<<endl; else cout<<"不是矩形"<<endl; return 0; }
取值为【1,n-1】含n个元素的整数数组至少存在一个重复数,O(n)时间内找出其中任意一个重复数
// ww.cpp : Defines the entry point for the console application. // #include "stdafx.h" #include <iostream> #include <algorithm> using namespace std; /* 取值为【1,n-1】含n个元素的整数数组至少存在一个重复数,O(n)时间内找出其中任意一个重复数 */ /* 思路分析: 1、如果数组中有且仅有一个重复数,可以简单的通过S(A)=(n-1)*n/2得到重复数,其中S(A)表示对数组A求和 2、仿链表中找环的思路解决至少含一个重复数的问题 */ int GetRepeatNumber(int arr[], int n) { int x = 0, y = 0; do { x = arr[arr[x]]; y = arr[y]; } while (x != y); return arr[x]; } int main() { int arr[10] = {1, 4, 3, 5, 4, 5, 5, 4, 8, 9}; cout<<"重复的数字为:"<<GetRepeatNumber(arr, 10)<<endl; }
相关文章推荐
- 微软、谷歌、百度等公司经典面试100题[第1-60题]——自己的实现[转]
- 全新整理:微软、谷歌、百度等公司经典面试100题[第1-60题]
- 微软、谷歌、百度等公司经典面试100题[第1-60题]及解答
- 全新整理:微软、谷歌、百度等公司经典面试100题[第1-60题]
- 全新整理:微软、谷歌、百度等公司经典面试100题[第1-60题]
- 全新整理:微软、谷歌、百度等公司经典面试100题[第1-60题]
- 全新整理:微软、谷歌、百度等公司经典面试100题[第1-60题]
- 微软、谷歌、百度等公司经典面试100题[第1-60题]
- 全新整理:微软、谷歌、百度等公司经典面试100题[第1-60题]
- 微软、谷歌、百度等公司经典面试100题[第1-60题]
- 全新整理:微软、谷歌、百度等公司经典面试100题[第1-60题]
- 微软、谷歌、百度等公司经典面试100题[第101-160题]
- 全新整理:微软、谷歌、百度等公司经典面试100题[第101-160题]
- 全新整理:微软、谷歌、百度等公司经典面试100题[第101-160题]
- 全新整理:微软、谷歌、百度等公司经典面试100题[第101-160题]
- 全新整理:微软、谷歌、百度等公司经典面试100题[第101-160题]
- 微软、谷歌、百度等公司经典面试100题
- 微软、谷歌、百度等公司经典面试100题
- 全新整理:微软、谷歌、百度等公司经典面试100题[第101-160题]
- 全新整理:微软、谷歌、百度等公司经典面试100题[第101-160题]