您的位置:首页 > 编程语言

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

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

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

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

顺便提一嘴,我目前使用的语言是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
9e91
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:第一次写技术类博客,各种经验不足,图片也不会插入,排版也不太熟,写了好久,不足之处还请指出,非常感谢,我自己之后也会把现在不足的地方改正。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  编程 校招 java