女友校招笔试编程题:网易测试岗-买苹果和求最大奇约数

来源:互联网 发布:mac py终端指的是什么 编辑:程序博客网 时间:2024/04/30 09:30

嗯,这算是人生中第一次正式写博客吧。以前一直将笔记记录到网络笔记本上,自己没事的时候会翻翻笔记回顾总结一下自己。

但是前段时间在某个场合提到了“技术需要分享”,嗯,是的,技术需要分享,想来自己也看不少大牛的技术博客,大牛一般都是非常乐于分享自己的技术的!作为一个小菜鸟,我也要像技术大神们学习,分享菜鸡的技术成长历程。一是希望通过自己的分享尽量能够帮助到一些人,同时希望在这个过程中能够提升自己的语言组织与逻辑表达能力。

文章中肯定会有或大或小的错误,希望读到我文章的朋友能够在评论里及时指明,我会第一时间给改正!以前比较少写正规的文章,做笔记的时候比较随意,格式排版配图什么的可能刚开始不太好,但凡事总有开始,肯定会越来越好的。

顺便提一嘴,我目前使用的语言是Java。

好了,不瞎BB了,分享技术,享受技术!go~


女友最近在找工作,参加各种公司的校招,每次笔试完后都会和我分享其中的一些题目,中秋放假做一个算是阶段性总结的总结吧!

第一题:

[编程题] 买苹果
时间限制:c/c++,1s,其他语言3s
空间限制:32768K,其他语言忘记了...
题目描述:
小易去附近的商店买苹果,奸诈的商贩使用了捆绑交易,只提供6个每袋和8个每袋的包装(包装不可拆分)。
可是小易现在只想购买恰好n个苹果,小易想购买尽量少的袋数方便携带。

如果不能购买恰好n个苹果,小易将不会购买。
输入描述:
输入一个整数n,表示小易想购买n(1 ≤ n ≤ 100)个苹果
输出描述:
输出一个整数表示最少需要购买的袋数,如果不能买恰好n个苹果则输出-1
输入样例:
20
输出样例:
3


解析:这道题不难,就是考察2元一次方程的最值问题,中学生都会.....

设,容量为6的袋子数量为a,容量为8的袋子的数量为b,使用的袋子总数为x,则以上问题可由如下方程组表示:(请忽略很丑的字体,重点是内容)


然后,用b表示a,经过一些运算可以得到如下结果:(请忽略很丑的字体,重点是内容)


再然后,需要注意的是,因为是要求x的最小值,所以当b最大时,x最小,所以实现时需要注意一下,b从最大的可选值开始取就可以了。

然后根据上面的思路就可以进行代码实现啦!具体代码如下:

import java.util.Scanner;public class wangyi1 {public static void main(String[] args) {Scanner scan = new Scanner(System.in);while (scan.hasNext()) {int n = scan.nextInt();System.out.println(getSum(n));}}public static int getSum(int n) {int sum = -1;int a = 0;int b = 0;int m = n / 8;for (int i = m; i >= 0; i--) {if ((n - 8 * i) % 6 == 0) {b = (n - 8 * i) / 6;a = i;sum = a + b;break;}}return sum;}}

第二题:

[编程题|20分] 最大的奇约数
时间限制:c/c++,1s,其他语言3s
空间限制:32768K,其他语言忘记了...

题目描述:
大的奇约数
小易是一个数论爱好者,并且对于一个数的奇数约数十分感兴趣。一天小易遇到这样一个问题:
定义函数 f(x) 为 x 最大的奇数约数,x为正整数。 例如:f(44) = 11.
现在给出一个N,需要求出 f(1) + f(2) + f(3)…….f(N)
例如: N = 7
f(1) + f(2) + f(3) + f(4) + f(5) + f(6) + f(7) = 1 + 1 + 3 + 1 + 5 + 3 + 7 = 21
小易计算这个问题遇到了困难,需要你来设计一个算法帮助他。

输入描述:
输入一个整数N (1 ≤ N ≤ 1000000000)
输出描述:
输出一个整数,即为f(1) + f(2) + f(3)…….f(N)
输入样例:
7
输出样例:

21

解析:这道题的解题过程也是充满了艰辛......

当时的解题过程是这样的:

首先,先对n以内的所有奇数直接用公式求和。

其次,就考虑偶数的情况,偶数分两种:2的n次幂的数和非2的n次幂的数。设这个偶数为a,对a进行开方,这个开方的结果也分两种:整数和浮点数。如果开方的结果是整数,则判断是奇数还是偶数,如果是奇数则返回,如果是偶数则对Math.sqrt(a)递归这个操作。如果开方的结果是浮点数,则对a / 2递归这个操作。这样就可以得出结果。下面是实现的代码。下面的图是当时的推导过程,有些乱,大家可以自己拿草纸推导一下。

import java.util.Scanner;/** * 方法1:时间复杂度并不高,但是耗时过长(开方运算耗时长) *  * @author Administrator *  */public class wangyi2_a {public static void main(String[] args) {Scanner scan = new Scanner(System.in);while (scan.hasNext()) {int n = scan.nextInt();// long t1 = System.currentTimeMillis();System.out.println(getsum(n));// long t2 = System.currentTimeMillis();// System.out.println("total time=" + (t2 - t1));// System.out.println("sqrt time=" + sqrtTime);}}// static int sqrtTime = 0;static int f(int x) {if ((x & 1) == 1) {return x;}// long t1 = System.currentTimeMillis();// 经测试,开方运算过于耗时double sqrt = Math.sqrt(x);int k = (int) Math.floor(sqrt);int up = (int) Math.ceil(sqrt);// long t2 = System.currentTimeMillis();// long t3 = t2 - t1;// sqrtTime += t3;if ((k & 1) == 1) {return k;} else {if (k == up)return f(k);else {return f(x >> 1);}}}static int getsum(int n) {int m = 0;int maxj = 0;int t = 0;if ((n & 1) == 0) {m = n >> 1;maxj = n - 1;t = n;} else {m = n >> 1 + 1;maxj = n;t = n - 1;}int sum = (1 + maxj) * (m >> 2);for (int i = 2; i <= t; i = i + 2) {sum += f(i);}return sum;}}

是的,正如上面的代码中注释的那样,提交之后,结果超时了......代码的循环次数其实并不多的,但是“时间复杂度”这个东西嘛,也是要考虑某个操作的耗时情况的。正如上面代码中的注释那样,Math.sqrt()方法是很耗时的,读者朋友们可以自己打开注释去看看,开方运算占用了大部分的运算时间。既然这样都不行,那只有一种可能,这个东西真的是有公式或者说规律的。好那现在就来分析怎么找规律......

设sum(i) = f(1) + f(2) + ... + f(i);
求sum(i)的过程中,对于f(i), i 为奇数可以直接求,就是 i 本身。
问题就是求所有f(i), i为偶数的和。
因为要求的是最大奇约数,

所以f(2k) = f(k) + 1 + 3 + ... + 2k - 1  ,

所以f(2) + f(4) + ... + f(2k) = f(1) + f(2) + ... + f(k)  + 1 + 3 + ... + 2k - 1  
所以
当i 为偶数时,sum(i) =  sum (i / 2) + 1 + 3 + ... + i - 1 
当i 为奇数时,sum(i) =  sum (i - 1) +  i

所以,根据这个思想,代码如下:

import java.util.Scanner;/** * 方法2:动态规划方法 *  * @author Administrator *  */public class wangyi2_b {public static void main(String[] args) {Scanner scan = new Scanner(System.in);while (scan.hasNext()) {int n = scan.nextInt();System.out.println(getsum(n));}}static int getsum(int n) {if (n == 1) {return 1;}if (n % 2 == 0) {return getsum(n / 2) + n * n / 4;} else {return getsum(n - 1) + n;}}}

这样,终于完成了这道题。

ps:第一次写技术类博客,各种经验不足,图片也不会插入,排版也不太熟,写了好久,不足之处还请指出,非常感谢,我自己之后也会把现在不足的地方改正。



2 0