选择10道,编程题3道。
上来就就把网页内置的编译器给ban了,只能用本地编译器答了,和其他厂笔试有所不同。
第一题:
version1和version2的对比,例如:1.2.1 > 1.2.0 ,但1.2等于1.2.0
额外处理数字之间的点号,然后将字符串提取转换成数字再对比即可。
cpp
//返回1时,v1>v2 返回-1时,v1<v2 返回0时,v1==v2
//1.需要注意版本号需要分段比较,因为它是含有点号分隔的数字序列
//2.在就是前导0被忽略,那么可以直接将每段字符串转换成整数,这样前导0会自动消失,01-》1
//3.1.2和1.2.0是相等的
//解题步骤:可以使用双指针法,两个指针i和j分别遍历version1和version2
// 每一轮循环,从当前指针位置开始,提取下一个点号前的数字,计算比较整数值,返回1或-1,依此类推直到遍历完毕
class Solution {
public:
int conpareVersions(string version1, string version2) {
int n = version1.length();
int m = version2.length();
int i = 0, j = 0;//遍历字符串1和字符串2的起始指针
while (i < n || j < m) {
int num1 = 0;
int num2 = 0;
//提取版本号1中当前点号之前的数字段
while (i < n && version1[i] != ".") {
num1 = num1 * 10 + (version1[i] - '0');//字符转数字并累加
i++;
}
//提取版本号2中点号之前的数字段
while (j < m && version2[j] != '.') {
num2 = num2 * 10 + (version2[j] - '0');
j++;
}
if (num1 > num2) {
return 1; // version1的修订号更大
}
else if (num1 < num2) {
return -1;//version2的修订号更大
}
i++;j++;//跳过点号,为下次迭代
}
//所有修订号都一样,版本号一致
return 0;
}
};
第二题:
设计LRU最近和最久未使用,哈希表加双向链表,之前力扣自己写过,只不过我直接用的是list,没自己实现双向链表结构,可能要考察链表吧,但list也没毛病哈哈。
cpp
//list来存储键值对,链表头部表示最近使用的元素,链表尾部表示最近未使用的元素
//unordered_map<int,list<xx>::iteraror>存储key到链表节点的迭代器映射,这样key在O(1)可以定位到链表节点
//get(key): 哈希表中查找key 、不存在返回-1、存在利用哈希表找到链表中节点、把该节点移动带链表头部,返回节点中value
//put(key):哈希表中查找key、如果key存在更新链表中节点的value并把节点移到链表头部
//如果key不存在,缓存满就移除尾部节点(最近未使用),删除哈希表中删除对应的key,创建新节点插入链表头部
//记录key的迭代器
#include<iostream>
#include<unordered_map>
#include<list>
using namespace std;
class LRU {
private:
int cap;//记录缓存最大值
list<pair<int, int>> lt;//用双向链表存储键值对,头部为最新,尾部最旧
unordered_map<int, list<pair<int, int>>::iterator> cacheMap; //哈希表映射键到链表迭代器
public:
LRU(int capacity) : cap(capacity){}
//获取数据
int get(int key) {
auto it = cacheMap.find(key);
if (it == cacheMap.end()) return -1;
//使用splice将访问的节点移动到链表前面
lt.splice(lt.begin(), lt, it->second);
//返回该节点的value
return it->second->second;
}
void put(int key, int value) {
//首先在映射中寻找已有的键
auto it = cacheMap.find(key);
//如果键存于缓存中
if (it != cacheMap.end()) {
it->second->second = value;
lt.splice(lt.begin(), lt,it->second);
return;
}
//如果缓存已达容量上限
if (lt.size() == cap) {
//获取链表尾部最久未使用的键
int key = lt.back().first;
//从哈希映中移除该键
cacheMap.erase(key);
//链表中移除最末尾的元素
lt.pop_back();
}
//链表头部插入新的键值对,保存新节点的迭代器
lt.emplace_front(key, value);
cacheMap[key] = lt.begin();
}
};
int main() {
int capacity;
cin >> capacity; //输入不能为0
LRU lru(capacity);
//用string模拟结果
string s;
while (cin >> s) {
if (s == "get") {
int key; cin >> key;
cout << lru.get(key) << endl;
}
else if (s == "put") {
int key, value;
cin >> key >> value;
lru.put(key, value);
}
}
return 0;
}
第三题:
方案设计题,也需要编码然后输入输出,估计写的大多数可以是伪代码,时间不太够了,只写了一下思路。
题目:一个APP的视频有50-500MB,然后让你设计弱网下如何做好切片策略以及断点续传还有针对上传失败的重试以及退避策略,然后优化前后台的上传体验,兼容用户随时退出APP的场景。