赞
踩
面试流程,大概如下:先是40分钟的笔试编程题,面试官给出3个编程题,让我现场进行编程,至少完成其中一道,无IDE,用的是视频对话的网页自带的检查器(貌似只能检查出基本类型拼写错误及补全括号等基础书写问题)。编程题目如下图
编程题时间到之后面试官会提醒(我太菜了,一题没做出来),问我要再继续做,还是讲下我的思路。我选择讲下我的思路(毕竟还差不少才能写出一题来QAQ),面试官听完我的思路后也没再说什么。
然后就是开始正式的面试,首先做个简短自我介绍,之后面试官让我简单介绍一下我的项目情况,再轻描淡写地问了我的团队项目的实现原理。再后来开始问我一些基础核心知识。
首先,问的是数组和链表的优缺点,这个我答的还可以,然后问我 Java 里面有哪些容器是用链表实现的,这个我没答上来。再来就是问了我 Java 里面的Map是怎样的结构,其查询效率又如何。之后又问了我排序算法都知道哪些(我说了冒泡、归并、快排、桶排序、基数排序等),再问了我这些算法时间复杂度比较低的是哪些(快排和归并),分别是多少(都是 nlogn ),再让我仔细讲一下快排是怎么实现的(我忘记了 orz ),再然后,问了我二叉搜索树是怎么样的数据结构(每个结点的值大于左子节点的值,小于或等于右子结点的值),二叉搜索树的查询效率是多少(这个我忘了 orz ,我懵了个 nlogn )。
再来就问了一下数据库的知识,问我学的什么数据库(MySQL),然后又问我引擎用的是什么(这个我也答不上 orz ,我甚至到没听过这个概念,后来听面试官说 InooDB ,我才想起一点)。然后让我讲一下什么是ACID属性(我答得踉踉跄跄,并不好, orz ),然后举例问我,假如数据库里存有某商品的库存,现在查询到这个数据,并执行减一的操作,这整个操作过程有什么问题吗?(我答得不是太好,大概说了一下事务的一致性原理)面试官又问我怎么解决这个问题(我回答加锁),面试官继续追问,怎么加锁,技术上具体如何实现(我就被问倒了,后来面试官说直接加线程锁是不行,因为它不是内存里的东西,我后知后觉才明白是数据库的存储过程,果然我数据库还菜比 orz )。
大概整个面试过程就这么多,后面面试官提问结束后,会询问我还有什么问题,我就再跟面试官简单聊了几句(毕竟太菜了,没脸接着聊了),然后就结束了。整个过程大概85分钟左右。
第一道笔试题应该采用动态规划来解决比较合适。
设 d [ i ] [ j ] d[i][j] d[i][j]为使用 arr 中(arr已按从小到大的顺序排列)前 i 种零钱,找的零钱为 j 的组合方式的种数。
则 d [ i ] [ j ] = ∑ k = 0 j / d [ i ] d [ i − 1 ] [ j − k ∗ d [ i ] ] d[i][j] = \sum_{k=0}^{j/d[i]} d[i-1][j-k*d[i]] d[i][j]=k=0∑j/d[i]d[i−1][j−k∗d[i]],即第 i 种有以下选择:可以不用、可以用1个、可以用2个、…、可以用 j / d[ i ] 个。
初始化则为: d [ i ] [ 0 ] = 1 ; d [ 0 ] [ j ] = 0 ; d[i][0] = 1; d[0][j] = 0; d[i][0]=1;d[0][j]=0; 即 凑成0元只有一种方法,也就是不用任何一种零钱;用前0种零钱凑成 j( j ≠ 0) 元的方法,为0种,因为前0种零钱即没有零钱。
public static void dynamic_prommgram(int[] arr,int n){ int[][] d = new int[arr.length+1][n+1];//length+1表示不适用任何币种、只使用1、只使用1 2 只使用1 2 3......等等,共length+1种情况,且n+1表示总计0、1.....至n元共n+1种情况 for(int i = 0;i<=arr.length;i++) d[i][0] = 1; for(int i = 1 ;i<=arr.length;i++){ //因为d[0][i]是0,所以i从1开始 for(int j = 1;j<=n;j++){ //由于d[i][0]==1,所以j从1开始 for(int k=0;k<=j/arr[i-1];k++){ //例如,使用面值为1时,对应的coins[]下标是i-1,逻辑上和实际上不是一致的 d[i][j] +=d[i-1][j-k*arr[i-1]]; } } } System.out.println(d[arr.length][n]); }
再将这段代码中的二元数组简化为一元数组即可。
public int solution(int[] arr, int n){
int[] d = new int[n+1];
d[0] = 1;
for (int i = 0; i < arr.length ;i++) {
for (int j = arr[i]; j <= n; j++) {
d[j] += d[j - arr[i]];
}
}
int result = d[n];
return result;
}
第二道题是股票最大利润问题。
首先是只买一次的情况。
只要记录前面的最小价格,将这个最小价格作为买入价格,然后将当前的价格作为出售价格,查看当前收益是不是最大利益。
public int solution(int[] prices){
if (prices.length == 0)
return 0;
int min = prices[0];
int max = 0;
for (int i = 1; i < prices.length; i++) {
if (prices[i] < min)
min = prices[i];
else
max = Math.max(max, prices[i] - min);
}
return max;
}
然后是在日期不重叠的情况下卖买多次的最大利润。
对于prices[ i ] > prices[ i-1 ], 那么就可以进行一次卖买,即把prices[ i ] - prices[ i-1 ] 加入到收益当中,因为我们可以昨天买入,今天卖出,若明天价更高的话,还可以今天买入,明天卖出。以此类推,遍历完整个数组后即可求得最大利润。
public int solution2(int[] prices){
int profit = 0;
for (int i = 1; i < prices.length; i++) {
if (prices[i] - prices[i-1] > 0)
profit += prices[i] - prices[i-1];
}
return profit;
}
第三道题是36进制求和。
这道题相对来说简单点,可以考虑将‘0’ - ‘9’,‘a’ - ‘z’存储到List中,index是0-35为其对应的数字。定义一个StringBuilder,将每一位的计算 结果利用append方法加入其中,最后再用reverse方法倒转过来即可,注意最后要先检查进位temp是否为0,如果不为0,则需要再append字符‘1’,再倒转。
import java.util.Arrays; import java.util.List; public class Main { static Character[] nums = { '0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'}; static List<Character> list = Arrays.asList(nums); public String solution(String num_a,String num_b){ String result = new String(); char[] n1 = num_a.toCharArray(); char[] n2 = num_b.toCharArray(); int i = num_a.length()-1; int j = num_b.length()-1; int temp = 0; StringBuilder stringBuilder = new StringBuilder(); while(i >= 0 || j >=0){ if (i >=0 && j >= 0){ char c1 = n1[i]; char c2 = n2[j]; int index1 = list.indexOf(c1); int index2 = list.indexOf(c2); int sum = index1 +index2 + temp; if (
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。