剑指Offer——携程笔试题+知识点总结
情景回顾
时间:2016.9.17 19:10-21:10
地点:山东省网络环境智能计算技术重点实验室
事件:携程笔试
总体来说,携程笔试内容与其它企业笔试题类型基本一致,主要分为智能题、选择题、编程题、附加题(编程题)。其实,附加题前面的题目难度还算可以,真正拉开差距的是附加题的编程题。自己当时没有通过附加题,结束后进行一小结。为后序笔试积累经验。
编程题
二分查找
package cn.edu.ujn.practice; import java.util.Scanner; public class XC_1 { /** * 二分查找 * * 题目描述: 请写一个二分查找算法查找一个数最先出现的index,如果数不在集合中需要返回(-1)-当前数应该出现的位置。 例如 [1,3,6],查找5,5应该是在index=2的位置但并不在集合中。返回(-1)-2 = -3。 输入 第一行读入一个整数x,表示要查找的数;第二行读入一个正整数n,表示待查找数组的元素个数;第三行读入n个递增整数,构成待查找的数组。 输出 整数x在数组中出现的索引位置(索引从0开始计数);如果不存在,返回(-1)-当前数应该出现的位置。 样例输入 3 5 0 1 3 5 6 样例输出 2 */ public static void main(String[] args) { Scanner in = new Scanner(System.in); // 待查找的数 int target = in.nextInt(); // 数组长度 int len = in.nextInt(); int [] arr = new int[len]; for(int i = 0; i < len; i++){ arr[i] = in.nextInt(); } System.out.println(resolution(target, arr, arr.length)); } private static int resolution(int target, int [] arr, int len){ if(arr == null || arr.length == 0) return 0; int er = 0; return binarySearchRecursion(arr, target, 0, len-1, er); } private static int binarySearchRecursion(int arry[],int value,int start,int end, int er) { if(start > end) return -1-er; int mid = start + (end-start)/2; if(arry[mid] == value) return mid; else if(value < arry[mid]) { end = mid - 1; er = mid; return binarySearchRecursion(arry,value,start,end, er); } else { start = mid + 1; er = mid+1; return binarySearchRecursion(arry,value,start,end, er); } } }
股票利润
package cn.edu.ujn.practice; import java.util.Scanner; import java.util.regex.Pattern; public class XC_2 { /** * 股票利润 * 题目描述: 假如一个数组中存储了一个股票在一天交易窗口内各时间点的股票价格(正整数)。 只允许一次买入和一次卖出,请提供一个算法,计算出通过卖出和买入可以得到的最大利润 输入 价格序列,用,号隔开 输出 最大的可能利润 样例输入 2,3,2,4 样例输出 2 * */ public static void main(String[] args) { Scanner in = new Scanner(System.in); Pattern pattern = Pattern.compile("[,]"); // 一天内的股票价格 while(in.hasNextLine()){ String str = in.nextLine(); String [] arr = pattern.split(str); int len = arr.length; int [] a = new int[len]; for(int i = 0; i < len; i++){ a[i] = Integer.parseInt(arr[i]); } System.out.println(resolution(a, len)); } } private static int resolution(int [] arr, int len){ if(arr == null || len == 0) return -1; int max = 0; for(int i = 0; i < len; i++){ for(int j = i; j < len; j++){ if((arr[j]-arr[i]) > max) max = arr[j]-arr[i]; } } return max; } }
遍历最短路径长度
package cn.edu.ujn.practice; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Scanner; import java.util.regex.Pattern; public class XC_3 { /** * 遍历最短路径长度 * 题目描述: 暴风降临的龙母丹妮莉丝·坦格利安要骑着她的龙以最快的速度游历各国,她的谋士们纷纷献策规划路线。 作为她的谋士之一和仰慕者的你,决定冒险穿越到21世纪借助计算机来寻求最优路线。 请设计一段程序,读取各国两两之间的距离,距离以邻接矩阵表示,并计算出遍历各国的最短路径长度。 输入 第一行:国家数量,假设为n 后续n行是国家间距离的邻接矩阵表示 输出 遍历各国的最短路径长度 样例输入 4 0,1,2,3 1,0,4,5 2,4,0,2 3,5,2,0 样例输出 5 思路: 组合 --> 最小值 TC: O(n!) SC: O(n) */ public static void main(String[] args) { Scanner in = new Scanner(System.in); Pattern pattern = Pattern.compile("[,]"); // 获取国家数 int lines = in.nextInt(); int [][] arr = new int [lines][lines]; // 缓冲输入--Key in.nextLine(); for(int i = 0; i < lines; i++){ int k = 0; String s = in.nextLine(); String [] str = pattern.split(s); int len = str.length; for(int j = 0; j < len; j++){ arr[i][k++] = Integer.parseInt(str[j]); } } /*for(int i = 0; i < arr.length; i++){ for(int j = 0; j < arr.length; j++){ System.out.print(arr[i][j] + " "); } System.out.println(" "); }*/ List<Integer> s = new ArrayList<Integer>(); List<Integer> rs = new ArrayList<Integer>(); for(int i = 0; i < lines; i++) s.add(i); ArrayList<Integer> list = new ArrayList<Integer>(); ArrayList<Integer> li = new ArrayList<Integer>(); li = pl(s, rs, arr, list); System.out.println(""); for(Integer c : li){ System.out.print(c + " "); } System.out.println(""); System.out.println("最短路径:" + Collections.min(li)); } private static ArrayList<Integer> pl(List<Integer> s,List<Integer> rs, int [][] arr, ArrayList<Integer> list){ int cost = 0; // 递归出口 if(s.size() == 1) { rs.add(s.get(0)); // System.out.println(rs.toString()); for(int i = 0; i < rs.size()-1; i++){ cost += arr[rs.get(i)][rs.get(i+1)]; } if(!list.contains(cost)){ list.add(cost); } System.out.print(cost + " "); rs.remove(rs.size()-1); }else{ for(int i = 0; i < s.size(); i++){ rs.add(s.get(i)); List<Integer> tmp = new ArrayList<Integer>(); for(Integer a:s) tmp.add(a); tmp.remove(i); pl(tmp, rs, arr, list); rs.remove(rs.size()-1); } } return list; } }
经验
赛码网、牛客网上的考试,编程题均可以本地编译,故相关代码应提前准备好,这就要求自己之前进行过大量的编程练习。待使用相关算法时,可以直接进行CV操作。其实编程最主要的还是思想。前2道编程题很容易想到,也很容易实现。甚至直接使用暴力解法也不会出现TO异常。相比于前两道题,第三题就要考察自己的编程思想功底了。 对于一些数组元素操作,要学会使用Java中的工具类,例如Collections工具类就很好用。经常会用到其sort()、reverse()、max()、min()、replaceAll()、frequency()、binarySearch()等方法。有关其详情请阅读博文《Java进阶(三十九)Java集合类的排序,查找,替换操作》。编程的第一大要义就是DTY(Don not repeat yourself),及不要重复造*。况且*质量无法保证.....
数据结构一定要吃透,不能遗漏任何知识点。