网易2018春招笔试编程题参考代码

练习地址:https://www.nowcoder.com/test/9763997/summary


牛牛的闹钟

分析

对于每一个闹钟,计算x分钟后的时间,和上课时间进行比较,如果不超过上课时间,把闹钟时间和保存的答案进行比较,取最晚。

时间复杂度

O(n)

参考代码

#include <bits/stdc++.h>

using namespace std;

int h[105], m[105];
int main() {
    int n, x;
    int ans1 = 0, ans2 = 0, temp1, temp2;
    int a, b;
    scanf("%d", &n);
    for(int i = 0; i < n; i++) scanf("%d%d", &h[i], &m[i]);
    scanf("%d", &x);
    scanf("%d%d", &a, &b);
    for(int i = 0; i < n; i++) {
        temp2 = m[i] + x;
        temp1 = h[i] + temp2 / 60;
        temp2 = temp2 % 60;
        if(temp1 < a || (temp1 == a && temp2 <= b)) {
            if(h[i] > ans1 || (h[i] == ans1 && m[i] > ans2)) {
                ans1 = h[i];
                ans2 = m[i];
            }
        }
    }
    printf("%d %d\n", ans1, ans2);
    return 0;
}

迷路的牛牛

分析

统计一共向左和向右转了多少次,计算最后的方向相对于初始方向的差异,模拟即可。

时间复杂度

O(n)

参考代码

#include <bits/stdc++.h>

using namespace std;

char s[1005];
int main() {
    int now = 0, n;
    scanf("%d", &n);
    scanf("%s", s);
    for(int i = 0; i < n; i++) {
        if(s[i] == 'L')
            now--;
        else
            now++;
    }
    now = (now % 4 + 4) % 4;
    if(now == 0)
        printf("N\n");
    else if(now == 1)
        printf("E\n");
    else if(now == 2)
        printf("S\n");
    else
        printf("W\n");
    return 0;
}

安置路灯

分析

贪心。
对于一个需要照亮的位置的右边一格放置一个路灯就好了。

时间复杂度

O(n)

参考代码

#include <bits/stdc++.h>

using namespace std;
int n;
char s[1005];
int main() {
    int t;
    scanf("%d", &t);
    while(t--) {
        scanf("%d", &n);
        scanf("%s", s);
        int ans = 0;
        for(int i = 0; i < n; i++) {
            if(s[i] == 'X') continue;
            if(s[i] == '.') ans++;
            i += 2;
        }
        printf("%d\n",ans);
    }
    return 0;
}

被3整除

分析

手算一下会发现规律。
三个数为一组,第一个数不能被3整除,另外两个可以被3整除。
于是把区间端点都移到某组的开端,记录移动过程中满足的数, 之后就可以通过(b - a) / 3 * 2快速计算。

时间复杂度

O(1)

参考代码

#include <bits/stdc++.h>

using namespace std;
int main() {
    int l, r;
    scanf("%d%d", &l, &r);
    int cnt1 = 0, cnt2 = 0, cnt = 0;
    if(l % 3 == 2 || l % 3 == 0) cnt++;
    if(r % 3 == 2 || r % 3 == 0) cnt++;
    while(l % 3 != 1) {
        if(l % 3 == 2 || l % 3 == 0) cnt1++;
        l--;
    }
    while(r % 3 != 1) {
        if(r % 3 == 2 || r % 3 == 0) cnt2++;
        r++;
    }
    cnt += (r - l) / 3 * 2;
    printf("%d\n", cnt - cnt1 - cnt2);
    return 0;
}

数对

分析

对于一个b, n范围内的数模b的序列应该是:
0,1,2,...,b-1, 0, 1, 2,..., b-1,...0,1,2,..n%b
前面部分是个循环节,所以可以通过(n / b) * max(0, b - k)计算。
后面部分是max(0, n % b - k + 1),
于是我们枚举合法的b计算就可以了。
k = 0的情况特判处理。

时间复杂度

O(n)

参考代码

#include <bits/stdc++.h>

using namespace std;

int main() {
    int n, k;
    cin >> n >> k;
    if(k == 0) cout << 1LL * n * n << endl;
    else {
        long long ans = 0;
        for(int i = k + 1; i <= n; i++){
            ans += (n / i) * (i - k);
            if(n % i >= k)    ans += n % i - k + 1;
        }
        cout << ans << endl;
    }
    return 0;
}

矩形重叠

分析

分别枚举所有的横纵坐标,挨着判断每个矩形是否符合条件,计数维护最大即可。

时间复杂度

O(n^3)

参考代码

#include <bits/stdc++.h>

using namespace std;

const int maxn = 50 + 5;
int X1[maxn], Y1[maxn];
int X2[maxn], Y2[maxn];
set<int> xx, yy;
int main() {
    int n;
    cin >> n;
    for(int i = 0; i < n; i++) {
        cin >> X1[i];
        xx.insert(X1[i]);
    }
    for(int i = 0; i < n; i++) {
        cin >> Y1[i];
        yy.insert(Y1[i]);
    }
    for(int i = 0; i < n; i++) {
        cin >> X2[i];
        xx.insert(X2[i]);
    }
    for(int i = 0; i < n; i++) {
        cin >> Y2[i];
        yy.insert(Y2[i]);
    }
    int ans = 0;
    for(int x : xx) {
        for(int y : yy) {
            int cnt = 0;
            for(int i = 0; i < n; i++) {
                if(X1[i] <= x && Y1[i] <= y && X2[i] > x && Y2[i] > y) cnt++;
            }
            ans = max(ans, cnt);
        }
    }
    cout << ans << endl;
    return 0;
}

牛牛的背包问题

分析

容量太大,没办法dp。
看到物品数量是30,直接爆搜也不行。。
于是对半分成两部分枚举之后,二分计算贡献。
当然用个map来做个map版本的背包也是兹磁的吧?

时间复杂度

O(2^(n/2) * log(2^(n/2)))

参考代码

#include <bits/stdc++.h>

using namespace std;
typedef long long LL;
LL v[35];
vector<LL> val1, val2;
int n, w;
void calc(LL *item, int mx, vector<LL> &val){
    for(int i = 0; i < mx; i++){
        LL sum = 0;
        for(int j = 0; j < 20; j++){
            if(i & (1 << j)){
                sum += item[j];
                if(sum > w) break;
            }
        }
        if(sum <= w) val.push_back(sum);
    }
}
int main() {
    val1.clear();
    val2.clear();
    scanf("%d%d", &n, &w);
    for(int i = 0; i < n; i++) scanf("%lld", &v[i]);
    calc(v, 1 << (n / 2), val1);
    calc(&v[n - (n + 1) / 2], 1 << (n - n / 2), val2);
    sort(val2.begin(), val2.end());
    LL ans = 0;
    for(int i = 0; i < val1.size(); i++){
        ans += upper_bound(val2.begin(), val2.end(), w - val1[i]) - val2.begin();
    }
    printf("%lld\n", ans);
    return 0;
}

牛牛找工作

分析

实际上对于每个难度的工作,只有报酬最高的那一种是可能成为答案的,剩下的都可以无视。
由于只有N项工作和M个小伙伴,最多只会出现N+M种难度(能力值),所以可以把难度和能力值映射到不超过N+M个数上(std通过排序+map来完成)。
对这些难度(能力值)分别求出最高的报酬,再按i从小到大的顺序维护难度(能力值)不超过i的最大报酬。最后输出每个小伙伴对应的能力值以下的最高报酬即可。

时间复杂度

O((N+M)*log(N+M))

参考代码

#include <bits/stdc++.h>
using namespace std;

map<int,int> mp;
int cnt = 0;
int ans[200005];
int d[100005], p[100005];
int val[200005];
int a[100005];
int main() {
    int n, m;
    scanf("%d%d", &n, &m);
    for(int i = 1; i <= n; i++) {
        scanf("%d%d", &d[i], &p[i]);
        val[i] = d[i];
    }
    for(int i = 1; i <= m; i++) {
        scanf("%d", &a[i]);
        val[i + n] = a[i];
    }
    sort(val + 1, val + 1 + n + m);
    for(int i = 1; i <= n + m; i++) {
        if(val[i] != val[i - 1]) {
            cnt++;
            mp[val[i]] = cnt;
        }
    }
    for(int i = 1; i <= n; i++) ans[mp[d[i]]] = max(ans[mp[d[i]]], p[i]);
    for(int i = 2; i <= n + m; i++) ans[i] = max(ans[i], ans[i - 1]);
    for(int i = 1; i <= m; i++)
        printf("%d\n", ans[mp[a[i]]]);
    return 0;
}
#春招#
全部评论
编程题开放练习了 https://www.nowcoder.com/test/9763997/summary 
点赞 回复 分享
发布于 2018-03-27 23:07
哇,香港记者都没你快
点赞 回复 分享
发布于 2018-03-27 21:40
nk题思路理解: 1.首先看题目给的条件,1<=(x,y)<=n ,x%y >= k 2.分为两大类,k==0时(x,y)取任何值都可以,这样的情况下总数count = n*n 3.k != 0时,由 x%y >= k 转换成 x = a*y + b,可知y肯定是大于k的,所以固定y,从y=k+1遍历到y=n,然后对每个y,a 可以取的值有[0,n/y),b可以取的值有[k,y),注意这里的区间都是左闭右开,所以count+=(n/y)*(y-k) 4.需要单独考虑的是a == n/y时的情况,如果此时n%y >= k,那么a可以取n/y,此时count需要再加上n%y-k+1 Java代码如下: import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner in = new Scanner(System.in); int n = in.nextInt(); int k = in.nextInt(); long count = 0; if (k == 0) { System.out.println(n*n);   } else { for (int y = k + 1; y <= n; y++) { count += (n / y) * (y - k); if (n % y >= k) { count += n % y - k + 1;   } } System.out.println(count); } } }
点赞 回复 分享
发布于 2018-03-28 08:59
内部大佬。
点赞 回复 分享
发布于 2018-03-27 21:48
atcoder原题 也是 服气n,k那个 戳这里 <<<<
点赞 回复 分享
发布于 2018-03-27 21:42
你是网易员工吗,怎么做了这么多题。。
点赞 回复 分享
发布于 2018-03-27 21:40
那个输入n,k的应该怎么写呀,我用循环嵌套说超时,c和python 都超时
点赞 回复 分享
发布于 2018-03-27 21:39
nk那道题搞了半个多小时,看了答案发现就差一点点。。。唉,凉凉
点赞 回复 分享
发布于 2018-03-28 08:33
在楼主的基础上把牛牛找工作的代码优化一下 #include <bits/stdc++.h> using namespace std; map<int, int> mp; int cnt = 0; int ans[200005]; int d[100005], p[100005]; int val[200005]; int a[100005]; int main() { int maxn = 0; int n, m; scanf("%d%d", &n, &m); for (int i = 1; i <= n; i++) { scanf("%d%d", &d[i], &p[i]); mp[d[i]] = p[i]; } for (int i = 1; i <= m; i++) { scanf("%d", &a[i]); } for (map<int, int>::iterator it = mp.begin(); it != mp.end(); it++) { if (mp[it->first] >= maxn) { maxn = mp[it->first]; } else { mp[it->first] = maxn; } } for (int i = 1; i <= m; i++) { map<int, int>::iterator it1 = mp.upper_bound(a[i]); --it1; cout << mp[it1->first] << endl; } return 0; }
点赞 回复 分享
发布于 2018-04-03 00:34
矩阵重叠那道题看不懂,有大神能给讲讲吗?
点赞 回复 分享
发布于 2018-03-31 23:14
牛牛找工作第28行可以直接写成 for(int i = 1; i <= n; i++) ans[mp[d[i]]] = p[i]; 感觉好理解一点
点赞 回复 分享
发布于 2018-03-31 21:09
膜拜大佬。。。
点赞 回复 分享
发布于 2018-03-28 21:13
然而 这个牛牛的背包 剪枝+深搜 还是能过 啊 - -|
点赞 回复 分享
发布于 2018-03-28 17:44
n,k的那个交完卷后才分析出解法,思路和这个一样,可惜。。。。
点赞 回复 分享
发布于 2018-03-28 12:44
矩形重叠只要判断点就行了,我理解错了题意吗?看这图,右边两个重叠,左边三个重叠。用这个算法不是求出右边那个矩形重叠区域吗?事实上左边矩形重叠区域里重叠矩形更多呀?
点赞 回复 分享
发布于 2018-03-28 12:35
膜拜dalao
点赞 回复 分享
发布于 2018-03-28 10:37
我的nk题解法,O(N) public static void main(String[] args) { Scanner sc = new Scanner(System.in); int n = sc.nextInt(); int k = sc.nextInt(); long ans = 0; for (int i = 1; i <=n; i++) { if (i >= k) { ans += n-i;   } if (i > k) { ans += (n/i - 1)*(i-k);   if (n % i >=k) { ans += n%i -k +1;   } } } System.out.println(ans); }
点赞 回复 分享
发布于 2018-03-28 09:43
矩形重叠问题我和你思路一样 但是Java超时了  C语言不会超时吗
点赞 回复 分享
发布于 2018-03-28 09:21
import java.util.Scanner; public class Main {     public static void main(String[] args) {         Scanner in = new Scanner(System.in);         int n = in.nextInt();         int k = in.nextInt();         long count = 0L;         if (k == 0) {             count = (long)n*n;             System.out.println(count);         } else {             for (int y = k + 1; y <= n; y++) {                 count += (long)(n / y) * (y - k);                 if (n % y >= k) {                     count +=(long) n % y - k + 1;                 }             }             System.out.println(count);         }     } } nk题 100%
点赞 回复 分享
发布于 2018-03-28 09:07
请收下我的膝盖!!!!楼主平时刷题多吗?
点赞 回复 分享
发布于 2018-03-28 09:03

相关推荐

07-07 17:06
已编辑
深圳技术大学 golang
点赞 评论 收藏
分享
07-11 11:15
中南大学 Java
好可爱的hr姐姐哈哈哈哈
黑皮白袜臭脚体育生:兄弟们貂蝉在一起,吕布开了
点赞 评论 收藏
分享
评论
点赞
161
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务