2020.08.08 网易秋招算法岗笔试简单总结(贪心,dp,二进制枚举,tarjan)

这篇博客是对2020年网易秋季招聘算法岗位笔试题的总结,涉及题目包括贪心算法、动态规划、二进制枚举以及Tarjan算法求强连通分量。博主分享了每道题目的解题思路,包括暴力解法和优化策略,并邀请读者交流讨论。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

记录一下8号做的网易笔试题,总的来说笔试难度相对easy且每个人的题目可能不同,简单记录分享下。
PS:对于题目,每个人有每个人不同的想法和解题思路,大佬们有更高效的方法欢迎讨论,但勿喷,谢谢!

TI

在这里插入图片描述

思路:

就一个简单的贪心,暴力拆成2的和统计个数就好了,不过多解释。

T2

在这里插入图片描述
在这里插入图片描述

思路

可dp可暴力。
dp简单的可以是两维 d p [ i ] [ j ] , j ∈ { 0 , 1 } dp[i][j],j\in\{0,1\} dp[i][j],j{0,1},转移方程也极其简单。当然细心的可以发现,一维其实就足够了。
在这里插入图片描述

T3

在这里插入图片描述
在这里插入图片描述

思路

法1

这题暴力 3 n 3^n 3n也能过,大概1e7的复杂度,就是爆搜每个物品是属于第一个人还是第二个人还是抛弃,然后维护最小值。

#include <bits/stdc++.h>

using namespace std;
using LL = long long;
using pii = pair<LL, LL>;

const int maxn = 16;
int n;
int a[maxn];
int ret = INT_MAX;

void dfs(int id, int l, int r, int drop) {
  if (id == n + 1) {
    if (l == r) {
      ret = min(ret, drop);
    }
    return;
  }
  dfs(id + 1, l + a[id], r, drop);
  dfs(id + 1, l, r + a[id], drop);
  dfs(id + 1, l, r, drop + a[id]);
}


signed main() {
  // freopen("in", "r", stdin);
  // freopen("out", "w", stdout);
  int T;
  scanf("%d", &T);
  while (T--) {
    scanf("%d", &n);
    for (int i = 1; i <= n; i++) {
      scanf("%d", &a[i]);
    }
    ret = INT_MAX;
    dfs(1, 0, 0, 0);
    printf("%d\n", ret);
  }
  return 0;
}

法2

其实更好的方法我觉得是用二进制枚举+Hash,即先用二进制枚举所有能组成的和(二进制hash,即key=二进制,value=凑成的和),然后再枚举选择哪些商品,计算能否分开两堆且和相等,最后得到抛弃的值。应特别注意揣摩 ( S 2 − 1 ) & S (S_2-1)\&S (S21)&S的用法

在这里插入图片描述

T4

在这里插入图片描述
在这里插入图片描述

思路:

题目讲的花里胡哨,细细揣摩一下这不就是求个强连通分量,然后缩点。最后的答案就是每个强连通分量中点的个数为k,答案就是 ∑ ( k ∗ ( k − 1 ) ) / 2 \sum(k*(k-1))/2 (k(k1))/2
求强连通分量这里使用tarjan算法,复杂度为 O ( n + m ) O(n+m) O(n+m)

#include <bits/stdc++.h>

using namespace std;
using LL = long long;
using pii = pair<int, int>;

const int maxn = 50050;
const int maxm = 600600;

typedef struct Edge {
  int u;
  int v;
  int next;
  Edge() { next = -1; }
}Edge;

int head[maxn], ecnt;
Edge edge[maxm];
int n, m;

int bcnt, dindex;
int dfn[maxn], low[maxn];
int stk[maxn], top;
int belong[maxn];
int in[maxn], out[maxn];
bool instk[maxn];

void init() {
  memset(edge, 0, sizeof(edge));
  memset(head, -1, sizeof(head));
  memset(instk, 0, sizeof(instk));
  memset(dfn, 0, sizeof(dfn));
  memset(low, 0, sizeof(low));
  memset(belong, 0, sizeof(belong));
  memset(in, 0, sizeof(in));
  memset(out, 0, sizeof(out));
  ecnt = top = bcnt = dindex = 0;
}

void adde(int uu, int vv) {
  edge[ecnt].u = uu;
  edge[ecnt].v = vv;
  edge[ecnt].next = head[uu];
  head[uu] = ecnt++;
}

void tarjan(int u) {
  int v = u;
  dfn[u] = low[u] = ++dindex;
  stk[++top] = u;
  instk[u] = 1;
  for(int i = head[u]; ~i; i=edge[i].next) {
    v = edge[i].v;
    if(!dfn[v]) {
      tarjan(v);
      low[u] = min(low[u], low[v]);
    }
    else if(instk[v]) low[u] = min(low[u], dfn[v]);
  }
  if(dfn[u] == low[u]) {
    bcnt++;
    do {
      v = stk[top--];
      instk[v] = 0;
      belong[v] = bcnt;
    } while(v != u);
  }
}

int main() {
  // freopen("in", "r", stdin);
  // freopen("out", "w", stdout);

  int uu, vv;
  while(~scanf("%d %d", &n, &m)) {
    init();
    for (int i = 1; i <= m; i++) {
      scanf("%d %d", &uu, &vv);
      if (uu == vv) continue;
      adde(uu, vv);
    }
    for(uu = 1; uu <= n; uu++) {
      if(!dfn[uu]) {
        tarjan(uu);
      }
    }
    for(int i = 0; i < ecnt; i++) {
      if(belong[edge[i].u] != belong[edge[i].v]) {
        in[belong[edge[i].u]]++;
        out[belong[edge[i].v]]++;
      }
    }
    unordered_map<int, int> vis;
    for (int i = 1; i <= n; i++) {
      vis[belong[i]]++;
    }
    LL ret = 0;
    for (const auto x : vis) {
      LL cnt = x.second;
      ret += (cnt - 1) * cnt / 2;
    }
    printf("%lld\n", ret);
  }
  return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Marcus-Bao

万水千山总是情,只给五角行不行

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值