滴滴实习面经

滴滴出行 工程框架与算法 秋储实习生面试

2121.6.22 一面 至今没有二面的通知 凉凉!

自我介绍 没问C++基础 没问数据库

聊项目(以下都是项目里的内容 大概40min 全程1h

进程 线程 的区别 优缺点
TCP/IP UDP各自的优缺点
可靠传输 流量控制 拥塞控制 三次握手 四次挥手 为什么不两次握手 time_wait过多会对系统有什么影响

为什么都用进程 不考虑在一个进程下开辟三个线程?

网络通信模型 7层 socket通信

信号量机制的原子性 信号量加 减 恢复 三个过程是如何体现原子性的

共享内存

锁机制 问我的项目里遇到网络通信问题 是如何解决的 开辟两个进程进行单独处理

建立socket通信进行数据包传输时 如果上一个数据包还没来得及接收 下一个就发送了 怎么处理

多进程并发问题 问做过并发相关的开发嘛 如何处理多进程并发执行的问题 如死锁 介绍了死锁 产生死锁的情况 和如何避免死锁

对于项目中的设备为什么选择在局域网下进行 而不是将两部分集成到一个设备上
问我以后的职业规划


做题 20min

Leetcode 25 k个一组反转链表 困难

输入:1-2-3-4-5-6-7-8

输出:3-2-1-6-5-4-7-8

不太会 直接写了最简单的反转链表

然后说了一下刚才那个题的思路

算法思路
滴滴实习面经_第1张图片

补充一下代码实现:

#include
using namespace std;
#include
#include

struct ListNode
{
	int val;
	ListNode* next;
	ListNode(int x):val(x),next(nullptr){}
};

//反转链表
class Solution1
{
public:
	ListNode* reverseList(ListNode* head)
	{
		if (head == NULL)return {};
		ListNode* pre = nullptr;
		ListNode* cur = head;
		while (cur)
		{
			ListNode* temp = cur->next;
			cur->next = pre;
			pre = cur;//继续向下遍历
			cur = temp;
		}
		return pre;//返回原链表的最后一个节点作为新链表的头节点
	}
};

//=----------------------------------分界线---------------------------------------------------

//k个一组反转链表
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
 
//递归的遍历每一组k个节点 这一组不足k个节点的话直接返回这组的头节点
class Solution
{
public:
	ListNode* reverseKGroup(ListNode* head, int k)
	{
		ListNode* last = head;//创建一个指针指向每组的第一个节点
		for (int i = 0; i < k; i++)//递归终止条件==遍历某一组的k个节点 查看是不是够k个
		{
			if (last == NULL)return head;//如果head后续节点不够k个直接返回这一组的头节点
			last = last->next;
		}
		ListNode* pre = head;//创建pre指针指向头节点 pre指向每一组的第一个节点
		ListNode* cur = head->next;//创建cur指针指向头节点的下一个节点  cur指向每一组的第二个节点
		for (int i = 0; i < k - 1; i++)//对这一组的k个节点进行反转  因为是两两一组进行反转的  pre移动k-1个位置  就可以反转k个节点;
		{
			ListNode* temp = cur->next;//temp指向每一组的第三个节点
			cur->next = pre;//实现每一组里面第一个和第二个节点的反转;
			pre = cur;//以两个节点为一组进行反转,继续向下遍历;
			cur = temp;
		}
		//用next来接收下一组反转之后的头节点
		ListNode* next = reverseKGroup(cur, k);//在完成一组的反转后 cur指向下一组的第一个节点; next指针指向不足k个节点的那一组的第一个节点;
		head->next = next;// head是第一组反转之后的尾节点 指向下一组反转之后的头节点 将各组连接起来 保证链表的完整性;
		return pre;//返回新链表的头节点即可 pre(head)是指向第一组待反转区域的最后一个节点的,也就是新链表的第一个节点;
	}
};

//自定义输出链表节点值得函数
vector<int>Fun(ListNode* node)
{
	vector<int>res;
	ListNode* p = node;
	while (p)
	{
		res.push_back(p->val);
		p = p->next;
	}
	return res;
}


int main()
{
  //实例化链表
	ListNode*head=new ListNode(1);
	ListNode* head0 = head;//head0保存最初的头节点
	head->next = new ListNode(2);
	head = head->next;
	head->next = new ListNode(3);
	head = head->next;
	head->next = new ListNode(4);
	head = head->next;
	head->next = new ListNode(5);
	head = head->next;
	head->next = new ListNode(6);
	head = head->next;
	head->next = new ListNode(7);
	head = head->next;
	head->next = new ListNode(8);
	head = head->next;
	head->next = new ListNode(9);

	ListNode* node1 = new ListNode(0);
	ListNode* node2 = new ListNode(0);
	Solution2 so2;
	Solution1 so1;
	node1 = so1.reverseList(head0);
	node2 = so2.reverseGroup(head0, 3);
	vector<int>ans;
	ans = Fun(node1);//自定义函数输出链表每个节点的值
	for (auto it = ans.begin(); it != ans.end(); it++)
	{
		cout <<"反转之后的链表是:"<< * it << endl;
	}
	system("pause");
	return 0;
}

反问

-----------------
**感悟**:
滴滴面试体验也是很不错的  面试官是个挺年轻的哥哥 感觉交流起来也没啥障碍  脾气也蛮好的 各种引导 很有耐心
面试内容真的分企业 参加字节两面 项目都没怎么聊 滴滴上来就直接聊项目 就在项目里深挖 问的很详细 必须得好好准备
比较而言 滴滴得一面比字节一面有难度 也是自己对项目的一些细节没了解透吧
继续面 继续干!!

你可能感兴趣的:(数据结构与算法,实习经验,C++基础,面试,c++,算法)