智力题
高楼扔鸡蛋
100层楼和2个鸡蛋,求最少几次能够一定知道鸡蛋在哪一层扔下来会碎。
https://leetcode-cn.com/problems/super-egg-drop/
当楼层为100,鸡蛋为2的时候,最少需要14次。
天平称重
给你12个球和一个天平,现知道只有一个和其它的重量不同,问怎样称才能用三次就找到那个球,并知道是轻了还是重了。
答:先分成3堆4个,然后不会了。
https://www.cnblogs.com/yan456jie/p/5369362.html
4个人过桥
四个人晚上要过一个桥回家,
由于桥上的灯坏了,只能用四个人仅有的一个手电筒照明,手电筒只能坚持照明17分钟.
而且桥很窄,一次只能通过两个人,
四个人过桥的速度也不同,甲乙丙丁过桥需要的时间分别是1分钟.2分钟.5分钟.10分钟.
问:怎样能让4人全部照明通过
答:先让甲乙过桥,2分钟,然后甲回来1分钟,丙丁过桥10分钟,乙回来2分钟,甲乙过桥2分钟,10+2+2+2+1 = 17。
雷火算法题
最小公共子串
给定两个字符串s1和s2,求这两个字符串的所有最长公共子串(连续的)。
分析:最小公共子串问题,不求最大长度,而是求字符串。
其实最小公共子串问题没什么好说的,但是我一紧张连dp方程都写不出来了,最后想用暴力解决还出了BUG,我好菜啊。
//暴力匹配,晚点再更新dp的做法
public static void main(String[] args) {
//Scanner in = new Scanner(System.in);
//int a = in.nextInt();
//System.out.println(a);
//s1 s2
List<String> r = getString("abccccabcd","abcdcccc");
for(String s:r){
System.out.println(s);
}
}
//abcccc abc 3 abc
//ArrayList<String>
public static ArrayList<String> getString(String s1,String s2){
char[] char1 = s1.toCharArray();
char[] char2 = s2.toCharArray();
ArrayList<String> res = new ArrayList<>();
res.add("");
String tmp;
for(int i=0;i<char1.length;i++){
for(int j=0;j<char2.length;j++){
if(char1[i] == char2[j]){
tmp = find(char1,i,char2,j);
if(tmp.length() > res.get(0).length()){
res.clear();
res.add(tmp);
}else if(tmp.length() == res.get(0).length())
res.add(tmp);
}
}
}
return res;
}
public static String find(char[] char1,int start1,char[] char2,int start2){
StringBuilder sb = new StringBuilder();
while(start1 < char1.length && start2<char2.length){
if(char1[start1] == char2[start2]){
sb.append(char1[start1]);
start1++;
start2++;
}else{
break;
}
}
return sb.toString();
}
//dp版,没有对字符串去重
public static void main(String[] args) {
List<String> list = commonString("abcccccabcd","abcdcccc");
for (String s:list){
System.out.println(s);
}
}
public static List<String> commonString(String s1,String s2){
int n = s1.length();
int m = s2.length();
char[] char1 = s1.toCharArray();
char[] char2 = s2.toCharArray();
int[][] dp = new int[n+1][m+1];
List<String> res = new ArrayList<>();
res.add("");
for(int i=1;i<dp.length;i++){
for(int j=1;j<dp[0].length;j++){
if(char1[i-1] == char2[j-1])
dp[i][j] = dp[i-1][j-1]+1;
else
dp[i][j] = 0;
if(dp[i][j] > res.get(0).length()){
res.clear();;
res.add(s1.substring(i-dp[i][j],i));
}else if(dp[i][j] == res.get(0).length()){
res.add(s1.substring(i-dp[i][j],i));
}
}
}
return res;
}
制高点
1.有一个二维数组,里面各值代表山坡高度(值均>1),要求你找到所有制高点。
2.所谓制高点:指可以从这个点往上下左右四个边界都能走出去。例如图中7、6以及第2行第3列的5,这三个点都是制高点。
3.移动规则:可以从一个点向上下左右四个方向走,只能走向不大于自己的值的位置。
matrix = [ [1, 3, 2, 3, 5],
[3, 4, 5, 6, 3],
[2, 7, 4, 3, 3],
[5, 2, 2, 3, 1] ]
输出 7 6 5
思路:从上下左右4条边进行深度优先遍历,然后把遍历到的点放入数组中,一共4个数组,然后取交集(面试官提示的思路)。
不过话说回来,4个数组求交集挺麻烦的吧,我感觉额外开一个二维数组,把边遍历到的次数保存下来比较好吧。
static boolean[][] visited;
public static void main(String[] args) {
// Scanner scan = new Scanner(System.in);
// int n = scan.nextInt();
// int m = scan.nextInt();
// int[][] matrix = new int[n][m];
// for(int i=0;i<n;i++){
// for(int j=0;j<m;j++){
// int tmp = scan.nextInt();
// matrix[i][j] = tmp;
// }
// }
int n = 4,m = 5;
int[][] matrix = new int[][]{
{1,3,2,3,5},
{3,4,5,6,3},
{2,7,4,3,3},
{5,2,2,3,1},
};
List<int[]> up = new ArrayList<>();
List<int[]> down = new ArrayList<>();
List<int[]> left = new ArrayList<>();
List<int[]> right = new ArrayList<>();
visited = new boolean[n][m];
//最上面一行
for(int i=0;i<m;i++){
a1(matrix,0,i,up);
}
//right
visited = new boolean[n][m];
for(int i=0;i<n;i++){
a1(matrix,i,m-1,right);
}
visited = new boolean[n][m];
//left
for(int i=0;i<n;i++){
a1(matrix,i,0,left);
}
visited = new boolean[n][m];
//down
for(int i=0;i<n;i++){
a1(matrix,n-1,i,down);
}
List<int[]> ans = new ArrayList<>();
for(int[] tmp:up){
if(find(left,tmp) && find(right,tmp) && find(down,tmp)){
ans.add(tmp);
}
}
for(int[] p:ans){
System.out.println(matrix[p[0]][p[1]]);
}
}
public static boolean find(List<int[]> list,int[] target){
for(int[] i:list){
if(i[0] == target[0] && i[1] == target[1])
return true;
}
return false;
}
public static void a1(int[][] matrix,int i,int j,List<int[]> res){
visited[i][j] = true;
int[] p = new int[]{i,j};
int tmp = matrix[i][j];
res.add(p);
if(i>0 && !visited[i-1][j] && matrix[i-1][j] >= tmp)
a1(matrix,i-1,j,res);
if(j>0 && !visited[i][j-1] && matrix[i][j-1] >= tmp)
a1(matrix,i,j-1,res);
if(i<matrix.length-1 && !visited[i+1][j] && matrix[i+1][j] >= tmp)
a1(matrix,i+1,j,res);
if(j<matrix[0].length-1 && !visited[i][j+1] && matrix[i][j+1] >= tmp)
a1(matrix,i,j+1,res);
}
腾讯算法题
微信跳-跳游戏
1、有100个格子,每个格子上有一 个蘑菇,蘑菇分为好蘑菇和毒蘑菇,好蘑菇增加体力值n,毒蘑菇消耗体力值n
2、人的初始体力值为m
3、跳的格子的距离与消耗的体力值成正比,正比关系是1:1
问题:输入一个人的初始体力值m和格子初始化序列list,求问:写一个函数, 判断该人是否能否跳到终点?如果不能,函数返回-1,如果可以,返回剩余的最大体力值。
分析:
这道题我在面试的时候想复杂了,想用dp或者是回溯法去解决。然后就被面试官吐槽说这道题有这么麻烦吗?一趟for循环就能解决了,让我下去再好好想想。
面试结束之后,我想了一想,其实这道题的解法非常简单,但是我在面试的时候可能过于紧张就完全没想到。
考虑一下毒蘑菇的情况,如果本来就无法跳到最后一格,吃了毒蘑菇导致体力下降之后就更加跳不到了。
再考虑一下好蘑菇的情况,跳格子是需要消耗体力的,一旦跳到好蘑菇的格子上之后,体力值是一定上升的(无论如何j-i的体力消耗是不可避免的)。
所以只要考虑只往好蘑菇的格子里跳,体力变化为(m-(j-i)+n)
,判断中间过程的体力是否会小于等于0即可。
这么简单的题,我面试时候怎么就没做出来呢
//假设一开始的时候在-1的位置,最后要到达100的位置
//具体的题目意思还是要面试的时候问问面试官
public static int tian(int m,int[] nums){
int cur = m;
int last = -1;
for(int i=0;i<nums.length;i++){
if(nums[i] > 0){
cur+=nums[i]-(i-last);
if(cur<=0)
return -1;
last = i;
}
}
if(cur < nums.length-last)
return -1;
return cur-(nums.length-last);
}
这个故事告诉我们:面试的时候别紧张,先把题目看清楚,题目意思不明白就问问面试官。
说起来还不是面试官出完题就视频音频一关,搞得我很慌。
更新:已经灰了,果然是来随便面一下然后把我挂了,感谢腾讯给我的面试机会,过几年再来吧。
腾讯面试问题
- 扯了20多分钟项目
- TCP和UDP的区别,三次握手,SYN攻击,TIME_WAIT
- 进程和线程的区别,进程间通信
- 自己实现一个map
- 算法题
后记
腾讯我就知道我会挂,只是没想到还能有一次面试机会。相比较之前的面试,腾讯比较喜欢问网络相关的内容,一直以为自己准备的还不错结果TIME_WAIT在哪一端发生的都忘了,之后还是再好好看看。
雷火的测开面试居然有4轮,而且第4面的算法题还挺难的,我感觉字节也不过如此,我面的真的是测开?不过有一说一,最长公共子串的题目没有做出来不太应该,最后这种经典面试题还是需要多看看。
也不知道雷火面的怎么样,感觉面试官都是打个哈哈,先说你基础还不错,就是算法需要加强,然后反手把你挂了。
面试官的嘴,骗人的鬼,我太难了。