【面试题】一个号称BAT算法题
[我也带来一波节奏]既然想reroll码农的这么多,那来做个游戏吧,真实BAT面试
http://bbs.ngacn.cc/read.php?tid=8405951
发这个没有别的意思
有很多转行/自学/经验少的旁友很好奇真正的面试题是什么样子的,也想检验下自己什么水平
正好最近朋友给我看了这个真实的例子,就发来给大家看看
本题不涉及任何特定的算法,数学与专门的理论知识
考察的是基本的逻辑思维,抽象思维,基本的算法分析与动手能力
如图有限状态机
A,B,C三个状态
从左边start进入A开始运行,到达最右边的end状态结束
每个状态节点有若干条边来标识状态转换的路径
每个边上的符号代表一个概率p,表示到达这个节点后有p的概率走这条路线
概率值精确到2位小数
每个状态所有出去的路径概率之和为1
比如a1+a2+a3+a4=1
每到达一个状态后输出该状态的字母
如果到达end则停止输出
那么根据这个规则,可以随机输出一系列字符串,例如:
AABC
ABCCCAABC
等等
问题:
1. 写一个程序实现上述字符串输出
2. 给定一个字符串长度N,写一个函数计算1中的算法最终输出字符串长度为N的概率。
3. 给出2中算法的复杂度,是否有优化方法。
4. 快下班的时候,boss:小李啊,客户突然有个需求,要通过读取配置文件得到状态机信息,改下你的程序以支持用户输入的任意状态机,改完了再走吧,打车公司报销
要求:
手写代码
编码限时15分钟 (只要有核心功能即可,标准库随便用)
复杂度什么的写完代码再慢慢聊
1 // 2 // 有限状态机.cpp 3 // TestAllThings 4 // 5 // Created by 彭威 on 15/7/28. 6 // Copyright © 2015年 NJU. All rights reserved. 7 // 8 /* 9 10 [我也带来一波节奏]既然想reroll码农的这么多,那来做个游戏吧,真实BAT面试(37楼以后各路高玩出现) 11 发这个没有别的意思 12 有很多转行/自学/经验少的旁友很好奇真正的面试题是什么样子的,也想检验下自己什么水平 13 正好最近朋友给我看了这个真实的例子,就发来给大家看看 14 本题不涉及任何特定的算法,数学与专门的理论知识 15 考察的是基本的逻辑思维,抽象思维,基本的算法分析与动手能力 16 17 18 如图有限状态机 19 A,B,C三个状态 20 从左边start进入A开始运行,到达最右边的end状态结束 21 每个状态节点有若干条边来标识状态转换的路径 22 每个边上的符号代表一个概率p,表示到达这个节点后有p的概率走这条路线 23 概率值精确到2位小数 24 每个状态所有出去的路径概率之和为1 25 比如a1+a2+a3+a4=1 26 每到达一个状态后输出该状态的字母 27 如果到达end则停止输出 28 那么根据这个规则,可以随机输出一系列字符串,例如: 29 AABC 30 ABCCCAABC 31 等等 32 33 问题: 34 1. 写一个程序实现上述字符串输出 35 2. 给定一个字符串长度N,写一个函数计算1中的算法最终输出字符串长度为N的概率。 36 3. 给出2中算法的复杂度,是否有优化方法。 37 4. 快下班的时候,boss:小李啊,客户突然有个需求,要通过读取配置文件得到状态机信息,改下你的程序以支持用户输入的任意状态机,改完了再走吧,打车公司报销 38 39 要求: 40 手写代码 41 编码限时15分钟 (只要有核心功能即可,标准库随便用) 42 复杂度什么的写完代码再慢慢聊 43 44 45 46 */ 47 #include <iostream> 48 #include <stdlib.h> 49 #include <vector> 50 #include <string> 51 52 #define Rand ((double)arc4random() / 0x100000000) 53 54 using namespace std; 55 static const int n = 4; 56 static const double p[n][n] = { 57 0.1,0.2,0.3,0.4, 58 0.2,0.3,0.4,0.1, 59 0.3,0.4,0.1,0.2, 60 0 ,0 ,0 ,0 61 }; 62 char print[n] = {'A','B','C','\n'}; 63 class AutoStep { 64 int current; 65 public: 66 AutoStep(int start=0):current(start){}; 67 string start(){ 68 string result; 69 result.push_back(print[current]); 70 while (!isEnd()) { 71 current = makeChoice(); 72 result.push_back(print[current]); 73 } 74 return result; 75 } 76 protected: 77 bool isEnd(){ 78 return (n-1) == current; 79 } 80 int makeChoice(){ 81 vector<double> pro(n); 82 pro[0] = probability(current,0); 83 for (int i = 1; i < n; i++) { 84 pro[i] = pro[i-1] + probability(current,i); 85 } 86 auto iter = lower_bound(pro.begin(), pro.end(), Rand); 87 return (int)(iter - pro.begin()); 88 } 89 double probability(int i,int j){ 90 return p[i][j]; 91 } 92 }; 93 template <typename T> 94 class Matrix { 95 private: 96 T **m; 97 T *m0; 98 unsigned int n; 99 unsigned int K; 100 101 public: 102 Matrix(unsigned int _n,const T *a){ 103 const T *p=a; 104 init(_n); 105 for (int i=0; i<n; i++) 106 for (int j=0; j<n; j++) { 107 m[i][j]=*p++; 108 } 109 110 } 111 Matrix(unsigned int _n){ 112 init(_n); 113 }; 114 void init(unsigned int _n){ 115 n=_n; 116 m = new T*[n]; 117 m0= new T[n*n]; 118 for (int i=0;i<n*n;i++)m0[i]=0; 119 for (int i=0;i<n; i++){ 120 m[i]=&(m0[i*n]); 121 } 122 } 123 Matrix(const Matrix& r){ 124 init(r.n); 125 for (int i=0; i<n; i++) 126 for (int j=0; j<n; j++) { 127 m[i][j]=r.m[i][j]; 128 } 129 } 130 131 Matrix& operator=(const Matrix& r){ 132 for (int i=0; i<n; i++) 133 for (int j=0; j<n; j++) { 134 m[i][j]=r.m[i][j]; 135 } 136 return *this; 137 } 138 Matrix& operator%=(unsigned long long r){ 139 for (int i=0; i<n; i++) 140 for (int j=0; j<n; j++) { 141 m[i][j]%=r; 142 } 143 return *this; 144 } 145 Matrix& operator+=(const Matrix& r){ 146 for (int i=0; i<n; i++) 147 for (int j=0; j<n; j++) { 148 m[i][j]+=r.m[i][j]; 149 150 } 151 return *this; 152 } 153 Matrix& operator*=(const Matrix& r){ 154 Matrix temp(n); 155 for (int i=0; i<n; i++) 156 for (int j=0; j<n; j++) { 157 for (int k=0; k<n; k++) { 158 temp.m[i][j]+=(this->m[i][k]*r.m[k][j]); 159 } 160 } 161 *this=temp; 162 return *this; 163 } 164 void MatrixI(){ 165 for (int i=0; i<n; i++) 166 for (int j=0; j<n; j++) { 167 m[i][j]=0; 168 } 169 for (int i=0; i<n; i++){ 170 m[i][i]=1; 171 } 172 } 173 T value(int i,int j){ 174 return m[i][j]; 175 } 176 }; 177 template <typename T> 178 Matrix<T> operator+(const Matrix<T>& s,const Matrix<T>& r){ 179 Matrix<T> temp(s); 180 temp+=r; 181 return temp; 182 } 183 template <typename T> 184 Matrix<T> operator*(const Matrix<T> &s,const Matrix<T> &r){ 185 Matrix<T> temp(s); 186 temp*=r; 187 return temp; 188 } 189 190 int main(int argc,const char* argv[]){ 191 int N; 192 cin>>N; 193 while (N--) { 194 AutoStep step; 195 cout<<step.start(); 196 } 197 cin>>N; 198 Matrix<double> M(n,*p); 199 vector<Matrix<double>> a; 200 Matrix<double> temp(n); 201 a.push_back(M); 202 for(int i=1;i<=32;i++){ 203 temp=a[i-1]; 204 temp*=temp; 205 a.push_back(temp); 206 } 207 temp.MatrixI(); 208 for (int i=0; i<32; i++) { 209 if (N & (1<<i)) { 210 temp*=a[i]; 211 } 212 } 213 cout<<temp.value(0, n-1)<<endl; 214 return 0; 215 }
输出结果:
问题1
10
A
AC
A
ACA
A
ABBBBCBACBCCBBCBCC
A
ACBC
A
ABAACA
问题2
10
0.0190055
问题3
n^3 * log N
n是状态机个数,N需要求解的字符串长度
可优化的地方很多,n比较大的时候用Strassen算法,n^2.81
N达不到2^32 大小的话,用递归做,省掉我做的许多计算
写法不是很优化,矩阵写的要死人
问题4
只要保存转移矩阵和状态就好,一个是n*n矩阵,一个是n矢量,这个不涉及算法。