2022 5 字节实习一面--- Pico

第一部分 自我介绍+项目

10min自我介绍和项目介绍(项目没怎么深挖,大概了解了一下)


第二部分 基础知识

20min左右;
面试官是根据简历上的内容有针对性的提问的,有些知识在问你之前还会先问问你掌握的怎么样,平时自己做项目接触到的多嘛。挺人性化的哈哈哈哈 不会也没啥关系
具体如下:
ISO七层网络模型 每一层的作用以及每一层有哪些协议;
了解Http 1.0 和http 2.0
Http状态码 直接问的503服务器不可访问 这个好像很特别 ;
进程 线程和协程
TCP UDP的异同;
三次握手 四次挥手 为什么不两次握手或者四次握手 而是三次?我这里只考虑了两次握手的情况 四次握手应该也类似吧;
进程通信IPC的几种方式;
着重探讨了消息队列的应用场景异步 解耦 削峰
Linux内核相关的知识;Linux下信号有哪几种形式?比如 按下ctrl+c后退出的过程信号是怎样传递的,这块不是很熟悉;
熟悉的数据结构,常规问题 数组和链表的区别;
穿插问了一下怎么判断链表是不是有环
还问了C++对数组的大小改变是怎样实现的;(面试官的意思是让我介绍下C++是怎么实现数组容量改变的。这里会涉及到数组越界问题)
还谈到了vector的二倍扩容机制;
还谈到了堆栈的区别;
还谈到栈和队列的区别;
问了全局变量存放在堆还是栈(堆)
一些函数参数 返回值 局部变量等存放在哪(栈)
实际应用中 ,哪些地方会用到堆哪些地方会用到栈;我答的递归的本质是用栈实现的;很显然没理解面试官的意思;
堆的应用场景:堆排序(大顶堆 小顶堆);优先级队列(priority_queue)实现top_k问题等;
栈的应用场景:改变元素的顺序 ;括号匹配 ;逆波兰表达式求值;两个栈实现一个队列;


第三部分 代码题

20min左右
经典题目:求小于给定数字n的最大数

在这里插入图片描述

参考了几种解题思路 现给出以下几种方案:

方案一:逐位比较(存在一些问题) 确定(也是面试官提示我的写法)


//小于n的最大数
//假设给定的数组是 [1,2,4,9] n=2533 则返回的最大数是2499
class Solution
{
    
    
public:
	vector<int>maxNumber(const vector<int>& nums, int n)
	{
    
    
		vector<int>arr, ans;//arr存放给定数字的每一位;ans返回最终的结果
		int minChoose = 10, maxChoose = 0;
		bool exist[10];
		for (int x : nums)
		{
    
    
			exist[x] = true;
			minChoose = min(minChoose, x);//可选择的最小值 给定例子中就是1 
			maxChoose = max(maxChoose, x);//可选择的最大值 给定的例子中就是9
		}
		while (n)
		{
    
    
			arr.push_back(n % 10);//将n的每一位存到数组中
			n /= 10;
		}
		reverse(arr.begin(), arr.end());//答案应尽可能和num位数相同 若位数相同无解 则答案减少一位且每位取最大值 
		for (int i = 0; i < arr.size(); i++)   //arr[i]是当前位 arr[i+1]是后一位
		{
    
                    //待选择的后一位大于等于可选数字的最小值时,当前位才可以选等值;否则只能选小于的值
			int j = (i == arr.size() - 1 || arr[i + 1] >= minChoose ? arr[i] : arr[i] - 1); //j是你所找数字的最高位
			while (j >= 0 && !exist[j])
			{
    
    
				j--;  //j=0 j--之后-1小于0 考虑最高位是1的情况
				if (j < 0)//同位数无解 降低解的位数 ;因为位数是少于给定数字位数的 所以所有的位都取最大值即可;
				{
    
    
					ans.clear();
					for (int k = 0; k < arr.size() - 1; k++)
					{
    
    
						ans.push_back(maxChoose);
					}
					break;
				}
				if (j != arr[i])//当前位取了小于原数同位的值 则解就确定了 后面每一位都可以取最大值;
				{
    
    
					ans.push_back(j);
					while (ans.size() < arr.size())
					{
    
    
						ans.push_back(maxChoose);
					}
					//break;
				}
				ans.push_back(j);//当前位取了等于原数同位的值 直接将当前位放入结果数组中即可
			}
		}
		return ans;
	}
};


int main()
{
    
    
	vector<int>nums = {
    
     1,2,4,9};
	int n = 2533;
	vector<int>res;
	//int ans;
	Solution so;
	//res=so.maxNumber(nums, n);
	res = so.maxNumber(nums,n);
	for (auto it = res.begin(); it != res.end(); it++)
	{
    
    
		cout << *it;
	}
	system("pause");
	return 0;
}

方案二:全排列的思路(回溯) ---测试案例都是成功的


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


//全排列+回溯
//给定一个数组nums和一个指定的数字n,用数组中的数字组成一个整数 使得这个整数是不大于n的最大数;
class Solution
{
    
    
public:
	vector<int>vec;//存储一个结果集合
	string path;//存储单个数字的集合
	int findMax(vector<int>& nums, int n)
	{
    
    
		int res = INT_MIN;
		dfs(nums, n);
		for (auto num : vec)
		{
    
    
			res = max(res, num);//从容器中选一个最大的值
		}
		return res;
	}
	void dfs(vector<int>& nums, int x) 
	{
    
    
		if (path.size() > 0 && stoi(path) >= x)return; //递归终止条件
		for (int i = 0; i < nums.size(); i++) 
		{
    
    
			path += to_string(nums[i]);//用数组中的数字组成数字 用一个字符串来接收每一位数字
			if (stoi(path) < x)  ///将字符串表示的数字转成整型数字进行比较
			{
    
    
				vec.push_back(stoi(path));//将所有小于给定数字的数字存入容器中
			}
			dfs(nums, x);
			path.pop_back();//回溯
		}
	}
};

int main()
{
    
    
	vector<int> nums = {
    
    5,6,7};
	int x = 120;
	Solution so;
	int ans = 0;
	ans = so.findMax(nums, x);
	cout << ans<< endl;
	system("pause");
	return 0;
}






剑指offer 45 把数组排成最小的数

输入一个非负整数数组,把数组中所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个;

例如:

扫描二维码关注公众号,回复: 15716976 查看本文章

输入: [10,2]
输出: “102”

在这里插入图片描述

//核心思路就是从高位到低位  一直选取最小的数字

class Solution
{
    
    
public:
	string minNumber(vector<int>& nums)
	{
    
    
		vector<string>strs;
		string ans;
		for (int i = 0; i < nums.size(); i++)//遍历数组中的所有元素
		{
    
    
			strs.push_back(to_string(nums[i]));//把整数转换成字符串 接下来实现重排列
		} //每两个表示数字的字符串进行比较 使得两个字符串排成较小的数字
		auto cmp = [](string& s1, string& s2) {
    
    return s1 + s2 < s2 + s1; };//Lamda表达式实现比较 比较方式是 第一个字符串+第二个字符串 小于 第二个字符串+第一个字符串组成的数字;
		sort(strs.begin(), strs.end(), cmp);//前两个参数是排序范围 第三个参数是排序规则
		for (auto str:strs) ans+=str;
		return ans;
	}
};


//用冒泡排序实现 =================================================================================

//用冒泡排序实现
class Solution
{
    
    
public:
	string minNumber(vector<int>& nums)
	{
    
    
		int len = nums.size();
		vector<string>str;
		string res;
		for (int i = 0; i < len; i++)
		{
    
    
			str.push_back(to_string(nums[i]));
		}
		for (int i = 0; i < str.size(); i++) //冒泡排序的逻辑实现
		{
    
    
			for (int j = 0; j < str.size() - i - 1; j++)
			{
    
    
				if (str[j] + str[j + 1] > str[j + 1] + str[j])
				{
    
    
					string tmp = str[j];
					str[j] = str[j + 1];
					str[j + 1] = tmp;
				}
			}
		}
		for (auto c : str)res+=c;
		return res;
	}
};



leetcode402 移掉k位数字

给定一个以字符串表示的非负整数num和一个整数k,移除这个数中的k位数字,使得剩下的数字最小;以字符串的形式返回这个最小的数字即可
例如:
输入:num = "1432219", k = 3
输出:"1219"
解释:移除掉三个数字 4, 3, 和 2 形成一个新的最小的数字 1219 。

输入:num = "10200", k = 1
输出:"200"
解释:移掉首位的 1 剩下的数字为 200. 注意输出不能有任何前导零

在这里插入图片描述
小注
最小的实现是通过向容器中添加元素,当遇到更小的元素删除容器中的最后一个元素,然后将这个较小的元素放入到容器中

C++实现

class Solution
{
    
    
public:
	string removek(string num, int k)
	{
    
    
		vector<int>res;
		for (auto x : num)
		{
    
    
			while (!res.empty() && x < res.back() && k)
			{
    
    
				res.pop_back();//将较大的数字移除
				k--;
			}
			res.push_back(x);//较小的数字存入容器中
		}
		for (;k>0; k--)//考虑k最终没减为0的情况 则依次删除容器尾部的元素即可
		{
    
    
			res.pop_back();
		}
		string ans = "";
		bool isZero = true;
		for (auto num : res)
		{
    
    
			if(isZero && num == '0')continue;
			isZero = false;
			ans += num;
		}
		return ans == "" ? 0 : ans;
	}
};

//移掉k位数字使剩下的数字可以组成的数字是最小的 不能改变原给定数组中的数字的顺序
class Solution
{
    
    
public:
	string removeKdigits(string num, int k)
	{
    
    
		vector<int>res;
		for (auto& digit : num)//从前向后遍历 移除遇到的较大的k个数字
		{
    
    
			while (res.size() > 0 && res.back() > digit && k)//当前遍历到的数字小于容器尾部的数字 删除尾部数字 k做自减 最后留下的数字就是一个符合条件的最小数字
			{
    
    
				res.pop_back();
				k--;
			}
			res.push_back(digit);
		}
		for (; k > 0; --k)//考虑k最终没有减为0的情况 则依次删除容器尾部的元素 例如132319 k=3 当得到最后的数字后 k=1 
		{
    
    
			res.pop_back();
		}
		string ans = "";//初始化一个空串用于连接最小数字的字符串
		bool isLeadingZero = true;//考虑存在前导零的情况 例如 104129这个数字去掉三个数之后是存在前导零的 
		for (auto& digit : res)
		{
    
    
		//遇到前导0 不计入 直接进行下一个数字的拼接
			if (isLeadingZero && digit == '0')continue;//continue是跳过本次循环体中余下尚未执行的语句,立即进行下一次的循环条件判定,可以理解为仅结束本次循环
			isLeadingZero = false;//不存在前导零 
			ans += digit;//将vector中的数字连接成字符串
		}
		return ans == "" ? "0" : ans;//最后的字符串是空串直接返回0 不是空串返回这个字符串即可;
	}
};


猜你喜欢

转载自blog.csdn.net/weixin_48433164/article/details/124749854