美团网2015校招研发笔试题(2014-9-11,哈尔滨哈工大站)

来源路径:http://blog.csdn.net/zheng0518/article/details/39211909


2、用O(n)的算法,实现对一组无序的字母进行从小到大排序(区分大小写),相同的字母,小写在大写前

思路:空间换时间,把52个字母映射为52个数字,并记录出现的次数,然后迭代输出


[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. public static void main(String[] args) {  
  2.         // A=65,Z=90 a=97,z=122  
  3.         char[] src = { 'R''B''B''b''W''W''B''R''B''w' };  
  4.         src = sortCharsOn(src);  
  5.         for (char c : src) {  
  6.             System.out.print(c + " ");  
  7.         }  
  8.     }  
  9.   
  10.     /** 
  11.      * O(n)的时间复杂度对给定的字符数组进行排序 
  12.      *  
  13.      * @param src 
  14.      *            原数组 
  15.      * @return 排序后的数组 
  16.      */  
  17.     private static char[] sortCharsOn(char[] src) {  
  18.         int[] items = new int[54];// 用于保存52个字符  
  19.         char[] des = new char[src.length];  
  20.   
  21.         for (int i = 0; i < src.length; i++) {  
  22.             if (src[i] < 'z' && src[i] > 'a') { // 小写对应于items中下标为偶数  
  23.                 items[(src[i] - 'a') * 2]++;  
  24.             } else if (src[i] < 'Z' && src[i] > 'A') { // 大写对应于items中下标为奇数  
  25.                 items[(src[i] - 'A') * 2 + 1]++;  
  26.             }  
  27.         }  
  28.   
  29.         int index = 0;  
  30.         for (int i = 0; i < items.length; i++) {  
  31.             if (items[i] != 0) {// items[i],就是该字符出现的次数  
  32.                 if (i % 2 == 0) {  
  33.                     for (int j = 0; j < items[i]; j++) {  
  34.                         des[index++] = (char) (i / 2 + 'a');// 转化成小写  
  35.                     }  
  36.                 } else {  
  37.                     for (int j = 0; j < items[i]; j++) {  
  38.                         des[index++] = (char) ((i - 1) / 2 + 'A');// 转化成大写  
  39.                     }  
  40.                 }  
  41.             }  
  42.         }  
  43.         return des;  
  44.     }  


3、给定N个磁盘,每个磁盘大小为D[i],i=0...N-1,现在要在这N个磁盘上"顺序分配"M个分区,每个分区大小为P[j],
 j=0....M-1,顺序分配的意思是:分配一个分区P[j]时,如果当前磁盘剩余空间足够,则在当前磁盘分配;如果不够,则
  尝试下一个磁盘,直到找到一个磁盘D[i+k]可以容纳该分区,分配下一个分区P[j+1]时,则从当前磁盘D[i+k]的剩余
  空间开始分配,不在使用D[i+k]之前磁盘末分配的空间,如果这M个分区不能在这N个磁盘完全分配,则认为分配失败,请
  实现函数,is_allocable判断给定N个磁盘(数组D)和M个分区(数组P),是否会出现分配失败的情况。
  举例:磁盘为[120,120,120],分区为[60,60,80,20,80]可分配 ,如果为[60,80,80,20,80]则分配失败


[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. public static void main(String[] args) {  
  2.         int[] d = { 120120120 };// 磁盘  
  3. //      int[] p = { 60, 60, 80, 20, 80 };// 分区  
  4.         int[] p = { 6080802080 };// 分区  
  5.   
  6.         if (is_allocable(d, p)) {  
  7.             System.out.println("分配成功");  
  8.         } else {  
  9.             System.out.println("分配失败");  
  10.         }  
  11.     }  
  12.   
  13.     private static boolean is_allocable(int[] d, int[] p) {  
  14.         int pindex = 0;//记录已分配的分区  
  15.         boolean isAllocable = false;//用来记录是否分配成功  
  16.         for (int i = 0; i < d.length; i++) {//对所有磁盘遍历  
  17.             while (d[i] > 0) {//如果该磁盘还有剩余空间,就一直迭代  
  18.                 if (p[pindex] <= d[i]) {//如果磁盘空间足够,就分配,否则,进入下一个磁盘  
  19.                     d[i] -= p[pindex++];  
  20.                     if (pindex == p.length) {//如果已分配的分区数跟传入的一值,意味着分配成功  
  21.                         isAllocable = true;  
  22.                         break;  
  23.                     }  
  24.                 } else {  
  25.                     break;  
  26.                 }  
  27.             }  
  28.             if (isAllocable) {  
  29.                 break;  
  30.             }  
  31.         }  
  32.         return isAllocable;  
  33.     }  


4、给定正整数X,定义函数A(n)=1+x+x^2+x^3+...+x^n(n为整数且>=0),已知乘运算的时间远大于加运算,
 输入x,n:如何尽可能快的求出A(n)

这题应该有更好的解决方法吧。。

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. public static void main(String[] args) {  
  2.         Scanner s = new Scanner(System.in);  
  3.         int x = s.nextInt();  
  4.         int n = s.nextInt();  
  5.   
  6.         long temp = x+1;  
  7.         for(int i=0;i<n-1;i++){  
  8.             temp = temp*x+1;  
  9.         }  
  10.         System.out.println(temp);  
  11.     }  

5、请实现方法:print_rotate_matrix(int matrix,int n),来将一个n X n二维数组
 * 逆时针旋转45度后打印,例如,下图显示一个3X3的二维数组及其旋转后屏幕输出的效果
 * <br/>
 * 123 旋转45度          3                                 3
 * 456------>           2 6       屏幕输出         2 6
 * 789                       1 5 9       ----->               1 5 9
 *            4 8                                  4 8
 *                                  7                                    7
 * 
 * 思路:从右上角开始打印....

3
26
159
48
7


[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. public static void main(String[] args) {  
  2.         Scanner s = new Scanner(System.in);  
  3.         System.out.println("请输入几维数组:");  
  4.         int n = s.nextInt();  
  5.         int [][]matrix = new int[n][n];  
  6.         for(int i=0;i<n;i++){  
  7.             for(int j=0;j<n;j++){  
  8.                 matrix[i][j]=i*n+(j+1);  
  9.             }  
  10.         }  
  11.         print_rotate_matrix(matrix,n);  
  12.     }  
  13.   
  14.     private static void print_rotate_matrix(int[][] matrix, int n) {  
  15.         //a[0][2]  
  16.         //a[0][1] a[1][2]  
  17.         //a[0][0] a[1][1] a[2][2]  
  18.         //a[1][0] a[2][1]  
  19.         //a[2][0]  
  20.         int f,s;//第一维,第二维坐标  
  21.         for(int i=n-1;i>=0;i--){//打印上半部分  
  22.             f=0;  
  23.             s=i;  
  24.             while(s<n){  
  25.                 System.out.print(matrix[f++][s++]);  
  26.             }  
  27.             System.out.println();  
  28.         }  
  29.           
  30.         for(int i=1;i<n;i++){//打印下半部分  
  31.             f=i;  
  32.             s=0;  
  33.             while(f<n){  
  34.                 System.out.print(matrix[f++][s++]);  
  35.             }  
  36.             System.out.println();  
  37.         }  
  38.     }  


6、已知队列支持先进先出的操作(add/remove),而栈则直技先进后出的操作push/pop,请用两个队列实现栈
 先进后出的操作,希望该栈的push/pop时间复杂度尽量小。
  
  请写出push/pop的代码,需要考虑栈溢出(stackoverflow)的情况
  
  思路:顺序不一样,队列1接收的数据,由队列2来反转顺序。队列1只进,队列2只出


[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. public class MyStack<T> {  
  2.   
  3.     Queue<T> q1, q2;  
  4.   
  5.     public MyStack() {  
  6.         q1 = new LinkedBlockingQueue<T>();  
  7.         q2 = new LinkedBlockingQueue<T>();  
  8.     }  
  9.   
  10.     public void push(T value) {  
  11.         q1.add(value);  
  12.     }  
  13.   
  14.     public T pop() {  
  15.         if(!q2.isEmpty())  
  16.             return q2.poll();  
  17.         while(!q1.isEmpty())  
  18.             q2.add(q1.poll());  
  19.         return q2.poll();  
  20.     }  
  21.   
  22. }  

举一反三,由两个栈实现队列:

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. public class MyQueue<E> {  
  2.   
  3.     private Stack<E> s1, s2;  
  4.   
  5.     public MyQueue() {  
  6.         s1 = new Stack<E>();  
  7.         s2 = new Stack<E>();  
  8.     }  
  9.   
  10.     public int size() {  
  11.         return s1.size() + s2.size();  
  12.     }  
  13.   
  14.     public void add(E value) {  
  15.         s1.push(value);  
  16.     }  
  17.   
  18.     public E peek() {  
  19.         if (!s2.empty())  
  20.             s2.peek();  
  21.         while (!s1.empty())  
  22.             s2.push(s1.pop());  
  23.         return s2.peek();  
  24.     }  
  25.   
  26.     public E remove() {  
  27.         if (!s2.empty())  
  28.             s2.pop();  
  29.         while (!s1.empty())  
  30.             s2.push(s1.pop());  
  31.         return null;  
  32.     }  
  33.   
  34. }  




7、假设有一个中央调度机,有n个相同的任务需要调度到m台服务器上去执行,由于每台服务器的配置不一样,因此服务器
 执行一个任务所花费的时间也不同。现在假设第i个服务器执行一个任务所花费的时间也不同。现在假设第i个服务器执行 一个任务需要的时间为t[i].
 例如:有2个执行机a,b,执行一个任务分别需要7min,10min,有6个任务待调度。如果平分这6个任务,即a,b各3个
 任务,则最短需要30min执行完所有。如果a分4个任务 ,b分2个任务,则最短28min执行完。 请设计调度算法,使得所有任务完成所需要的时间最短。
 输入m台服务器,每台机器处理一个任务的时间为t[i],完成n个任务,输出n个任务在m台服务器的分布。 int
 estimate_process_time(int[] t,int m,int n)


思路:用一个数组记录每台机器已执行的时间(初始为0),在调度每一个任务的时候,对每一台机器需要执行的时间进行对比(已执行的时间加上需要执行该任务的时间


[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. public static void main(String[] args) {  
  2.         Scanner s = new Scanner(System.in);  
  3.         int t[] = new int[100];  
  4.         System.out.println("请输入几台机子:");  
  5.         int m = s.nextInt();  
  6.         int i = 0;  
  7.         System.out.println("输入每台机子的时间:");  
  8.         while (m-- > 0) {  
  9.             t[i++] = s.nextInt();  
  10.         }  
  11.         System.out.println("请输入多少任务:");  
  12.         int n = s.nextInt();  
  13.         int total = estimate_process_time(t, i, n);  
  14.         System.out.println("最小需要" + total);  
  15.     }  
  16.   
  17.     /** 
  18.      * @param t 每个服务器处理的时间 
  19.      * @param m 多少台服务器 
  20.      * @param n 多少个任务 
  21.      * @return 
  22.      */  
  23.     private static int estimate_process_time(int[] t, int m, int n) {  
  24.         int total = 0;  
  25.         int k;  
  26.         int apply[] = new int[m];// 记录m个机器已执行的时间,初始全为0  
  27.         for (int i = 0; i < n; i++) {// 遍历n个任务  
  28.             int tmp = apply[0] + t[0];//用来记录分配该任务给第j个机器所需要的时间(已执行的时间加需要执行的时间)  
  29.             k = 0;  
  30.             for (int j = 1; j < m; j++) {// 遍历m个机器  
  31.                 if (tmp > apply[j] + t[j]) {//遍历所有机器,选择时间最短的  
  32.                     tmp = apply[j] + t[j];  
  33.                     k = j;// 把该任务分配给第j个机器  
  34.                 }  
  35.             }  
  36.             apply[k] += t[k];  
  37.             total = tmp;  
  38.         }  
  39.         for (int i = 0; i < m; i++) {  
  40.             System.out.println("第"+(i+1)+"台服务器有"+apply[i]/t[i]+"个任务,运行了"+apply[i]);  
  41.         }  
  42.         return total;  
  43.     }  



8、n(1,2,3.....n)个元素有N!个不同的排列,将这n!个数按字典序排列,并编号0,1...n!-1,每个排号为其字典序的值,如n=3时,字典排序为123,132,213,231,312,321,这6个数的字典序分别为0,1,2,3,4,5.,现给定n,请输出字典序为k 的排列(0<=k<n!)

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. public static void main(String[] args) {  
  2.         long l1 = System.currentTimeMillis();  
  3.         System.out.println("请输入要对前n个数字进行排列:");  
  4.         Scanner s = new Scanner(System.in);  
  5.         int n = s.nextInt();  
  6.         System.out.println("请输入需要的第K个:");  
  7.         int k = s.nextInt();  
  8.         int[] arry = new int[n];  
  9.         for (int i = 0; i < arry.length; i++) {  
  10.             arry[i] = i + 1;  
  11.         }  
  12. //      System.out.println(Arrays.toString(getInt(arry)));  
  13.         do {  
  14.             if (k == 0){  
  15.                 System.out.println(Arrays.toString(getInt(arry)));  
  16.                 break;  
  17.             }  
  18.             k--;  
  19.         } while (next(arry));  
  20.         long l2 = System.currentTimeMillis();  
  21.         System.out.print("共耗时" + (l2 - l1) + "耗秒");  
  22.     }  
  23.   
  24.     private static int[] getInt(int[] arry) {  
  25.         int[] arry1 = new int[arry.length];  
  26.         System.arraycopy(arry, 0, arry1, 0, arry.length);  
  27.         return arry1;  
  28.     }  
  29.   
  30.     private static boolean next(int[] arry) {  
  31.         int pos1 = -1;  
  32.         int pos2 = -1;  
  33.         // 从右到左,找到第一个比右边小的数,记录位置pos1  
  34.         for (int i = arry.length - 1; i > 0; i--) {  
  35.             if (arry[i - 1] < arry[i]) {  
  36.                 pos1 = i - 1;  
  37.                 break;  
  38.             }  
  39.         }  
  40.         if (pos1 < 0) {  
  41.             return false;  
  42.         }  
  43.         // 在pos1位置后的数字中找出比它大的数中最小的一个,然后交换位置,在逆转  
  44.         for (int i = arry.length - 1; i > pos1; i--) {  
  45.             if (arry[i] > arry[pos1]) {  
  46.                 pos2 = i;  
  47.                 swap(arry, pos2, pos1);  
  48.                 reserve(arry, pos1 + 1, arry.length - 1);  
  49.                 break;  
  50.             }  
  51.         }  
  52.         if (pos2 < 0) {  
  53.             return false;  
  54.         }  
  55.         return true;  
  56.     }  
  57.   
  58.     /** 
  59.      *  
  60.      * 逆转数组中第i个到第j个的数,比如数组为123,i=0,j=2,则逆转为321 
  61.      *  
  62.      * @param arry 
  63.      * @param i 
  64.      * @param j 
  65.      */  
  66.     private static void reserve(int[] arry, int i, int j) {  
  67.         for (; i <= j; i++, j--) {  
  68.             swap(arry, i, j);  
  69.         }  
  70.     }  
  71.   
  72.     /** 
  73.      * 交换一个数组中第i个和第j个数的值 
  74.      *  
  75.      * @param array 
  76.      * @param i 
  77.      * @param j 
  78.      */  
  79.     private static void swap(int[] array, int i, int j) {  
  80.         int temp = array[j];  
  81.         array[j] = array[i];  
  82.         array[i] = temp;  
  83.     }  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值