微软二面面试题复盘

微软好像是两面平行面,然后通过任意一轮可以进入leader面。一上午连续面了两面,说实话真有点吃不消,一面感觉还行,二面直接凉凉。
主要来说就是两道题,我都没见过,说实话非常慌,不过一面写出来了,二面思路对了但实现方面太紧张连在编辑器里加上using namespace std都忘了,被面试官吐槽,难受😫。其实这题我可以写出来的,越想越后悔,大概还是代码敲得太少,继续努力吧!下面复盘下面试过程。

题目

给出两行字符串,用空格分隔,第二行的称为前缀,查询第二行中每个前缀在第一行中出现的频率(简单来看就说是频数好了,反正除个n一样的)

举例

第一行:abc bcd abe
前缀:a ab bcd
那么前缀a在第一行中的单词出现了2次,ab出现了2次,bcd出现了一次。

想法1

对每个前缀,都在字符串中查找其出现的次数,复杂度是O(n*m)。(假设n为第一行单词个数,m为前缀个数)。
显然复杂度太高,而且n可能很大,前缀的长度也可能很长。继续优化。

想法2

将所有的前缀都存储在一个map里,遍历字符串,如果出现相应的前缀,将map里对应的计数+1。
还是被否定了,面试官说假设前缀非常多,大到map无法装到内存里。
然后在面试官的引导下,来到了最终的方法,利用树,来存储字符串(假设都是小写字母),加快查询的过程。

最终方法

我的想法是读入字符串,然后生成一个统计的树(后来我才意识到这是一种字典树),例如abc bcd abe,那么生成的树如下:
在这里插入图片描述
并且我想到在建立树的过程中,记录节点被访问的个数,那么查询的时候,比如ab,查询到a b时,计数为2,那么ab前缀出现了两次。事后我觉得我的方法甚至有那么一丝巧妙?可惜面试时太紧张,加上自定义数据结构非常生疏,没做出来。。。
ok看看最后的代码。时间复杂度为O(n+m*msize) n为字符串的个数,m为前缀个数,msize为前缀的长度。

代码

#include <string>
#include <vector>
#include <iostream>
#include <sstream>
using namespace std;
struct Treenode {
	vector<Treenode*> child;
	int count;
	Treenode() {
		for (int i = 0; i < 26; i++) {
			child.push_back(NULL);
		}
		count = 0;
	}
};
vector<int> computePrefix(vector<string> strs, vector<string> prefix) {
	Treenode* tree = new Treenode;
	Treenode* cur;
	for (int i = 0; i < strs.size(); i++) {
		cur = tree;
		for (int j = 0; j < strs[i].size(); j++) {
			if (cur->child[strs[i][j]-'a'] == NULL) {
				Treenode* next = new Treenode;
				cur->child[strs[i][j] - 'a'] = next;
				next->count++;
				cur = next;
			}
			else {
				cur = cur->child[strs[i][j] - 'a'];
				cur->count++;
			}
		}
	}
	vector<int> res;
	for (int i = 0; i < prefix.size(); i++) {
		int cnt = 0;
		int j;
		cur = tree;
		for (j = 0; j < prefix[i].size(); j++) {
			if (cur->child[prefix[i][j]-'a'] != NULL) {
				cur = cur->child[prefix[i][j]-'a'];
			}
			else {
				break;
			}
		}
		if (j == prefix[i].size()) {
			cnt = cur->count;
		}
		res.push_back(cnt);
	}
	return res;
}
int main() {
	vector<string> strs;
	vector<string> prefix;
	string str;
	getline(cin, str);
	istringstream is(str);
	string tmp;
	while (is >> tmp) {
		strs.push_back(tmp);
	}
	getline(cin, str);
	istringstream is2(str);
	while (is2 >> tmp) {
		prefix.push_back(tmp);
	}
	vector<int> res;
	res=computePrefix(strs, prefix);
	for (int i = 0; i < res.size(); i++) {
		cout << res[i] << endl;
	}
	system("pause");
}

测试:

输入:abc ac bkd dk fdk f
a b ab d f fd
输出:

在这里插入图片描述

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值