快手2020校园招聘秋招笔试--工程B试卷

集合划分问题

题目描述

给定一个数组,每个元素范围是0~K(K < 整数最大值2^32),将该数组分成两部分,使得 |S1- S2|最小,其中S1和S2分别是数组两部分的元素之和。

输入描述

数组元素个数N(N 大于1但不超过 10, 000, 000)。

数组中N个元素(用空格分割)。

输出描述

|S1- S2|的值。

解题思路

转换为 0 − 1 0-1 01 背包问题,等价于,问,从 n n n 个数中选,在选取的数的和不超过 n n n 个数的总和的一半的前提下,所能选取的数的和的最大值。

代码实现
typedef long long ll;

int main() {
    int n;
    scanf("%d", &n);
    int a[n + 1];
    ll sum = 0, k;
    for (int i = 1; i <= n; i++) {
        scanf("%d", &a[i]);
        sum += a[i];
    }
    k = sum >> 1;
    ll dp[k + 1];
    memset(dp, 0, sizeof dp);
    for (int i = 1; i <= n; i++)
        for (ll j = k; j >= a[i]; j--)
            dp[j] = max(dp[j], dp[j - a[i]] + a[i]);
    printf("%lld", sum - (dp[k] << 1));
    return 0;
}

时间复杂度: O ( n × s u m ) O(n \times sum) O(n×sum)

空间复杂度: O ( s u m ) O(sum) O(sum)

最长等差数列问题

题目描述

给定一个未排序数组,找出其中最长的等差数列(无需保证数字顺序)。

输入描述

第一行N表示数组中元素个数(N < 10,000,000)

第二行是数组的元素,用空格分割

输出描述

等差序列长度

解题思路

先将数组 a a a 按从小到大排序,令 d p [ i ] [ j ] dp[i][j] dp[i][j] = 公差为 i i i 且以 a j a_j aj 结尾的等差数列的最长长度,则 d p [ i ] [ j ] = m a x ( d p [ i ] [ j ] , d p [ i ] [ a j − i ] + 1 ) dp[i][j]=max(dp[i][j],dp[i][a_j-i]+1) dp[i][j]=max(dp[i][j],dp[i][aji]+1)

上式简化为,由于 d p [ i ] [ j ] dp[i][j] dp[i][j] 不依赖于 d p [ i − 1 ] [ ? ] dp[i-1][?] dp[i1][?],故可转为一维数组, d p [ j ] = m a x ( d p [ j ] , d p [ a j − i ] + 1 ) dp[j]=max(dp[j],dp[a_j-i]+1) dp[j]=max(dp[j],dp[aji]+1)

代码实现
const int N = 1e5 + 5;
int a[N], dp[N];

int main() {
    int n;
    scanf("%d", &n);
    for (int i = 0; i < n; i++)
        scanf("%d", &a[i]);
    sort(a, a + n);
    int diff = a[n - 1] - a[0], res = 1;
    int *dpc = dp - a[0];
    for (int d = -diff; d <= diff; d++) {
        memset(dp, -1, sizeof dp);
        for (int i = 0; i < n; i++) {
            int pre = a[i] - d;
            if (pre >= a[0] && pre <= a[n - 1] && dpc[pre] != -1) {
                dpc[a[i]] = max(dpc[a[i]], dpc[pre] + 1);
                res = max(res, dpc[a[i]]);
            }
            dpc[a[i]] = max(dpc[a[i]], 1);
        }
    }
    printf("%d", res);
    return 0;
}

时间复杂度: O ( m n ) O(mn) O(mn),其中, m m m a i a_i ai 的最大值与最小值之差。

空间复杂度: O ( n ) O(n) O(n)

字母组合

题目描述

给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合,按照字典序升序排序,如果有重复的结果需要去重给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。

输入描述

输入2-9数字组合, 字符串长度 1<=length<=20。

输出描述

输出所有组合。

解题思路

模拟即可。

代码实现
string s, t, all;
unordered_map<int, string> mp = {
        {2, "abc"},
        {3, "def"},
        {4, "ghi"},
        {5, "jkl"},
        {6, "mno"},
        {7, "pqrs"},
        {8, "tuv"},
        {9, "wxyz"},
};

void dfs(int x) {
    if (x >= s.size()) {
        all.append(t).append(", ");
        return;
    }
    for (char c: mp[s[x] - '0']) {
        t.push_back(c);
        dfs(x + 1);
        t.pop_back();
    }
}

int main() {
    cin >> s;
    dfs(0);
    all.pop_back();
    all.pop_back();
    cout << "[" << all << "]";
    return 0;
}

时间复杂度: O ( n ) O(n) O(n)

空间复杂度: O ( 1 ) O(1) O(1)

验证IP地址

题目描述

编写一个函数来验证输入的字符串是否是有效的 IPv4 或 IPv6 地址。

IPv4 地址由十进制数和点来表示,每个地址包含4个十进制数,其范围为 0 - 255, 用(“.”)分割。比如,172.16.254.1;
同时,IPv4 地址内的数不会以 0 开头。比如,地址 172.16.254.01 是不合法的。

IPv6 地址由8组16进制的数字来表示,每组表示 16 比特。这些组数字通过 (“:”)分割。比如, 2001:0db8:85a3:0000:0000:8a2e:0370:7334 是一个有效的地址。而且,我们可以加入一些以 0 开头的数字,字母可以使用大写,也可以是小写。所以, 2001:db8:85a3:0:0:8A2E:0370:7334 也是一个有效的 IPv6 address地址 (即,忽略 0 开头,忽略大小写)。

然而,我们不能因为某个组的值为 0,而使用一个空的组,以至于出现(::)的情况。 比如, 2001:0db8:85a3::8A2E:0370:7334 是无效的 IPv6 地址。
同时,在 IPv6 地址中,多余的 0 也是不被允许的。比如, 02001:0db8:85a3:0000:0000:8a2e:0370:7334 是无效的。

说明: 你可以认为给定的字符串里没有空格或者其他特殊字符。

输入描述

一个IP地址字符串

输出描述

ip地址的类型,可能为:IPv4, IPv6, Neither

解题思路

按题意进行判断即可。

代码实现
bool isIPv4(string &s) {
    int idx = 0, cnt = 0;
    while (idx < s.size()) {
        if (s[idx] == '0' || s[idx] == '.')return false;
        int x = 0;
        while (idx < s.size() && s[idx] != '.')x = x * 10 + s[idx] - '0', idx++;
        if (x > 255)return false;
        idx++, cnt++;
    }
    return cnt == 4;
}

bool isIPv6(string &s) {
    int idx = 0, cnt = 0;
    while (idx < s.size()) {
        if (s[idx] == ':')
            return false;
        int t = idx;
        while (idx < s.size() && s[idx] != ':')idx++;
        if (idx - t > 4)return false;
        idx++, cnt++;
    }
    return cnt == 8;
}

int main() {
    string s;
    cin >> s;
    if (isIPv4(s))printf("IPv4");
    else if (isIPv6(s))printf("IPv6");
    else printf("Neither");
    return 0;
}

时间复杂度: O ( n ) O(n) O(n)

空间复杂度: O ( 1 ) O(1) O(1)

END

文章文档:公众号 字节幺零二四 回复关键字可获取本文文档。

题目来源:快手2020校园招聘秋招笔试–工程B试卷

文章声明:题目来源 牛客 平台,如有侵权,请联系删除!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值