c++数据结构例题
来源:互联网 发布:监控数据恢复 编辑:程序博客网 时间:2024/06/01 11:53
由于二面boss时被boss的两道算法题难住了(ps:本人应聘的是ios开发岗位,oc语言),没什么好说的了,只能怪自己太年轻了。回来后开始脑补各公司的数据结构与算法面试题。
先从已有答案的面试题开始模仿及学习c++语言。点击打开链接 点击打开链接
再从没有答案的面试题开始自己写(遇事不懂问度娘~)。点击打开链接
环境:mac,xcode或者终端;
语言:c++;
潇洒的分割线~哗——————————————————————————————————————————————————
例1:求一个数组的最长递减子序列比如{9,4,3,2,5,4,3,2}的最长递减子序列为{9,5,4,3,2}
算法描述:
1. 对原序列进行递减排序(选择快速排序法);
2. 删掉重复数字;
3. 得到子序列。
c++代码:
#include <iostream>using namespace std;#define MAX_SIZE 9void FastSort(int a[],int left,int right){ if (left < right) { int i = left,j = right; int temp = a[left]; while (i<j) { while (j>i&&a[j]>temp) { j--; } a[i]=a[j]; while (i<j&&a[i]<=temp) { i++; } a[j]=a[i]; } a[i]=temp; FastSort(a, i+1, right); FastSort(a, left, i-1); }}void getChildSet(int a[],int p[],int n,int& length){ for (int i=0; i<n; i++) { if (a[i]!=a[i+1]) { p[length]=a[i]; length++; } }}int main(int argc, const char * argv[]) { int a[MAX_SIZE] = {2,3,4,1,5,6,9,7,6}; for (int i= 0; i<MAX_SIZE; i++) { cout<<a[i]; } cout<<":"; FastSort(a, 0, MAX_SIZE-1); int p[MAX_SIZE]; int length = 0; getChildSet(a,p,MAX_SIZE,length); for (int i=0; i<length; i++) { cout<<p[i]; } cout<<"\n"; return 0;}运行结果:234156976:12345679
收获:序列的快速排序,题目的改动,正序排列,删除重复项。
例2:将一整数序列逆序(要求递归实现)
算法描述:
1当满足first<last时直接交换序列首位和末尾位元素;
2.递归调用(注意递归退出条件:必须是变量first大于或等于last)
c++代码:
#include <iostream>using namespace std;#define MAX_SIZE 9void FastSort(int a[],int left,int right){ if (left >= right) return; int temp = a[left]; a[left] = a[right]; a[right] = temp; FastSort(a, left+1, right-1);}int main(int argc, const char * argv[]) { int a[MAX_SIZE] = {1,2,3,4,5,6,7,8,9}; for (int i=0; i<MAX_SIZE; i++) { cout << a[i]; } cout << ":"; FastSort(a, 0, MAX_SIZE-1); for (int i=0; i<MAX_SIZE; i++) { cout << a[i]; } cout << "\n"; return 0;}
收获:关键在于数组的长度奇偶性。递归思想
例3:将一整数逆序后放入一数组中(要求递归实现)如:12345逆置后为54321
算法描述:
1分割出整数的每一个位,方法n%10;
2.每一次分割都是得到整数最后一个位,数组索引值要从第0开始
c++代码:
#include <iostream>using namespace std;void FastSort(int a[],int n,int& length){ if (n == 0) return; a[length] = n%10; length++; FastSort(a, n/10,length);}int main(int argc, const char * argv[]) { int n = 1234567890; int length = 0; cout << n <<":"; int a[100]; FastSort(a, n, length); for (int i=0; i<length; i++) { cout << a[i]; } cout << "\n"; return 0;}
运行结果:1234567890:0987654321
收获:/10与%10的灵活运用。
例4:递归实现回文判断(如:abcdedbca就是回文,判断一个面试者对递归理解的简单程序)
算法描述:
与求一个序列的转置类似。
c++代码:
#include <iostream>using namespace std;bool FastSort(char* str,int left,int right){ if (left > right) { return false; } if (left == right) { return true; } if (str[left] != str[right]) { return false; }else return(FastSort(str,left+1,right-1)); }int main(int argc, const char * argv[]) { char* str = "abcdedcba"; cout<<str<<":"; int count = strlen(str); if(FastSort(str, 0, count-1)) cout<<"yes"<<endl; else cout<<"no"<<endl; return 0;}
运行结果:abcdedcba:yes ; abcddcba:no ;
收获:字符串也可像数组那样直接str[index]取。注意字符串最后一个是“\0”!自定义函数从void扩展到bool,注意return。
例5:分解成质因数(如435234=251*17*17*3*2)
算法描述:
1 寻找一个整数的质因数方法从2开始遍历,依次查找
c++代码:
#include <iostream>using namespace std;void func(int n,int i){ while (n%i !=0) { i++; if (i*i > n) { i = n; break; } } if (i != n) { func(n/i, i); cout<<"*"<<i; }else cout<<n;}int main(int argc, const char * argv[]) { int n = 435234; cout<<n<<"="; func(n, 2); cout<<"\n"; return 0;}
运行结果:435234=251*17*17*3*2
收获:分解质因数,简单而有深度的题!改动的地方在于i*i>n,判断一个数是不是质数,不需要从2到n,只需从2到根号n!
例6:寻找迷宫的一条出路,1代表障碍,0代表通。
算法描述:
这里可以使用几种方法,我知道的有使用《数据结构》上“穷举求解”的方法,还有就是使用遗传算法寻找最优路径。这里我先简单描述下“穷举求解”,然后再做遗传算法的方式。
1 问题中要涉及走过路径的回溯,因为栈是先进后出,所以利于回溯,选择栈来存储走过路径
2 每一步有四个方向可以走,每到一步依次判断每一个方向,只要判断到某个方向可走就选择这个方向前进。
3 当所有方向都不能行进时,回溯到上一步,此时判断栈顶指针是否为-1,如果是,返回false失败,否则递归调用继续寻找。
c++代码:
#include <iostream>using namespace std;#define MAX_SIZE 10int maze[MAX_SIZE][MAX_SIZE]={ {1,1,1,1,1,1,1,1,1,1}, {1,0,0,1,0,1,0,1,0,1}, {1,0,0,1,0,0,0,1,0,1}, {1,0,0,0,0,1,1,0,0,1}, {1,0,1,1,1,0,0,0,0,1}, {1,0,0,0,1,0,0,0,0,1}, {1,0,1,0,0,0,1,0,0,1}, {1,0,1,1,1,0,1,1,0,1}, {1,1,0,0,0,0,0,0,0,1}, {1,1,1,1,1,1,1,1,1,1}};typedef struct{ int x; int y;}POINT;typedef struct{ POINT data[MAX_SIZE * MAX_SIZE]; int top;}STACK;void findWay(int maze[][MAX_SIZE],POINT start,POINT end,STACK& way){ POINT step; step.x = start.x; step.y = start.y; if (way.data[way.top].x != end.x || way.data[way.top].y != end.y) { //left if (!maze[step.y][step.x+1]) { maze[step.y][step.x] = 1; way.top++; way.data[way.top] = step; step.x++; findWay(maze, step, end, way); } //down else if (!maze[step.y+1][step.x]) { maze[step.y][step.x] = 1; way.top++; way.data[way.top] = step; step.y++; findWay(maze, step, end, way); } //right else if (!maze[step.y][step.x-1]) { maze[step.y][step.x] = 1; way.top++; way.data[way.top] = step; step.x--; findWay(maze, step, end, way); } //up else if (!maze[step.y-1][step.x]) { maze[step.y][step.x] = 1; way.top++; way.data[way.top] = step; step.y--; findWay(maze, step, end, way); } else{ if (way.top == -1) return; maze[step.y][step.x] = 1; way.top--; step = way.data[way.top]; findWay(maze, step, end, way); } }}int main(int argc, const char * argv[]) { POINT start,end; start.x = 1; start.y = 1; end.x = 8; end.y = 8; STACK way; way.top = -1; findWay(maze, start, end, way); if (way.top != -1) { cout<<"Have fount the way!"<<endl; for (int i = 0; i < way.top; i++) { cout<<"("<<way.data[i].x<<" , "<<way.data[i].y<<"),"; } } else cout<<"Don't find the way"<<endl; return 0;}
运行结果:Have fount the way!(1 , 1),(2 , 1),(2 , 2),(2 , 3),(2 , 3),(1 , 3),(1 , 4),(1 , 5),(2 , 5),(3 , 5),(3 , 6),(4 , 6),(5 , 6),(5 , 7),(5 , 8),(6 , 8),(7 , 8)
收获:矩阵里的坐标跟眼睛看到的坐标反一下就好。穷举法。一个点有路就走,前脚走后脚封路,没路可走退回一步封路。用遗传算法求最优路径,待定!学过oc,对于.的用法、对象、属性还是理得清的,比较好理解。
80题-例3:求子数组的最大和
题目:
输入一个整形数组,数组里有正数也有负数。
数组中连续的一个或多个整数组成一个子数组,每个子数组都有一个和。
求所有子数组的和的最大值。要求时间复杂度为O(n)。
例如输入的数组为1, -2, 3, 10, -4, 7, 2, -5,和最大的子数组为3, 10, -4, 7, 2,
因此输出为该子数组的和18。
c++代码:
#include <iostream>using namespace std;int func(int a[],int length){ int smin = 0; int smax = 0; int sminInmax = 0; int sum = 0; for (int i=0; i < length; i++) { sum += a[i]; if (sum > smax) { smax = sum; smin = sminInmax; } if (sum < smin) { sminInmax = sum; } } return smax-smin;}int main(int argc, const char * argv[]) { //int a[8] = {1,-2,3,10,-4,7,2,-5}; int a[8] = {-1,2,3,4,5,6,-10,11}; int result = func(a, 8); cout<<result; return 0;}
运行结果:21
收获:这题关键在于时间复杂度要求,所以就遍历一次。思路,连续n-m个数求和=1到n个求和-1到m个求和,求最大值=1到n求和的最大值-最小值。由于可能最小值的数组长度大于最大值的数组长度,这样相减结果不是我们要的,于是引入延迟最小值!当最大值更新了,再去刷新最小值。遗憾的是主要还是用到数学思想,没用到计算机思想(毕竟本人曾是数学竞赛的0.0)
补充:计算机思想。f(n-1)表示前面已找到的最大值,若f(n-1)<0,则f(n)=a[n];否则f(n)=f(n-1)+a[n];
c++代码(终端):
#include <iostream>#include <vector>using namespace std;int main(){vector<int> a;int temp;while(cin >> temp){a.push_back(temp);} if(a.size() == 0){return -1;}int last = a[0];int max = a[0];for(int i = 1; i < a.size(); i++){if(last > 0){last += a[i];}else {last = a[i];}if(max < last){max = last;}}cout << max << endl;return 0;}
题80-例5:查找最小的k个元素
题目:输入n个整数,输出其中最小的k个。
例如输入1,2,3,4,5,6,7和8这8个数字,则最小的4个数字为1,2,3和4。
c++代码:
#include <iostream>using namespace std;#define n 8#define k 4void func(int a[],int left,int right){ int i = left, j = right; int temp = a[left]; if (left<right) { while (i<j) { while (i<j&&a[j]>temp) { j--; } a[i] = a[j]; while (i<j&&a[i]<=temp) { i++; } a[j]=a[i]; } a[i]=temp; func(a, left, i-1); func(a, i+1, right); }}int main(int argc, const char * argv[]) { //int a[n] = {1,2,3,4,5,6,7,8}; int a[n]; for (int i=0; i<n; i++) { cout<<"a["<<i<<"]="; cin>>a[i]; } func(a, 0, n-1); for (int i = 0; i<k; i++) { cout<<a[i]<<" "; } cout<<endl; return 0;}
运行结果:1,2,3,4
收获:数组的快速排列又巩固一次。
题80-例10:翻转句子中单词的顺序。
题目:输入一个英文句子,翻转句子中单词的顺序,但单词内字符的顺序不变。
句子中单词以空格符隔开。为简单起见,标点符号和普通字母一样处理。
例如输入“I am a student.”,则输出“student. a am I”。
c++代码:
#include <iostream>using namespace std;void func(string str,string comparestr,int right){ int i = right-1; while (i) { if (str.compare(i, 1, comparestr) == 0) { for (int j = i+1; j < right ; j++) { cout<<str[j]; } cout<<comparestr; func(str,comparestr,i); break; } i--; } if (i == 0) { for (int j = i; j < right ; j++) { cout<<str[j]; } }}int main(int argc, const char * argv[]) { string str = "I am a student."; string str1 = " "; cout<<str<<":"; func(str,str1,str.length()); cout<<endl; return 0;}
运行结果:I am a student.:student. a am I
收获:string字符串比较。
题80-例12:题目:求1+2+…+n,
要求不能使用乘除法、for、while、if、else、switch、case等关键字以及条件判断语句(A?B:C)。
c++代码:
#include <iostream>using namespace std;#define N 10int func(int n,int &sum){ n && func(n-1, sum); return sum+=n;}int main(int argc, const char * argv[]) { int sum = 0; cout<<func(N, sum); return 0;}
运行结果:55;
收获:这题抄袭网上大牛的,用&&特性跳出循环,膜拜orz!get☑️。
题80-例14:题目:输入一个已经按升序排序过的数组和一个数字,
在数组中查找两个数,使得它们的和正好是输入的那个数字。
要求时间复杂度是O(n)。如果有多对数字的和等于输入的数字,输出任意一对即可。
例如输入数组1、2、4、7、11、15和数字15。由于4+11=15,因此输出4和11。
c++代码:
#include <iostream>using namespace std;#define n 6#define SUM 15void func(int a[],int length,int right){ while (length!=right) { if ((a[length]+a[right])>SUM) { right--; } else if ((a[length]+a[right])<SUM) { length++; } else { cout<<a[length]<<"+"<<a[right]<<"="<<SUM<<endl; break; } } if (length == right) { cout<<"no result"<<endl; }}int main(int argc, const char * argv[]) { int a[n] = {1,2,3,4,11,15}; func(a, 0, n-1); return 0;}运行结果:4+11=15
收获:重要题干“已经正序排列”“两个数”。省了很多事了。头尾两指针,sum大了尾针移,小了头针移。
题80-例18:题目:n个数字(0,1,…,n-1)形成一个圆圈,从数字0开始,
每次从这个圆圈中删除第m个数字(第一个为当前数字本身,第二个为当前数字的下一个数字)。
当一个数字删除后,从被删除数字的下一个继续删除第m个数字。
求出在这个圆圈中剩下的最后一个数字。
c++代码:
#include <iostream>using namespace std;#define N 17#define M 5int LastRemaining_Solution2(int n, unsigned int m){ if(n <= 0 || m < 0) return -1; int lastinteger = 0; for (int i = 2; i <= n; i ++) lastinteger = (lastinteger + m) % i; return lastinteger;}int main(int argc, const char * argv[]) { cout<<LastRemaining_Solution2(N, M); return 0;}
运行结果:10.
收获:约瑟夫环,数学分析一番,递推一番,得出公式:f(n,m)=[f(n-1,m)+m]%n n>1。第一个删除的是M-1.
题80-例19:题目:定义Fibonacci数列如下:
/ 0 n=0
f(n)= 1 n=1
\ f(n-1)+f(n-2) n=2
输入n,用最快的方法求该数列的第n项。
c++代码:
#include <iostream>using namespace std;#define N 6int func(int n){ if (n <= 0) { return 0; } if (n == 1 || n == 2) { return n; } return func(n-1)+func(n-2);}int main(){ cout<<func(N)<<endl; return 0; }
运行结果:13
收获:斐波那契数列。
题80-例20:题目:输入一个表示整数的字符串,把该字符串转换成整数并输出。
例如输入字符串"345",则输出整数345。
c++代码:
#include <iostream>using namespace std;int main(int argc, const char * argv[]) { char* str = "0345"; int length = strlen(str); int sum = 0; for (int i = 0 ; i < length; i++) { sum = sum*10 + str[i]-48; } cout<<sum; return 0;}
运行结果:345
收获:直接通过字符的ASCII码计算。“0”对应48。
题80-例21:2010年中兴面试题
编程求解:
输入两个整数 n 和 m,从数列1,2,3.......n 中 随意取几个数,
使其和等于 m ,要求将其中所有的可能组合列出来.
c++代码:
#include <iostream>using namespace std;#define M 8#define N 20void func(int n, int m,int a[]){ if (m == 0) { for (int i = 1; i < M+1; i++) { if (a[i] == 1) { cout<<i<<" "; } } cout<<endl; } if (n <= 0 || m <= 0) { return; } a[n] = 0; func(n-1, m,a); a[n] = 1; func(n-1, m-n,a); a[n] = 0;}int main(){ int a[M+1]; int m = M; int n = N; if (n > m) { n = m; } if (m > n*n-n+1) { cout<<"Don't find!"<<endl; return 0; } func(n, m,a); return 0; }
运行结果:1 3 4 ,1 2 5 ,3 5 ,2 6 ,1 7 ,8
收获:0/1背包问题。从右往左,没拿标0,f(n-1,m,a[]);拿了标1,f(n-1,m-n,a[])。看m是否为零。
题80-例27:跳台阶问题
题目:一个台阶总共有n级,如果一次可以跳1级,也可以跳2级。
求总共有多少总跳法,并分析算法的时间复杂度。
这道题最近经常出现,包括MicroStrategy等比较重视算法的公司
都曾先后选用过个这道题作为面试题或者笔试题。
c++代码:
#include <iostream>using namespace std;#define N 6int func(int n){ if (n <= 0) { return 0; } if (n == 1 || n == 2) { return n; } return func(n-1)+func(n-2);}int main(){ cout<<func(N)<<endl; return 0; }
运行结果:6
收获:Fibonacci数列。
题80-例28:整数的二进制表示中1的个数
题目:输入一个整数,求该整数的二进制表达中有多少个1。
例如输入10,由于其二进制表示为1010,有两个1,因此输出2。
分析:
这是一道很基本的考查位运算的面试题。
包括微软在内的很多公司都曾采用过这道题。
c++代码:
#include <iostream>using namespace std;#define N 10int func(int n){ if (n == 1) { return 1; } if (n%2) { return func(n/2)+1; } return func(n/2);}int main(){ cout<<func(N)<<endl; return 0; }
运行结果:2
收获:递归,/2%2.
- 北大数据结构经典例题
- c++数据结构例题
- 数据结构(C语言版)陈锐主编第2章例题代码
- 数据结构与C语言实现(七)——树(下):集合与集合例题
- 例题3.1 猜猜数据结构 UVa11995
- C语言例题1:
- C语言例题2:
- C语言例题3:
- C语言例题4:
- C语言例题5:
- C语言例题6:
- C语言例题7:
- C语言例题8:
- C语言例题9:
- C语言例题10:
- C语言例题11:
- C语言例题12:
- C语言例题13:
- 2012 素数判定
- Java设计模式之工厂模式
- android studio 查看 类 接口 定义的方法实现方法 快捷键
- ActionBar
- hdu1002-大数相加
- c++数据结构例题
- ACM--大数阶乘位数--HDOJ 1018--Big Number--水
- ios textfield 长按粘贴复制 中文
- VS2008 影响程序大小和速度的选项
- 对XMl文件的操作
- 定时器
- epoll实现I/O多路复用
- 1107. Social Clusters (30)
- VectorDrawable