【每日刷题3.19】2道算法+1道真题+10道面试 - 阿V

昨天没完成,争取今天全部完成!!!加油~

算法练习

1. 设计LRU缓存结构

 之前写过一次,忘记了,这次看着别人的答案理解了一遍,学会了使用迭代器,以及list的erase函数,map的find函数等用法。本来想使用acm模式的,但这个好像只能使用核心代码模式。


代码详情:

class Solution {
private:
    int capacity_; //定义缓存容量
    list<int> list_; //创建双向链表,存储值
    unordered_map<int, pair<int,list<int>::iterator>> map_; //key对应key,value对应value和链表的迭代器
public:
    Solution(int capacity){
         // write code here
        capacity_ = capacity;
    }
    
    int get(int key) {
         // write code here
        auto it = map_.find(key); //寻值,返回迭代器
        if (it == map_.end()){ //不存在返回-1
            return -1;
        }
        
        int value = it->second.first; //获取值
        set(key,value); //更新值
        return value;
    }
    
    void set(int key, int value){
         // write code here
        auto it = map_.find(key); //返回一个迭代器
        if (it == map_.end() && map_.size() >= capacity_){ //迭代器等于末尾说明哈希表没有该值,并且缓存容量达到上限
            map_.erase(list_.back()); //在哈希表中删除链表最后一个元素
            list_.pop_back(); //弹出最后一个元素
        }
        
        if (it != map_.end()){ //说明哈希表里含有该值,需要移动该值到链首
            list_.erase(it->second.second);
        }
        
        list_.push_front(key); //将key更新到链首
        map_[key].first = value;
        map_[key].second = list_.begin(); //更新哈希表中value的迭代器
    }
};

/**
 * Your Solution object will be instantiated and called as such:
 * Solution* solution = new Solution(capacity);
 * int output = solution->get(key);
 * solution->set(key,value);
 */

2. 字符串出现次数的TopK问题

哈希表计算字符串出现次数,接着排序(先比数量,在比字符ASCII码大小)。


代码详情(ACM模式):

#include <iostream>
#include <vector>
#include <string>
#include <unordered_map>
#include <algorithm>
using namespace std;


class Solution {
public:
	vector<vector<string>> topKstrings(vector<string>& strings, int k) {
		vector<vector<string>> result; //存储答案
		unordered_map<string, int> map_; //创建哈希表,key代表字符串,value代表该串数量

		int n = strings.size();
		for (int i = 0; i < n; ++i) {
			if (map_.count(strings[i])) { //存在加一
				map_[strings[i]] += 1;
			}
			else { //不存在初始化为0
				map_[strings[i]] = 1;
			}
		}

		vector<pair<int, string>> sort_list; //创建排序表,int存储该串数量,string存储字符串
		for (auto m : map_) { //将哈希表数据导入排序表中
			sort_list.push_back({ m.second,m.first });
		}
		sort(sort_list.begin(), sort_list.end(), [](pair<int, string> p1,pair<int, string> p2) { //根据数量和字符串排序
			if (p1.first != p2.first) return p1.first > p2.first; //数量不同从大到小排序
			else { //数量相同,按字符ASCII码大小,从小到大排
				int i = 0;
				while (p1.second[i] == p2.second[i]) {
					if (i < p1.second.size() && i < p2.second.size()) {
						++i;
					}
					else {
						if (i == p1.second.size()) {
							return false;
						}
						{
							return true;
						}
					}
				}

				return p1.second[i] < p2.second[i];
			}
			});

		for (int i = 0; i < k; ++i) {
			result.push_back({ sort_list[i].second,to_string(sort_list[i].first) });
		}

		return result;
	}
};


/*
a b c b
2

*/
int main() {
	vector<string> strings; //存储字符串组
	string tem; //存储字符串
	while (cin >> tem) { //输入字符串
		strings.push_back(tem);
		if (getchar() == '\n') {
			break;
		}
	}
	int k = 0; //需要获取前k个数
	cin >> k;

	Solution sl;
	vector<vector<string>> result = sl.topKstrings(strings, k);

	//输出答案
	int n = result.size();
	for (int i = 0; i < n; ++i) {
		cout << result[i][0] << ' ' << result[i][1] << endl;
	}


	return 0;
}

算法真题

1. 出模拟赛

 

这题没想出来,我使用的方法时间复杂度过高没通过,看了题解也没理解,下次再尝试。

面试题

1. 进程和线程以及它们的区别

 进程是资源分配的基本单位,线程是程序执行的最小单位。

区别:

1. 进程拥有独立地址空间和资源,线程共享该进程的所有资源

2. 进程比线程更健壮,一个进程崩溃不会导致其他进程崩溃,一个线程崩溃会导致整个进程崩溃。

3. 进程开销比线程大。

2. TCP拥塞控制?

拥塞控制是防止过多的数据注入网络,导致网络中的路由器或链路过载

拥塞控制流程:

1. 慢开始:最开始发送方的拥塞窗口为1,由小到大递增,每经过一个传输轮次,拥塞窗口cwnd加倍,当拥塞窗口cwnd超过慢开始门限,使用拥塞避免算法

2. 拥塞避免算法:每经过一个传输轮次,cwnd增加1,一旦发现网络拥塞,将慢开始门限设置为当前值的一半,并重新设置拥塞窗口cwnd为1,重新慢开始

3. 快重传:接收方每收到一个失序的报文段就立即发出重复确认,发送方只要收到3个重复确认就立即重传。

4. 快恢复:当发送方连续收到三个重复确认,就将慢开始门限减半,将当前窗口设置为慢开始门限,并采用拥塞避免算法。

3.  C/C++内存有哪几种类型?

 C中内存分为:(malloc)、(局部变量、函数参数)、程序代码区(存放二进制代码)、全局/静态存储区(全局变量、static变量)和常量存储区(const)。C++有自由存储区。

4. 什么是死锁?死锁产生的条件?

死锁:在两个或者多个并发过程中,如果每个进程持有某种资源又等待其他进程释放资源,导致进程无法推进,称为死锁。通俗地讲,两个或多个进程无限期的阻塞相互等待的一种状态。

死锁产生条件:

1. 互斥:资源属于非共享

2. 占有并等待

3. 非抢占

4. 循环等待

5. TCP如何实现可靠连接?

 TCP通过序列号超时重传检验和(检测包里面数据是否正确)、流量控制滑动窗口拥塞控制实现可靠性。

6. 堆和栈的区别?

1. 堆存放动态分配的对象。

2. 栈用来保存定义在函数内的非static对象。

3. 静态内存用来保存static对象。

4. 栈是编译器自动创建和销毁的。

7. 进程有哪几种状态?

1. 就绪状态:进程已获得除处理机以外的所需资源,等待分配处理机资源。

2. 运行状态: 占用处理机资源运行

3. 阻塞状态: 进程等待某种条件,处于无法执行状态。

8. TCP三次握手

第一次握手:客户端--》服务端(数据包:SYN=1,seq=J),客户端进入SYN_SENT状态。

第二次握手:服务端--》客户端(数据包:SYN=1,ACK=1,ack=J+1,seq=K),服务端进入SYN_RCVD状态。

第三次握手:客户端检查数据包是否准确,客户端--》服务端(数据包:ACK=1,ack=K+1),服务端检查数据包是否准确,两者进入ESTABLISHED状态。

9. 程序编译的过程?

 四个过程:预处理(检查程序是否可以执行) --》编译(转换为汇编语言)--》汇编(转换为二进制机器指令)--》链接(链接其他文件)。

10. 分页和分段有什么区别(内存管理)?

段式存储:将程序的地址空间划分为若干段,每一段存储相同意义的信息

页式存储:将程序的逻辑地址划分为固定大小的页,物理内存也划分同样大小的帧

区别:

1. 目的不同:分页服务于系统管理,分段服务于用户,段内数据是一组有意义且相对完整的信息。

2. 大小不同:页的大小固定,段长度由功能决定

3. 地址空间不同:段向用户提供二维地址空间,页向用户提供一维地址空间

4. 信息共享:段是信息的逻辑单位,便于存储保护和信息共享,页的保护和共享受到限制。

5. 内存碎片:页式存储没有外碎片,但会有内碎片;段无内碎片,但会产生外碎片。

 11. TCP四次挥手

第一次挥手:客户端--》服务端(FIN),客户端进入FIN_WAIT_1状态。客户端不再发送数据,但可以接收数据。

第二次挥手:服务端--》客户端(ACK),服务端进入CLOSE_WAIT状态。服务端开始处理剩下的数据。客户端接收ACK,进入FIN_WAIT_2状态。

第三次挥手:服务端--》客户端(FIN),服务端进入LAST_ACK状态。服务端不再发送数据。

第四次挥手:客户端--》服务端(ACK),客户端进入TIME_WAIT状态(防止最后的确认数据包丢失),服务端接收ACK,进入CLOSED状态,一段时间后,客户端也进入CLOSED状态。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ZZW游戏制造

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值