本文最后更新于 34 天前,其中的信息可能已经有所发展或是发生改变。
- 深挖你做过的项目,问你在项目中的工作、承担的角色,根据你的回答会问一些专业性的问题,这里可能问了有二三十分钟。
- 主要是考察你对项目的了解程度;
- 可能会问实践项目的构成、技术栈、创新点等等;
- 由于面试官已经长期从事行业生产工作,所以对于项目存在的一些问题可能会一眼就看出来并指出,会问你项目是否存在一些问题;
- 计算机基础方面,由于是实习,可能问得很简单:
- 问数据库相关:
- 问了我索引和主键(这点很亏,我听成了组件,回答没有学过);
- 现场写一句SQL语句;
- 问计算机网络相关:
- http常见的响应码和含义;
- post和get的区别;
- 操作系统相关:
- 线程和进程的区别;
- 线程调度的方法,老实说我没搞懂他这一点问的什么,应该是指算法?
- 什么是死锁?造成死锁的原因?解决死锁的办法?
- 数据结构貌似一点没问;
- 问数据库相关:
- 业务方面:问有没有玩过短视频,假设了一个情景:
- 仅仅已知A发布了一个短视频,A的界面显示视频发布成功,并且能在主页看到;
- B访问A的主页,但是看不到A新发布的视频;
- 没有其他已知条件,问如果你是测试人员,你会怎么解决这个问题?
- 算法题:二路归并排序,已知两个有序数组,查找这两个数组合并后第K大的数字,问有没有O(lgn)的算法,我当时没想起来,只想到了O(n)的解法,后面会将O(n)和O(lgn)的算法贴在下面。
力扣上的归并排序如下所述,和面试的题也差不多,但我代码还是基于面试题来写:
给你两个按 非递减顺序 排列的整数数组 nums1
和 nums2
,另有两个整数 m
和 n
,分别表示 nums1
和 nums2
中的元素数目。
请你 合并 nums2
到 nums1
中,使合并后的数组同样按 非递减顺序 排列。
注意:最终,合并后数组不应由函数返回,而是存储在数组 nums1
中。为了应对这种情况,nums1
的初始长度为 m + n
,其中前 m
个元素表示应合并的元素,后 n
个元素为 0
,应忽略。nums2
的长度为 n
。
示例 1:
输入:nums1 = [1,2,3,0,0,0], m = 3, nums2 = [2,5,6], n = 3 输出:[1,2,2,3,5,6] 解释:需要合并 [1,2,3] 和 [2,5,6] 。 合并结果是 [1,2,2,3,5,6] ,其中斜体加粗标注的为 nums1 中的元素。
示例 2:
输入:nums1 = [1], m = 1, nums2 = [], n = 0 输出:[1] 解释:需要合并 [1] 和 [] 。 合并结果是 [1] 。
示例 3:
输入:nums1 = [0], m = 0, nums2 = [1], n = 1 输出:[1] 解释:需要合并的数组是 [] 和 [1] 。 合并结果是 [1] 。 注意,因为 m = 0 ,所以 nums1 中没有元素。nums1 中仅存的 0 仅仅是为了确保合并结果可以顺利存放到 nums1 中。
提示:
nums1.length == m + n
nums2.length == n
0 <= m, n <= 200
1 <= m + n <= 200
-109 <= nums1[i], nums2[j] <= 109
进阶:你可以设计实现一个时间复杂度为 O(m + n)
的算法解决此问题吗?
首先是O(m+n)的解法:
class Solution {
public:
int merge_and_find(vector<int>& nums1, int m, vector<int>& nums2, int n,int k) {
vector<int> nums(m + n);
int i = 0, j = 0, a = 0;
while (i < m && j < n) {
nums[a++] = (nums1[i] <= nums2[j]) ? nums1[i++] : nums2[j++];
}
while (i < m) nums[a++] = nums1[i++];
while (j < n) nums[a++] = nums2[j++];
return nums[k-1];
}
};
O(lgn)的解法很少见(也可能是我太菜了所以不知道),但是其实是有的,要求第K大的数,假设在第一个数组nums1 中取 x 个,那么第二个数组中取的个数也就确定了,为 k – x 个,对于x的值,可以用二分查找,
#include <vector>
#include <algorithm>
using namespace std;
int findKthElement(vector<int>& nums1, int start1, int remaining_len1,
vector<int>& nums2, int start2, int remaining_len2,
int target_order) {
// 始终保证 nums1 是较短的数组以简化边界处理
if (remaining_len1 > remaining_len2) {
return findKthElement(nums2, start2, remaining_len2,
nums1, start1, remaining_len1,
target_order);
}
// 边界情况处理
if (remaining_len1 == 0) {
return nums2[start2 + target_order - 1];
}
if (target_order == 1) {
return min(nums1[start1], nums2[start2]);
}
// 计算分区点
const int partition1 = min(target_order / 2, remaining_len1);
const int partition2 = target_order - partition1;
const int pivot1 = nums1[start1 + partition1 - 1];
const int pivot2 = nums2[start2 + partition2 - 1];
// 递归处理不同分区情况
if (pivot1 < pivot2) {
return findKthElement(
nums1, start1 + partition1, remaining_len1 - partition1,
nums2, start2, remaining_len2,
target_order - partition1
);
} else if (pivot1 > pivot2) {
return findKthElement(
nums1, start1, remaining_len1,
nums2, start2 + partition2, remaining_len2 - partition2,
target_order - partition2
);
}
return pivot1; // 相等时直接返回
}
详细的复盘,点赞👍