网易2018校招笔试编程题题解与思路

https://www.nowcoder.com/test/6910869/summary

相反数

分析

根据题意处理即可。

参考代码

#include <bits/stdc++.h>

using namespace std;

int n;
int main() {
    cin >> n;
    int cn = 0;
    int x = n;
    while(x) {
        cn = cn * 10 + x % 10;
        x /= 10;
    }
    cout << n + cn << endl;
    return 0;
}

字符串碎片

分析

计算有多少个片段,用总长度除以它即可。

参考代码

#include <bits/stdc++.h>

using namespace std;

string s;

int main() {
    cin >> s;
    char c = s[0];
    double n = 1, d;
    for(int i = 1; i < s.size(); i++) {
        if(c != s[i]) {
            c = s[i];
            n++;
        }
    }
    d = (double)s.size() / n;
    printf("%.2lf\n", d);
    return 0;
}

魔法币

分析

注意到答案肯定是确定的,对于每一步的奇偶进行判断,用栈保存输出即可。

参考代码

#include <bits/stdc++.h>

using namespace std;

int n;
stack<char> s;
int main() {
    cin >> n;
    while(n) {
        if(n % 2 == 0) {
            n = (n - 2) / 2;
            s.push('2');
        } else {
            n = (n - 1) / 2;
            s.push('1');
        }
    }
    while(!s.empty()) {
        printf("%c", s.top());
        s.pop();
    }
    printf("\n");
    return 0;
}

重排数列

分析

记录能被4整除的个数,能被2整除的个数以及奇数的个数,然后分情况讨论一下。

参考代码

#include <bits/stdc++.h>

using namespace std;

int n;
int main() {
    int t;
    scanf("%d", &t);
    while(t--) {
        scanf("%d", &n);
        int cnt4 = 0;
        int cnt2 = 0;
        int cnt1 = 0;
        for(int i = 0; i < n; i++) {
            int x;
            scanf("%d", &x);
            if(x % 4 == 0) cnt4++;
            else if(x % 2 == 0) cnt2++;
            else cnt1++;
        }
        if(cnt2 == 0) {
            if(cnt4 >= cnt1 - 1)
                printf("Yes\n");
            else
                printf("No\n");
        } else {
            if(cnt4 >= cnt1)
                printf("Yes\n");
            else
                printf("No\n");
        }
    }
    return 0;
}

游历魔法王国

分析

贪心。找出最长的那条树链长度,然后就可以判断出L是否足够走完最长的树链,贪心讨论下就好。

参考代码

#include <bits/stdc++.h>

using namespace std;

const int maxn = 50 + 5;
int n, L;
int parent[maxn];
int dp[200];
int main() {
    scanf("%d%d", &n, &L);
    for(int i = 0; i < n - 1; i++) scanf("%d", &parent[i]);
    int mx = 0;
    for(int i = 0; i < n - 1; i++) {
        dp[i + 1] = dp[parent[i]] + 1;
        mx = max(mx, dp[i + 1]);
    }
    int d = min(L, mx);
    cout << min((n), 1 + d + (L - d) / 2) << endl;
    return 0;
}

最长公共子括号序列

分析

因为长度相同,并且也是合法的括号序列,所以正反括号数跟原来一样。
我们考虑在原序列上枚举一个字符,把这个插入到序列的某个位置去,其他序列相对顺序不变,,这样就可以让LCS最大,然后我们判断一下是否合法,丢进set去重就好了。

参考代码

#include <bits/stdc++.h>

using namespace std;

string s;
int main() {
    cin >> s;
    set<string> S;
    int len = s.size();
    for(int i = 0; i < len; i++) {
        string w = s.substr(0, i) + s.substr(i + 1);
        for(int j = 0; j < len - 1; j++) {
            string u = w.substr(0, j) + s[i] + w.substr(j);
            int tmp = 0;
            for(int k = 0; k < len; k++) {
                tmp += (u[k] == '(' ? 1 : -1);
                if(tmp < 0) {
                    break;
                }
            }
            if(tmp >= 0) {
                S.insert(u);
            }
        }
    }
    cout << (int)S.size() - 1 << endl;
    return 0;
}

合唱

分析

动态规划。
dp[i][j]表示小Q上一个演唱的音符是v[i],牛博士上一个演唱的音符是v[j]的最小难度和。
记忆化搜索一下就好了。

参考代码

java版本

import static java.lang.StrictMath.abs;

import java.util.Scanner;

public class Main {

    static int maxn = 2000 + 5;
    static int[] v = new int[maxn];
    static int[][] dp = new int[maxn][maxn];
    static int n;

    public static int max(int a, int b) {
        return (a > b) ? a : b;
    }

    public static int min(int a, int b) {
        return (a < b) ? a : b;
    }



    public static int solve(int la,int lb){

        int now = max(la, lb) + 1;
        if(now == n + 1) return 0;
        if(dp[la][lb] != -1) return dp[la][lb];
        return dp[la][lb] = min(solve(now, lb) + (la>0 ? abs(v[now] - v[la]) : 0), solve(la, now) + (lb>0 ? abs(v[now] - v[lb]) : 0));
    }

    public static void main(String[] args) {
        Scanner cin = new Scanner(System.in);


        n = cin.nextInt();
        v[0] = -1;
        for(int i = 1; i <= n; i++) v[i] = cin.nextInt();


        for (int i = 0; i < maxn; i ++)
            for (int j = 0; j < maxn; j ++)
                dp[i][j] = -1;

        System.out.println(solve(0,0));
    }
}

C++版本

#include <bits/stdc++.h>

using namespace std;


const int maxn = 2000 + 5;
int v[maxn];
int n;
int dp[maxn][maxn];
int solve(int la, int lb) {
    int now = max(la, lb) + 1;
    if(now == n + 1) return 0;
    if(dp[la][lb] != -1) return dp[la][lb];
    return dp[la][lb] = min(solve(now, lb) + (la ? abs(v[now] - v[la]) : 0), solve(la, now) + (lb ? abs(v[now] - v[lb]) : 0));
}
int main() {
    scanf("%d", &n);
    v[0] = -1;
    for(int i = 1; i <= n; i++) scanf("%d", &v[i]);
    memset(dp, -1, sizeof(dp));
    printf("%d\n", solve(0, 0));
    return 0;
}

射击游戏

分析

注意到允许的移动和旋转都是对于怪物整体而言的,那么其实等价于整个坐标轴做移动或者旋转。
然后我们现在要移动或者旋转之后在坐标轴上的点最多,坐标轴肯定是由给定点集来组成的,接下来的问题就是枚举坐标轴统计就好了,中间会涉及到直线的垂直和平行的判断。

参考代码

java版本

import java.util.Scanner;

public class Main {

    public static int max(int a, int b) {
        return (a > b) ? a : b;
    }

    public static void main(String[] args) {
        Scanner cin = new Scanner(System.in);

        int[] x = new int[100];
        int[] y = new int[100];
        int n;
        n = cin.nextInt();
        for (int i = 0; i < n; i++) {
            x[i] = cin.nextInt();
        }
        for (int i = 0; i < n; i++) {
            y[i] = cin.nextInt();
        }

        if (n <= 2) {
            System.out.println(n);
            return;
        }
        int res = 1;
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                if (i != j) {
                    int dx1 = x[j] - x[i];
                    int dy1 = y[j] - y[i];
                    for (int k = 0; k < n; k++) {
                        int cnt = 0;
                        if (i != k && j != k) {
                            for (int r = 0; r < n; r++) {
                                int dx2 = x[r] - x[i];
                                int dy2 = y[r] - y[i];
                                if (dy1 * dx2 == dy2 * dx1) {
                                    cnt++;
                                } else {
                                    dx2 = x[r] - x[k];
                                    dy2 = y[r] - y[k];
                                    if (dy1 * dy2 == -dx2 * dx1) {
                                        cnt++;
                                    }
                                }
                            }
                        }
                        res = max(res, cnt);
                    }
                }
            }
        }
        System.out.println(res);


    }
}

C++版本

#include <bits/stdc++.h>

using namespace std;

const int maxn = 50 + 5;

int x[maxn], y[maxn];
int n;
int solve() {
    if(n <= 2) return n;
    int res = 1;
    for(int i = 0; i < n; i++) {
        for(int j = 0; j < n; j++) {
            if(i != j) {
                int dx1 = x[j] - x[i];
                int dy1 = y[j] - y[i];
                for(int k = 0; k < n; k++) {
                    int cnt = 0;
                    if(i != k && j != k) {
                        for(int r = 0; r < n; r++) {
                            int dx2 = x[r] - x[i];
                            int dy2 = y[r] - y[i];
                            if(dy1 * dx2 == dy2 * dx1) {
                                cnt++;
                            } else {
                                dx2 = x[r] - x[k];
                                dy2 = y[r] - y[k];
                                if(dy1 * dy2 == -dx2 * dx1) {
                                    cnt++;
                                }
                            }
                        }
                    }
                    res = max(res, cnt);
                }
            }
        }
    }
    return res;
}
int main() {
    cin >> n; 
    for(int i = 0; i < n; i++) cin >> x[i];
    for(int i = 0; i < n; i++) cin >> y[i];
    cout << solve() << endl;
}
全部评论
魔法王国题目意思都没看懂
点赞 回复 分享
发布于 2017-09-09 17:11
if (countMod4 >= n/2 || (countMod2 + countMod4) == n || countMod4 >= (n-countMod4-countMod2)) { puts("Yes"); } else { puts("No"); } 重排数列 我这么判断也 A 了
点赞 回复 分享
发布于 2017-09-09 17:19
我竟然是其中最难得三道T_T
点赞 回复 分享
发布于 2017-09-09 17:05
魔法王国那题不可以走回头路?
点赞 回复 分享
发布于 2017-09-09 17:06
        我很好奇你是什么人,为什么在笔试结束后可以给出所有题的答案。。。。。
点赞 回复 分享
发布于 2017-09-09 17:57
游历魔法王国这道题给的是有向边???我还以为是无向边
点赞 回复 分享
发布于 2017-09-09 17:12
每次自己写那么多代码,看看答案就简单的几行,感觉自己是个**...
点赞 回复 分享
发布于 2017-09-09 17:48
给大佬递柠檬茶
点赞 回复 分享
发布于 2017-09-09 17:04
还是因为自己太菜
点赞 回复 分享
发布于 2017-09-09 17:07
魔法王国是贪心?不是还可以原路返回吗,和旅行商问题有点像啊
点赞 回复 分享
发布于 2017-09-09 17:09
同 10 楼,魔法王国那题没说不能走回头路啊
点赞 回复 分享
发布于 2017-09-09 17:09
1 + d + (L - d) / 2,(L-d)/2为什么,回去路线是怎么考虑的
点赞 回复 分享
发布于 2017-09-09 17:38
魔法王国游历这题我终于看懂了,他这题的意思是最后达到的是最长路径的最后一个节点,如果步数比最长路径大,那么可以可以在其他路径上来回走访问其他城市,多出的步数除以2就是能多访问的城市数量,用比在纸上画一下就清楚了,在最长路径上走的是单向的距离,所以是最大利用的步数。
点赞 回复 分享
发布于 2017-09-09 17:58
大佬
点赞 回复 分享
发布于 2017-09-09 17:04
感谢大佬分享!
点赞 回复 分享
发布于 2017-09-09 17:04
给大佬端茶
点赞 回复 分享
发布于 2017-09-09 17:05
大佬,收小弟吗
点赞 回复 分享
发布于 2017-09-09 17:05
点赞 回复 分享
发布于 2017-09-09 17:05
跪拜大神~~
点赞 回复 分享
发布于 2017-09-09 17:05
学习一下
点赞 回复 分享
发布于 2017-09-09 17:05

相关推荐

点赞 254 评论
分享
牛客网
牛客企业服务