百度2017春招笔试真题编程题集合
买帽子 数据结构
度度熊想去商场买一顶帽子,商场里有N顶帽子,有些帽子的价格可能相同。度度熊想买一顶价格第三便宜的帽子,问第三便宜的帽子价格是多少?
输入描述:
首先输入一个正整数N(N <= 50),接下来输入N个数表示每顶帽子的价格(价格均是正整数,且小于等于1000)
输出描述:
如果存在第三便宜的帽子,请输出这个价格是多少,否则输出-1
输入例子1:
10
10 10 10 10 20 20 30 30 40 40
输出例子1:
30
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.StreamTokenizer;
import java.util.TreeSet;
/**
* 思路:利用数据结构,找出第三大的数即可
*/
public class Main {
public static void main(String[] args) throws IOException {
StreamTokenizer in = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));
int inputCount;
Integer result;
TreeSet set = new TreeSet();
while (in.nextToken() != StreamTokenizer.TT_EOF) {
inputCount = (int) in.nval;
while (inputCount-- != 0) {
in.nextToken();
set.add((int) in.nval);
}
set.pollFirst();
set.pollFirst();
result = set.pollFirst();
out.println(result == null ? -1 : result);
}
out.flush();
}
}
度度熊回家 贪心
一个数轴上共有N个点,第一个点的坐标是度度熊现在位置,第N-1个点是度度熊的家。现在他需要依次的从0号坐标走到N-1号坐标。
但是除了0号坐标和N-1号坐标,他可以在其余的N-2个坐标中选出一个点,并直接将这个点忽略掉,问度度熊回家至少走多少距离?
输入描述:
输入一个正整数N, N <= 50。
接下来N个整数表示坐标,正数表示X轴的正方向,负数表示X轴的负方向。绝对值小于等于100
输出描述:
输出一个整数表示度度熊最少需要走的距离。
输入例子:
4
1 4 -1 3
输出例子:
4
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.StreamTokenizer;
/**
* 贪心思想
*
* 问:忽略一个点,回家至少多少距离(至少多少距离 = 总距离 - 最大缩短距离)?
* 缩短距离 = 三点之间的间隔和 - 忽略中间点之后的间隔和
*
* 答:忽略一个点之后,总距离必须是缩短的最多。
*/
public class Main {
public static void main(String[] args) throws IOException {
StreamTokenizer in = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));
int inputN;
int arr[] = new int[55];
while (in.nextToken() != StreamTokenizer.TT_EOF) {
inputN = (int) in.nval;
for (int index = 0; index < inputN; index++) {
in.nextToken();
arr[index] = (int) in.nval;
}
int sum = Math.abs(arr[inputN - 1] - arr[inputN - 2]);
// 最大的缩短距离
int maxReduceLength = 0;
for (int index = 1; index < inputN - 1; index++) {
// 求各两点之间距离之和
sum += Math.abs(arr[index] - arr[index - 1]);
// 求出三点之间,若忽略中间的点,计算出缩短距离
int temp = Math.abs(arr[index] - arr[index - 1]) + Math.abs(arr[index + 1] - arr[index]) - Math.abs(arr[index + 1] - arr[index - 1]);
// 记录最大的缩短距离是多少
maxReduceLength = maxReduceLength > temp ? maxReduceLength : temp;
}
// 至少需要走的距离 = 总距离 - 最大缩短距离
out.println(sum - maxReduceLength);
}
out.flush();
}
}
寻找三角形 暴力
三维空间中有N个点,每个点可能是三种颜色的其中之一,三种颜色分别是红绿蓝,分别用'R', 'G', 'B'表示。
现在要找出三个点,并组成一个三角形,使得这个三角形的面积最大。
但是三角形必须满足:三个点的颜色要么全部相同,要么全部不同。
输入描述:
首先输入一个正整数N三维坐标系内的点的个数.(N <= 50)
接下来N行,每一行输入 c x y z,c为'R', 'G', 'B' 的其中一个。x,y,z是该点的坐标。(坐标均是0到999之间的整数)
输出描述:
输出一个数表示最大的三角形面积,保留5位小数。
输入例子:
5
R 0 0 0
R 0 4 0
R 0 0 3
G 92 14 7
G 12 16 8
输出例子:
6.00000
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.util.Scanner;
/**
* 思路:暴力遍历所有的点,看其是否匹配条件,然后再利用海伦公式计算其面积
*/
public class Main {
static class Point {
// 注意:此处最好设为 private,并使用 set & get
String color;
Integer x;
Integer y;
Integer z;
}
private static boolean isMatch(String color1, String color2, String color3) {
if (color1.equals(color2) && color1.equals(color3) || !color1.equals(color2) && !color1.equals(color3) && !color2.equals(color3)) {
return true;
}
return false;
}
/**
* 海伦公式求面积:s = sqrt(p* (p-a) * (p-b) * (p-c)) 其中 p=(a+b+c) / 2
*/
private static double heron(Point pointA, Point pointB, Point pointC) {
double a = distance(pointA, pointB);
double b = distance(pointA, pointC);
double c = distance(pointB, pointC);
double p = (a + b + c) / 2;
return Math.sqrt(p * (p - a) * (p - b) * (p - c));
}
private static double distance(Point pointA, Point pointB) {
return Math.sqrt((pointA.x - pointB.x) * (pointA.x - pointB.x) + (pointA.y - pointB.y) * (pointA.y - pointB.y) + (pointA.z - pointB.z) * (pointA.z - pointB.z));
}
public static void main(String[] args) throws IOException {
Scanner in = new Scanner(new BufferedReader(new InputStreamReader(System.in)));
PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));
int inputN;
Point[] points = new Point[55];
double result;
while (in.hasNext()) {
inputN = in.nextInt();
result = 0;
for (int index = 0; index < inputN; index++) {
points[index] = new Point();
points[index].color = in.next();
points[index].x = in.nextInt();
points[index].y = in.nextInt();
points[index].z = in.nextInt();
}
for (int indexI = 0; indexI < inputN - 2; indexI++) {
for (int indexJ = indexI + 1; indexJ < inputN - 1; indexJ++) {
for (int indexK = indexJ + 1; indexK < inputN; indexK++) {
if (isMatch(points[indexI].color, points[indexJ].color, points[indexK].color)) {
double temp = heron(points[indexI], points[indexJ], points[indexK]);
if (result < temp) {
result = temp;
}
}
}
}
}
out.printf("%.5f",result);
out.println();
}
out.flush();
}
}
有趣的排序 贪心 逆向思维
度度熊有一个N个数的数组,他想将数组从大到小排好序,但是萌萌的度度熊只会下面这个操作:
任取数组中的一个数然后将它放置在数组的最后一个位置。
问最少操作多少次可以使得数组从小到大有序?
度度熊有一个N个数的数组,他想将数组从大到小排好序,但是萌萌的度度熊只会下面这个操作:
任取数组中的一个数然后将它放置在数组的最后一个位置。
问最少操作多少次可以使得数组从小到大有序?
输入描述:
首先输入一个正整数N,接下来的一行输入N个整数。(N <= 50, 每个数的绝对值小于等于1000)
输出描述:
输出一个整数表示最少的操作次数。
输入例子:
4
19 7 8 25
输出例子:
2
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.StreamTokenizer;
import java.util.Arrays;
/**
* 贪心思路 + 逆向思维
*
* 贪心的思路:移动的方式,选择最优的思路,那么移动的次数肯定是最少的。
*
* 最优的思路:对于数组中的第 i 个元素,如果它后面有比它小的元素,这就说明第 i 个元素理应被移动到末尾去。
* 另外,应该优先移动较小的元素,这样才能够保证较小元素最后排在最前面。
*
* 步骤:①、用一个备份数组 b,把 a 中元素放到b中,对 b 数组进行排序。
* ②、用备份数组 b 中(排好序的)第 j 个依次与原数组 a (输入顺序)中的第 i++ 个元素比较
* i、若 a[i] == b[j],则 count++;j++
* ③、统计出一共有 count 个,这些元素是不需要移动的元素,一共有 n 个元素,所以需要移动 n - count 次
*
* 伪代码:
* b = copy a
* sort b
* for i = 0 to n & j < n do
* if a[i] == b[j] then
* j++;
* count++;
* endif
* end
*/
public class Main {
public static void main(String[] args) throws IOException {
StreamTokenizer in = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));
int inputN;
int[] arr = new int[55];
int[] aux = new int[55];
while (in.nextToken() != StreamTokenizer.TT_EOF) {
inputN = (int) in.nval;
for (int index = 0; index < inputN; index++) {
in.nextToken();
arr[index] = (int) in.nval;
aux[index] = arr[index];
}
Arrays.sort(arr, 0, inputN);
int indexJ = 0;
int count = 0;
for (int indexI = 0; indexI < inputN && indexJ < inputN; indexI++) {
if (aux[indexI] == arr[indexJ]) {
indexJ++;
count++;
}
}
out.println(inputN - count);
}
out.flush();
}
}
不等式数列 动态规划
度度熊最近对全排列特别感兴趣,对于1到n的一个排列,度度熊发现可以在中间根据大小关系插入合适的大于和小于符号(即 '>' 和 '<' )使其成为一个合法的不等式数列。但是现在度度熊手中只有k个小于符号即('<'')和n-k-1个大于符号(即'>'),度度熊想知道对于1至n任意的排列中有多少个排列可以使用这些符号使其为合法的不等式数列。
输入描述:
输入包括一行,包含两个整数n和k(k < n ≤ 1000)
输出描述:
输出满足条件的排列数,答案对2017取模。
输入例子:
5 2
输出例子:
66
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.StreamTokenizer;
/**
* 动态规划
*
* dp[i][j] 表示有 i 个数字及 j 个小于号所能组成的数量。
*
* 当加入第 i 个数字时:
* ①、加在不等式开头:即 1 < 2 ==> 3 > 1 < 2 此时就等同于加入了一个大于号
* ②、加在不等式末尾:即 1 < 2 ==> 1 < 2 < 3 此时就等同于加入了一个小于号
* ③、加在不等式中间:
* i、不等号为小于号:即 1 < 2 ==> 1 < 3 > 2 此时就等同于加入了一个大于号,但对于中间的每个小于号,都可以执行这样一次插入。
* ii、不等号为大于号:即 1 > 2 ==> 1 < 3 > 2 此时就等同于加入了一个小于号,但对于中间的每个大于号,都可以执行这样一次插入。
*
* 综上所述,dp[i][j] 等于以上四种情况之和:
* dp[i][0] = 1; 没有不等号时,只有一种不等式组合。
* dp[i][j] = dp[i-1][j] + dp[i-1][j-1] + dp[i-1][j] * j + dp[i-1][j-1] * (i-j+1)
* = dp[i-1][j] * (j+1) + dp[i-1][j-1] * (i-j)
*
* 结果记得 mod 2017
*/
public class Main {
public static void main(String[] args) throws IOException {
StreamTokenizer in = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));
int inputN;
int inputK;
// 表示有 i 个数字及 j 个小于号所能组成不等式的数量
int[][] dp = new int[1005][1005];
while (in.nextToken() != StreamTokenizer.TT_EOF) {
inputN = (int) in.nval;
in.nextToken();
inputK = (int) in.nval;
dp[1][0] = 1;
// 从 dp[2][1] 开始
for (int indexI = 2; indexI <= inputN; indexI++) {
dp[indexI][0] = 1;
for (int indexJ = 1; indexJ <= inputK; indexJ++) {
dp[indexI][indexJ] = (dp[indexI - 1][indexJ - 1] * (indexI - indexJ) + dp[indexI - 1][indexJ] * (indexJ + 1)) % 2017;
}
}
out.println(dp[inputN][inputK] % 2017);
}
out.flush();
}
}