百度2017春招笔试真题编程题集合 题解

题目链接:https://www.nowcoder.com/test/4998655/summary

难度分析:较简单,很多题的数据都比较水。

1.买帽子:

度度熊想去商场买一顶帽子,商场里有N顶帽子,有些帽子的价格可能相同。度度熊想买一顶价格第三便宜的帽子,问第三便宜的帽子价格是多少?

解题思路分析:

题意很简单,只需要排个序,再从头开始找到第三个出现的就能得到答案,题目的数据才50,也就是说甚至是冒泡选择排序这种O(n^2)的复杂度都不会被卡掉,完美的送分题。

代码:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 50 + 5;
int a[maxn];
int main() {
    int n;
    cin >> n;
    for(int i=0; i<n; i++) {
        cin >> a[i];
    }
    sort(a, a+n);
    int num = 0, ok = 0;
    for(int i=0; i<n; i++) {
        if(i == 0 || a[i] != a[i-1]) {
            num++;
        }
        if(num == 3) {
            cout << a[i] << endl;
            ok = 1;
            break;
        }
    }
    if(!ok) {
        cout << -1 << endl;
    }
}

2.度度熊回家:

一个数轴上共有N个点,第一个点的坐标是度度熊现在位置,第N-1个点是度度熊的家。现在他需要依次的从0号坐标走到N-1号坐标。
但是除了0号坐标和N-1号坐标,他可以在其余的N-2个坐标中选出一个点,并直接将这个点忽略掉,问度度熊回家至少走多少距离?

解题思路分析:去掉一个点减少的距离就是这个点到相邻两个点的距离和减去两个相邻点的距离,也就是说去掉一个点减少的距离是固定的,那么我们只需要求出所有点去掉它所减小的距离的最大值,答案就是每个相邻点的距离和减去这个最大值。这题的坐标是二维的,点的个数又是50的范围,也没有什么难度,送分题+1;

代码:

扫描二维码关注公众号,回复: 2619262 查看本文章
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 50 + 5;
int a[maxn];
int Abs(int x) {
    return x>0? x : -x;
}
int main() {
    int n;
    cin >> n;
    int sum = 0;
    for(int i=0; i<n; i++) {
        cin >> a[i];
        if(i != 0) {
            int tmp = a[i] - a[i-1];
            sum += Abs(tmp);
        }
    }
    int Max = 0;
    for(int i=1; i<n-1; i++) {
        int t1 = Abs(a[i] - a[i-1]);
        int t2 = Abs(a[i+1] - a[i]);
        int t3 = Abs(a[i+1] - a[i-1]);
        Max = max(Max, t1 + t2 - t3);
    }
    cout << sum - Max << endl;
}

3.寻找三角形

三维空间中有N个点,每个点可能是三种颜色的其中之一,三种颜色分别是红绿蓝,分别用'R', 'G', 'B'表示。 
现在要找出三个点,并组成一个三角形,使得这个三角形的面积最大。
但是三角形必须满足:三个点的颜色要么全部相同,要么全部不同。

解题思路分析:

真的,小编在做的时候看到第三题又是50的数据的时候是真的笑出声了,送分题+2,求解三角形面积的方法可以用海伦公式,求出三边长即可求得面积,因为数据的范围又才50,我们根本不需要什么判断颜色分情况讨论啥的,直接O(n^3)暴力求出每一种情况,判断每一种情况是否能构成三角形以及是否颜色满足题目要求,在满足要求的三角形中求最大值即可。

代码:

#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include"iomanip" 
using namespace std;
const int maxn = 50+5;
struct Point {
    char color;
    int x, y, z;
}p[maxn];
double count_triangle_area(Point a, Point b, Point c) {
    double area = -1;
    double side[3];
    side[0] = sqrt(pow(a.x - b.x,2) + pow(a.y - b.y,2) + pow(a.z - b.z,2));
    side[1] = sqrt(pow(a.x - c.x,2) + pow(a.y - c.y,2) + pow(a.z - c.z,2));
    side[2] = sqrt(pow(c.x - b.x,2) + pow(c.y - b.y,2) + pow(c.z - b.z,2));
    if(side[0]+side[1] <= side[2] || side[0]+side[2] <= side[1] || side[1]+side[2] <= side[0]) {
    	return area;
	}
    double p = (side[0] + side[1] + side[2])/2;
    area = sqrt(p * (p-side[0]) * (p-side[1]) * (p-side[2]));
    return area;
}
int main()
{
    int n;
    while(cin >> n) {
        double area = 0, Max = 0;
        for(int i=0; i<n; i++) {
            cin >> p[i].color >> p[i].x >> p[i].y >> p[i].z;
        }
        for(int i=0; i<n; i++) {
            for(int j=i+1; j<n; j++) {
                for(int k=j+1; k<n; k++) {
                    area = count_triangle_area(p[i],p[j],p[k]);
                    if(((p[i].color == p[j].color) && (p[i].color == p[k].color)) || ((p[i].color != p[j].color) && (p[i].color != p[k].color) && (p[j].color != p[k].color))) {
                        Max = max(Max,area);
                    }
                }
            }
        }
        printf("%.5f\n", Max);
    }
    return 0;
}

4.有趣的排序

度度熊有一个N个数的数组,他想将数组从小到大 排好序,但是萌萌的度度熊只会下面这个操作:
任取数组中的一个数然后将它放置在数组的最后一个位置。
问最少操作多少次可以使得数组从小到大有序?

解题思路分析:

终于不是范围50的数据了……这题我们反过来思考,有多少个数是不需要进行置后的操作的,首先我们先通过排序得知其排好序的顺序,然后再从第一个开始往后一个一个地找,在原有序列中和最终排好序的相邻元素的相对位置正确的就是不需要进行置后操作的,举个例子:1 4 2 3 5,明显排好序后的顺序应该是1 2 3 4 5,所以我们按着排好序的顺序从原序列中查找,得到1 2 3是不需要进行置后操作的,所以操作数就是5 - 3 = 2.

代码:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 50+5;
int a[maxn], b[maxn];
int main()
{
    int n;
    scanf("%d", &n);
    for(int i=0; i<n; i++) {
        cin >> a[i];
        b[i] = a[i];
    }
    sort(b, b+n);
    int num = 0;
    for(int i=0; i<n; i++) {
        if(a[i] == b[num]) {
            num++;
        }
    }
    cout << n - num << endl;
}

5.不等式序列:

度度熊最近对全排列特别感兴趣,对于1到n的一个排列,度度熊发现可以在中间根据大小关系插入合适的大于和小于符号(即 '>' 和 '<' )使其成为一个合法的不等式数列。但是现在度度熊手中只有k个小于符号即('<'')和n-k-1个大于符号(即'>'),度度熊想知道对于1至n任意的排列中有多少个排列可以使用这些符号使其为合法的不等式数列。

解题思路分析:

这题还比较有意思,思路上,从对2017取模得知答案应该非常的大,不可能直接算出来,再从1到n的排列的提示来看,这题应该是一个动态规划的题目,那么分析,如果从已经知道答案的序列,再加一个数会怎么样,首先,新加的数比我们当前序列里的所有数都大,所以它一定可以加个<放到序列的右边,以及加个>放到序列的左边,其次,它可以插入到序列中任意一个>的左边并在它的左边再加一个<,或者插入到序列中任意一个<的右边,并在它的右边再加一个>,所以状态转移方程应该为:

dp[i][j] = dp[i-1][j-1] + dp[i-1][j] + dp[i-1][j] * (i - j - 1) + dp[i-1][j-1] * j

还有就是注意每一步都进行取模,避免溢出。

代码:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 1000 + 5;
const int MOD = 2017;
int dp[maxn][maxn];
int main() {
    int n, k;
    cin >> n >> k;
    if(n <= 2) {
        cout << 1 << endl;
    }
    for(int i=0; i<=n; i++) {
        dp[i][0] = dp[i][i-1] = 1;
    }
    for(int i=2; i<=n; i++) {
        for(int j=1; j<=k; j++) {
            int x1 = dp[i-1][j] % MOD;
            int x2 = dp[i-1][j-1] % MOD;
            int x3 = dp[i-1][j] * j % MOD;
            int x4 = dp[i-1][j-1] * (i - j - 1) % MOD;
            dp[i][j] = (((x1 + x2)%MOD + x3)%MOD + x4)%MOD;
        }
    }
    cout << dp[n][k] << endl;
}

猜你喜欢

转载自blog.csdn.net/RaAlGhul/article/details/81480919
今日推荐