【字节跳动笔试题汇总】 2024-03-31-字节跳动春招笔试题-三语言题解(CPP/Python/Java)

🍭 大家好这里是KK爱Coding ,一枚热爱算法的程序员

✨ 本系列打算持续跟新字节跳动近期的春秋招笔试题汇总~

💻 ACM银牌🥈| 多次AK大厂笔试 | 编程一对一辅导

👏 感谢大家的订阅➕ 和 喜欢💗

文章目录

    • 01.K小姐的基环树游戏
      • 问题描述
      • 输入格式
      • 输出格式
      • 样例输入
      • 样例输出
      • 数据范围
      • 题解
      • 参考代码
    • 02.魔法糖果屋
      • 问题描述
      • 输入格式
      • 输出格式
      • 样例输入
      • 样例输出
      • 数据范围
      • 题解
      • 参考代码
    • 03.K小姐的树形公园设计
      • 题目描述
      • 输入格式
      • 输出格式
      • 样例输入
      • 样例输出
      • 样例说明
      • 数据范围
      • 题解
      • 参考代码
    • 04.LYA的光纤网络设计
      • 问题描述
      • 输入格式
      • 输出格式
      • 样例输入
      • 样例输出
      • 样例说明
      • 数据范围
      • 题解
      • 参考代码
    • 写在最后
    • 📧 KK这边最近正在收集近一年互联网各厂的笔试题汇总,如果有需要的小伙伴可以关注后私信一下 KK领取~

01.K小姐的基环树游戏

问题描述

K小姐最近迷上了一款基环树游戏。这个游戏的游戏地图是一个无向图,图中有 n n n 个节点和 m m m 条边,且不包含重边和自环。在这个游戏中,玩家需要在图上再选择连接一条边,使得整个无向图变成一棵基环树。

所谓基环树,是一种包含 n n n 个节点, n n n 条边,且不包含重边和自环的无向连通图。形象地说,基环树可以由一棵普通的树再添加一条之前不存在的边构成。

现在,K小姐想知道,对于当前的游戏地图,一共有多少种不同的连边方案可以使其变成一棵基环树呢?

输入格式

第一行输入两个正整数 n , m n,m n,m,代表无向图的节点数和边数。

接下来的 m m m 行,每行输入两个正整数 u , v u,v u,v,代表节点 u u u 和节点 v v v 之间有一条边相连。保证给定的无向图中不存在重边和自环。

输出格式

输出一个整数,代表添加一条新边使其变成基环树的方案数。

样例输入

4 4
1 2
1 3
2 3
2 4

样例输出

0

在这个样例中,原图已经是一棵基环树了,因此不需要再添加新边,方案数为0。

数据范围

1 ≤ n , m ≤ 1 0 5 1 \le n, m \le 10^5 1n,m105
1 ≤ u , v ≤ n 1 \le u, v \le n 1u,vn

题解

这道题可以用并查集和计数的方法来解决。基本思路如下:

  1. 首先判断原图是否已经是一棵树了,如果边数 m m m 不等于节点数 n − 1 n-1 n1,则原图一定不是树,方案数为0。

  2. 如果原图是树,则用并查集将所有边合并。合并完成后,统计并查集中连通分量的个数 c n t cnt cnt

  3. 如果 c n t > 2 cnt > 2 cnt>2,说明图不连通,无法通过添加一条边使其变成基环树,方案数为0。

  4. 如果 c n t = 1 cnt = 1 cnt=1,说明原图已经是基环树,方案数为 n ∗ ( n − 1 ) 2 − ( n − 1 ) \frac{n*(n-1)}{2}-(n-1) 2n(n1)(n1),即在完全图中选择一条之前不存在的边。

  5. 如果 c n t = 2 cnt = 2 cnt=2,说明原图由两个连通分量组成,方案数为两个连通分量的大小的乘积。

参考代码

  • Python
def find(x):
    if pre[x] != x:
        pre[x] = find(pre[x])
    return pre[x]

n, m = map(int, input().split())
if m != n - 1:
    print(0)
    exit()

pre = list(range(n))
for _ in range(n - 1):
    u, v = map(int, input().split())
    u, v = u - 1, v - 1
    pu, pv = find(u), find(v)
    if pu != pv:
        pre[pu] = pv

cnt = sum(pre[i] == i for i in range(n)) 
print(0 if cnt > 2 else n * (n - 1) // 2 - (n - 1) if cnt == 1 else next(a * b for a in map(pre.count, set(pre)) for b in map(pre.count, set(pre)) if a != n and b != n))
  • Java
import java.io.*;
import java.util.*;

public class Main {
    static int[] pre;
    
    static int find(int x) {
        if (pre[x] != x) 
            pre[x] = find(pre[x]);
        return pre[x];
    }
    
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        String[] params = br.readLine().split(" ");
        int n = Integer.parseInt(params[0]);
        int m = Integer.parseInt(params[1]);
        
        if (m != n - 1) {
            System.out.println(0);
            return;
        }
        
        pre = new int[n];
        for (int i = 0; i < n; i++) 
            pre[i] = i;
        
        for (int i = 0; i < n - 1; i++) {
            params = br.readLine().split(" ");
            int u = Integer.parseInt(params[0]) - 1;
            int v = Integer.parseInt(params[1]) - 1;
            int pu = find(u), pv = find(v);
            if (pu != pv) 
                pre[pu] = pv;
        }
        
        int cnt = 0;
        int[] size = new int[n];
        for (int i = 0; i < n; i++) {
            if (pre[i] == i) 
                cnt++;
            size[find(i)]++;
        }
        
        if (cnt > 2) {
            System.out.println(0);
        } else if (cnt == 1) {
            System.out.println(n * (n - 1L) / 2 - (n - 1));
        } else {
            int a = -1, b = -1;
            for (int s : size) {
                if (s > 0) {
                    if (a == -1) 
                        a = s;
                    else
                        b = s;
                }
            }
            System.out.println((long) a * b);
        }
    }
}
  • Cpp
#include <iostream>
#include <vector>
using namespace std;

vector<int> pre;

int find(int x) {
    if (pre[x] != x)
        pre[x] = find(pre[x]); 
    return pre[x];
}

int main() {
    int n, m;
    cin >> n >> m;
    
    if (m != n - 1) {
        cout << 0 << endl;
        return 0;
    }
    
    pre.resize(n);
    for (int i = 0; i < n; i++)
        pre[i] = i;
    
    for (int i = 0; i < n - 1; i++) {
        int u, v;
        cin >> u >> v;
        u--, v--;
        int pu = find(u), pv = find(v);
        if (pu != pv)
            pre[pu] = pv;
    }
    
    int cnt = 0;
    vector<int> size(n);
    for (int i = 0; i < n; i++) {
        if (pre[i] == i)
            cnt++;
        size[find(i)]++;
    }
    
    if (cnt > 2) {
        cout << 0 << endl;
    } else if (cnt == 1) {
        cout << n * (n - 1L) / 2 - (n - 1) << endl;
    } else {
        int a = -1, b = -1;
        for (int s : size) {
            if (s > 0) {
                if (a == -1)
                    a = s;
                else 
                    b = s;
            }
        }
        cout << (long long)a * b << endl;
    }
    return 0;
}

02.魔法糖果屋

问题描述

小美是一个贪吃的小朋友,有一天她发现了一个装满魔法糖果的糖果屋。糖果屋里一共有 n n n 颗糖果,第 i i i 颗糖果上写着数字 a i a_i ai

小美每天都必须吃一颗糖果,而且第 x x x 天必须吃一颗写着数字 x x x 的糖果。小美有一个魔法棒,可以用来改变一颗糖果上的数字,将其变成原来的两倍。但魔法棒只能使用一次。

小美想知道使用魔法棒一次之后,自己最多能连续吃到糖果的天数是多少呢?你能帮帮她吗?

输入格式

第一行包含一个正整数 n n n,表示糖果的数量。

第二行包含 n n n 个正整数 a 1 , a 2 , … , a n a_1, a_2, \ldots, a_n a1,a2,,an,表示每颗糖果上写的数字。

输出格式

输出一个整数,表示小美最多能连续吃到糖果的天数。

样例输入

4
1 1 3 5

样例输出

3

数据范围

  • 1 ≤ n ≤ 1 0 5 1 \le n \le 10^5 1n105
  • 1 ≤ a i ≤ 1 0 9 1 \le a_i \le 10^9 1ai109

题解

这道题可以用贪心的思想来解决。我们可以先将所有糖果按照数字从小到大排序,然后统计出每个数字出现的次数。

接下来,我们从左到右扫描排序后的糖果数组。如果当前数字 x x x 和前一个数字 y y y 满足 x = y + 1 x = y + 1 x=y+1,那么我们可以直接跳过,因为这两个数字之间没有断层。

如果 x > y + 1 x > y + 1 x>y+1,那么我们就找到了一个断层 [ y + 1 , x − 1 ] [y + 1, x - 1] [y+1,x1]。我们可以计算出这个断层的长度 x − y − 1 x - y - 1 xy1,更新答案。

最后,我们再考虑使用魔法棒的情况。对于每个数字 x x x,我们都可以将其变成 2 x 2x 2x,然后看看能否跟左右两侧的数字连成更长的序列。

具体来说,如果 2 x + 1 2x + 1 2x+1 存在,那么我们可以将 2 x 2x 2x 和右侧的数字连成一段;如果 2 x − 1 2x - 1 2x1 存在,那么我们可以将 2 x 2x 2x 和左侧的数字连成一段。选择其中更长的一段更新答案即可。

注意,如果 x x x 本身在原序列中出现了两次及以上,那么将其变成 2 x 2x 2x 之后,断层的长度还需要额外加 1 1 1

时间复杂度 O ( n log ⁡ n ) O(n \log n) O(nlogn),空间复杂度 O ( n ) O(n) O(n)

参考代码

  • Python
from typing import List
from collections import defaultdict

def maxConsecutiveDays(candies: List[int]) -> int:
    candies.sort()
    n = len(candies)
    cnt = defaultdict(int)
    for candy in candies:
        cnt[candy] += 1

    last = candies[0]
    left_range = {candies[0]: candies[0]}
    right_range = {}
    res = 0

    for i in range(n - 1):
        if candies[i + 1] != candies[i] + 1:
            left_range[last] = candies[i]
            right_range[candies[i]] = last
            res = max(res, candies[i] - last + 1)
            last = candies[i + 1]
            left_range[last] = candies[i + 1]

    if last != candies[-1]:
        left_range[last] = candies[-1]
        right_range[candies[-1]] = last
        res = max(res, candies[-1] - last + 1)

    for candy in candies:
        double_candy = candy * 2
        r = -1
        if candy in left_range and cnt[candy] < 2:
            r = left_range[candy]
            if r == candy:
                right_range.pop(r, None)
            else:
                right_range[r] = candy + 1

        ans = 1
        if double_candy + 1 in left_range:
            ans += left_range[double_candy + 1] - double_candy
        if double_candy - 1 in right_range:
            if cnt[candy] >= 2:
                ans += double_candy - right_range[double_candy - 1]
            else:
                ans += double_candy - max(right_range[double_candy - 1], candy + 1)
        res = max(res, ans)

        if r != -1:
            right_range[r] = candy

    return res
  • Java
import java.io.*;
import java.util.*;

public class Solution {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        int n = Integer.parseInt(br.readLine());
        String[] str = br.readLine().split(" ");
        int[] candies = new int[n];
        for (int i = 0; i < n; i++) {
            candies[i] = Integer.parseInt(str[i]);
        }
        System.out.println(maxConsecutiveDays(candies));
    }

    private static int maxConsecutiveDays(int[] candies) {
        Arrays.sort(candies);
        int n = candies.length;
        Map<Integer, Integer> cnt = new HashMap<>();
        for (int candy : candies) {
            cnt.put(candy, cnt.getOrDefault(candy, 0) + 1);
        }

        int last = candies[0];
        Map<Integer, Integer> leftRange = new HashMap<>();
        Map<Integer, Integer> rightRange = new HashMap<>();
        leftRange.put(candies[0], candies[0]);
        int res = 0;

        for (int i = 0; i < n - 1; i++) {
            if (candies[i + 1] != candies[i] + 1) {
                leftRange.put(last, candies[i]);
                rightRange.put(candies[i], last);
                res = Math.max(res, candies[i] - last + 1);
                last = candies[i + 1];
                leftRange.put(last, candies[i + 1]);
            }
        }

        if (last != candies[n - 1]) {
            leftRange.put(last, candies[n - 1]);
            rightRange.put(candies[n - 1], last);
            res = Math.max(res, candies[n - 1] - last + 1);
        }

        for (int candy : candies) {
            int doubleCandy = candy * 2;
            int r = -1;
            if (leftRange.containsKey(candy) && cnt.get(candy) < 2) {
                r = leftRange.get(candy);
                if (r == candy) {
                    rightRange.remove(r);
                } else {
                    rightRange.put(r, candy + 1);
                }
            }

            int ans = 1;
            if (leftRange.containsKey(doubleCandy + 1)) {
                ans += leftRange.get(doubleCandy + 1) - doubleCandy;
            }
            if (rightRange.containsKey(doubleCandy - 1)) {
                if (cnt.get(candy) >= 2) {
                    ans += doubleCandy - rightRange.get(doubleCandy - 1);
                } else {
                    ans += doubleCandy - Math.max(rightRange.get(doubleCandy - 1), candy + 1);
                }
            }
            res = Math.max(res, ans);

            if (r != -1) {
                rightRange.put(r, candy);
            }
        }

        return res;
    }
}
  • Cpp
#include <iostream>
#include <vector>
#include <algorithm>
#include <unordered_map>
using namespace std;

int maxDays(vector<int>& candies) {
    sort(candies.begin(), candies.end());
    int n = candies.size();
    unordered_map<int, int> cnt;
    for (int candy : candies) {
        cnt[candy]++;
    }

    int last = candies[0];
    unordered_map<int, int> leftRange, rightRange;
    leftRange[candies[0]] = candies[0];
    int res = 0;

    for (int i = 0; i < n - 1; i++) {
        if (candies[i + 1] != candies[i] + 1) {
            leftRange[last] = candies[i];
            rightRange[candies[i]] = last;
            res = max(res, candies[i] - last + 1);
            last = candies[i + 1];
            leftRange[last] = candies[i + 1];
        }
    }

    if (last != candies.back()) {
        leftRange[last] = candies.back();
        rightRange[candies.back()] = last;
        res = max(res, candies.back() - last + 1);
    }

    for (int candy : candies) {
        int doubleCandy = candy * 2;
        int r = -1;
        if (leftRange.count(candy) && cnt[candy] < 2) {
            r = leftRange[candy];
            if (r == candy) {
                rightRange.erase(r);
            } else {
                rightRange[r] = candy + 1;
            }
        }

        int ans = 1;
        if (leftRange.count(doubleCandy + 1)) {
            ans += leftRange[doubleCandy + 1] - doubleCandy;
        }
        if (rightRange.count(doubleCandy - 1)) {
            if (cnt[candy] >= 2) {
                ans += doubleCandy - rightRange[doubleCandy - 1];
            } else {
                ans += doubleCandy - max(rightRange[doubleCandy - 1], candy + 1);
            }
        }
        res = max(res, ans);

        if (r != -1) {
            rightRange[r] = candy;
        }
    }

    return res;
}

03.K小姐的树形公园设计

题目描述

K小姐是一名园林设计师,最近她接到了一个新的任务。任务是设计一个树形公园,公园由 n n n 个节点组成,节点之间由 n − 1 n-1 n1 条无向边连接。公园建成后,为了方便游客游览,K小姐需要在公园中选择一个节点建立一个游客中心。

建立游客中心后,公园会被分割成若干个连通块。为了避免某些连通块游客过于拥挤,K小姐希望最大的连通块的节点数量尽可能小。但是她发现要找到最优的游客中心位置并不容易。因此,她决定随机选择一个节点作为游客中心的位置。

现在,K小姐想知道,如果随机选择一个节点作为游客中心,最大连通块节点数量的期望值是多少呢?

输入格式

第一行包含一个正整数 n n n,表示树形公园的节点数量。

接下来 n − 1 n-1 n1 行,每行包含两个正整数 u u u v v v,表示节点 u u u 和节点 v v v 之间有一条无向边相连。

输出格式

输出一个实数,表示最大连通块节点数量的期望值,与标准答案误差不超过 1 0 − 6 10^{-6} 106 即视为正确。

样例输入

2
1 2

样例输出

1.000000000

样例说明

无论选择节点 1 还是节点 2 作为游客中心,最大连通块的节点数量均为 1。

数据范围

1 ≤ n ≤ 1 0 5 1 \le n \le 10^5 1n105
1 ≤ u , v ≤ n 1 \le u, v \le n 1u,vn

题解

本题可以使用树形 DP 的思想求解。我们可以对树进行一次 DFS 遍历,在遍历的过程中维护以每个节点为根的子树的大小。

对于每个节点 u u u,我们可以计算出以 u u u 为游客中心时,最大连通块的节点数量。具体地,设 f u f_u fu 表示以 u u u 为根的子树的节点数量,则最大连通块的节点数量为 max ⁡ ( n − f u , max ⁡ v ∈ s o n ( u ) f v ) \max(n-f_u, \max\limits_{v \in son(u)} f_v) max(nfu,vson(u)maxfv),其中 s o n ( u ) son(u) son(u) 表示 u u u 的所有子节点。

这样,我们可以在 DFS 的过程中,计算出每个节点作为游客中心时最大连通块的节点数量,然后将它们加和并除以 n n n,即可得到最大连通块节点数量的期望值。

时间复杂度 O ( n ) O(n) O(n),空间复杂度 O ( n ) O(n) O(n)

参考代码

  • Python
import sys
sys.setrecursionlimit(int(1e5 + 5))

n = int(input())
g = [[] for _ in range(n+1)]
for _ in range(n-1):
    a, b = map(int, input().split())
    g[a].append(b)
    g[b].append(a)

r = 1 / n
res = 0
f = [0] * (n+1)

def dfs(u, pre):
    global res
    f[u] = 1
    max_sz = 0
    for i in g[u]:
        if i != pre:
            dfs(i, u)
            f[u] += f[i]
            max_sz = max(max_sz, f[i])
    max_sz = max(max_sz, n - f[u])
    res += max_sz * r

dfs(1, 0)
print(f"{res:.10f}")
  • Java
import java.io.*;
import java.util.*;

public class Main {
    static int n;
    static List<Integer>[] g;
    static double r, res;
    static int[] f;

    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        n = Integer.parseInt(br.readLine());
        g = new List[n+1];
        for (int i = 1; i <= n; i++) {
            g[i] = new ArrayList<>();
        }
        for (int i = 0; i < n-1; i++) {
            String[] s = br.readLine().split(" ");
            int a = Integer.parseInt(s[0]);
            int b = Integer.parseInt(s[1]);
            g[a].add(b);
            g[b].add(a);
        }
        r = 1.0 / n;
        res = 0;
        f = new int[n+1];
        dfs(1, 0);
        System.out.printf("%.10f\n", res);
    }

    static void dfs(int u, int pre) {
        f[u] = 1;
        int maxSz = 0;
        for (int i : g[u]) {
            if (i != pre) {
                dfs(i, u);
                f[u] += f[i];
                maxSz = Math.max(maxSz, f[i]);
            }
        }
        maxSz = Math.max(maxSz, n - f[u]);
        res += maxSz * r;
    }
}
  • Cpp
#include <bits/stdc++.h>
using namespace std;

const int N = 1e5 + 5;
int n;
vector<int> g[N];
double r, res;
int f[N];

void dfs(int u, int pre) {
    f[u] = 1;
    int maxSz = 0;
    for (int i : g[u]) {
        if (i != pre) {
            dfs(i, u);
            f[u] += f[i];
            maxSz = max(maxSz, f[i]);
        }
    }
    maxSz = max(maxSz, n - f[u]);
    res += maxSz * r;
}

int main() {
    cin >> n;
    for (int i = 0; i < n-1; i++) {
        int a, b;
        cin >> a >> b;
        g[a].push_back(b);
        g[b].push_back(a);
    }
    r = 1.0 / n;
    res = 0;
    dfs(1, 0);
    printf("%.10lf\n", res);
    return 0;
}

04.LYA的光纤网络设计

问题描述

LYA是一家通信公司的工程师,她正在设计一个新的光纤网络。这个网络需要在一条直线上建设 5 5 5 个信号塔,用于传输信号。

直线上有 n n n 个可以建设信号塔的位置,其中第 1 1 1 个位置和第 n n n 个位置必须建设信号塔。每个位置都有一个建设强度 a i a_i ai,代表在该位置建设信号塔的设备质量。

信号在两个信号塔之间传输时,信号强度会发生变化。信号强度的变化值与两个信号塔的建设强度之和成正比,与两个信号塔之间的距离成反比。具体来说,如果两个信号塔的建设强度分别为 a a a b b b,它们之间的距离为 d d d,则一个强度为 x x x 的信号经过这两个信号塔传输后,强度将变为 x × a + b d x \times \frac{a+b}{d} x×da+b

LYA需要在剩余的 n − 2 n-2 n2 个位置中选择 3 3 3 个建设信号塔,使得从最左侧的信号塔传输到最右侧信号塔时,信号的强度尽可能大。假设最左侧信号塔发出的初始信号强度为 1 1 1。请你帮助LYA设计出这个光纤网络,计算出信号强度的最大值。

输入格式

第一行包含一个正整数 n n n,表示可以建设信号塔的位置数量。

第二行包含 n n n 个正整数 x 1 , x 2 , … , x n x_1, x_2, \ldots, x_n x1,x2,,xn,其中 x i x_i xi 表示第 i i i 个位置的坐标。

第三行包含 n n n 个正整数 a 1 , a 2 , … , a n a_1, a_2, \ldots, a_n a1,a2,,an,其中 a i a_i ai 表示在第 i i i 个位置建设信号塔的建设强度。

输出格式

输出一个实数,表示信号强度的最大值。与标准答案误差不超过 1 0 − 6 10^{-6} 106 即视为正确。

样例输入

6
1 3 5 7 8 10
7 6 9 5 1 3

样例输出

910.0000000000

样例说明

在第 1 1 1 2 2 2 3 3 3 4 4 4 6 6 6 这五个位置建设信号塔是最优方案。第 1 1 1 个信号塔发出强度为 1 1 1 的信号:

  • 传输到第 2 2 2 个信号塔后,信号强度变为 6.5 6.5 6.5
  • 传输到第 3 3 3 个信号塔后,信号强度变为 48.75 48.75 48.75
  • 传输到第 4 4 4 个信号塔后,信号强度变为 341.25 341.25 341.25
  • 传输到第 6 6 6 个信号塔后,信号强度变为 910 910 910

可以证明这是最优的建设方案。

数据范围

5 ≤ n ≤ 2000 5 \le n \le 2000 5n2000
1 ≤ x i , a i ≤ 1 0 4 1 \le x_i, a_i \le 10^4 1xi,ai104
x 1 < x 2 < … < x n x_1 < x_2 < \ldots < x_n x1<x2<<xn

题解

本题可以使用动态规划求解。我们可以定义两个数组 f f f g g g,其中:

  • f [ i ] f[i] f[i] 表示从第 1 1 1 个信号塔传输到第 i i i 个信号塔的最大信号强度。
  • g [ i ] g[i] g[i] 表示从第 i i i 个信号塔传输到第 n n n 个信号塔的最大信号强度。

我们可以先计算出 f f f 数组的值。对于每个位置 i i i,枚举 1 ≤ j < i 1 \le j < i 1j<i,更新 f [ i ] f[i] f[i] 的值:

f [ i ] = max ⁡ 1 ≤ j < i { a 1 + a j x j − x 1 × a i + a j x i − x j } f[i] = \max\limits_{1 \le j < i} \left\{\frac{a_1 + a_j}{x_j - x_1} \times \frac{a_i + a_j}{x_i - x_j}\right\} f[i]=1j<imax{xjx1a1+aj×xixjai+aj}

类似地,我们可以计算出 g g g 数组的值。对于每个位置 i i i,枚举 i < j ≤ n i < j \le n i<jn,更新 g [ i ] g[i] g[i] 的值:

g [ i ] = max ⁡ i < j ≤ n { a n + a j x n − x j × a j + a i x j − x i } g[i] = \max\limits_{i < j \le n} \left\{\frac{a_n + a_j}{x_n - x_j} \times \frac{a_j + a_i}{x_j - x_i}\right\} g[i]=i<jnmax{xnxjan+aj×xjxiaj+ai}

最后,我们枚举中间的信号塔位置 i i i,计算 f [ i ] × g [ i ] f[i] \times g[i] f[i]×g[i] 的最大值即为答案。

时间复杂度为 O ( n 2 ) O(n^2) O(n2),空间复杂度为 O ( n ) O(n) O(n)

参考代码

  • Python
def solve():
    tower_count = int(input())
    positions = list(map(int, input().split()))
    strengths = list(map(int, input().split()))

    left_dp = [0] * tower_count
    right_dp = [0] * tower_count

    for i in range(1, tower_count):
        for j in range(1, i):
            left_dp[i] = max(left_dp[i], (strengths[0] + strengths[j]) / (positions[j] - positions[0]) * (strengths[i] + strengths[j]) / (positions[i] - positions[j]))

    for i in range(tower_count - 2, -1, -1):
        for j in range(i + 1, tower_count - 1):
            right_dp[i] = max(right_dp[i], (strengths[-1] + strengths[j]) / (positions[-1] - positions[j]) * (strengths[j] + strengths[i]) / (positions[j] - positions[i]))

    max_strength = 0
    for i in range(2, tower_count - 2):
        max_strength = max(max_strength, left_dp[i] * right_dp[i])

    print(f"{max_strength:.6f}")

solve()
  • Java
import java.util.Scanner;

public class Solution {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int towerCount = scanner.nextInt();
        int[] positions = new int[towerCount];
        int[] strengths = new int[towerCount];
        
        for (int i = 0; i < towerCount; i++) {
            positions[i] = scanner.nextInt();
        }
        for (int i = 0; i < towerCount; i++) {
            strengths[i] = scanner.nextInt();
        }
        
        double[] leftDP = new double[towerCount];
        double[] rightDP = new double[towerCount];
        
        for (int i = 1; i < towerCount; i++) {
            for (int j = 1; j < i; j++) {
                leftDP[i] = Math.max(leftDP[i], (strengths[0] + strengths[j]) * 1.0 / (positions[j] - positions[0]) * (strengths[i] + strengths[j]) / (positions[i] - positions[j]));
            }
        }
        
        for (int i = towerCount - 2; i >= 0; i--) {
            for (int j = i + 1; j < towerCount - 1; j++) {
                rightDP[i] = Math.max(rightDP[i], (strengths[towerCount - 1] + strengths[j]) * 1.0 / (positions[towerCount - 1] - positions[j]) * (strengths[j] + strengths[i]) / (positions[j] - positions[i]));
            }
        }
        
        double maxStrength = 0;
        for (int i = 2; i < towerCount - 2; i++) {
            maxStrength = Math.max(maxStrength, leftDP[i] * rightDP[i]);
        }
        
        System.out.printf("%.6f\n", maxStrength);
    }
}
  • Cpp
#include <iostream>
#include <vector>
#include <iomanip>

using namespace std;

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int towerCount;
    cin >> towerCount;
    vector<int> positions(towerCount);
    vector<int> strengths(towerCount);

    for (int i = 0; i < towerCount; i++) {
        cin >> positions[i];
    }
    for (int i = 0; i < towerCount; i++) {
        cin >> strengths[i];
    }

    vector<double> leftDP(towerCount, 0);
    vector<double> rightDP(towerCount, 0);

    for (int i = 1; i < towerCount; i++) {
        for (int j = 1; j < i; j++) {
            leftDP[i] = max(leftDP[i], 1.0 * (strengths[0] + strengths[j]) / (positions[j] - positions[0]) * (strengths[i] + strengths[j]) / (positions[i] - positions[j]));
        }
    }

    for (int i = towerCount - 2; i >= 0; i--) {
        for (int j = i + 1; j < towerCount - 1; j++) {
            rightDP[i] = max(rightDP[i], 1.0 * (strengths[towerCount - 1] + strengths[j]) / (positions[towerCount - 1] - positions[j]) * (strengths[j] + strengths[i]) / (positions[j] - positions[i]));
        }
    }

    double maxStrength = 0;
    for (int i = 2; i < towerCount - 2; i++) {
        maxStrength = max(maxStrength, leftDP[i] * rightDP[i]);
    }

    cout << fixed << setprecision(6) << maxStrength << endl;

    return 0;
}

写在最后

📧 KK这边最近正在收集近一年互联网各厂的笔试题汇总,如果有需要的小伙伴可以关注后私信一下 KK领取~

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/506661.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

基于Python的口罩佩戴识别的设计与实现(UI界面+MySQL数据库+YOLOv5+训练数据集+开题报告+中期检查+论文)

本文旨在基于Python开发一种口罩佩戴识别系统&#xff0c;通过深度学习技术实现对口罩佩戴情况的准确检测。采用了YOLOv5系列目标检测算法作为基础模型&#xff0c;并结合迁移学习进行训练和优化。同时&#xff0c;为了提供更好的用户体验&#xff0c;本系统还设计了用户登录注…

“315晚会”中的“网络水军”是什么?

水军一词&#xff0c;源自网络用语&#xff0c;通常指的是一群在网络上被雇佣来进行特定活动的人群。他们的主要任务通常是在各种社交媒体平台、论坛或者评论区发表大量的帖子、评论或者回复&#xff0c;以此来达到某种特定的目的。这些目的可能包括提升某个产品、服务或者个人…

【机器学习300问】58、什么是词袋模型和N-gram模型?

词袋模型&#xff08;Bag of Words, BoW&#xff09;和N-gram模型主要用于早期的自然语言处理任务&#xff0c;上文中我介绍了机器是如何读懂文本的四个阶段&#xff0c;这篇文章带大家来看看在不同阶段中会用到的两个模型——词袋模型和N-gram模型。如果没有读过我之前的文章&…

纯小白蓝桥杯备赛笔记--DAY9(搜索)

文章目录 三道例题学会DFS剪枝什么是剪枝数字王国之军训排队--2942特殊的三角形--3008特殊的多边形--3075 DFS基础回溯简介回溯法模版例题N皇后--1508小朋友崇拜圈--182全球变暖--178 记忆化搜索简介斐波那契数列混境之地5-3820地宫取宝-216 三道例题学会DFS剪枝 什么是剪枝 …

云计算迎变局:阿里云、腾讯云“各有千秋”

毋庸置疑&#xff0c;无论在什么时候什么行业&#xff0c;低价策略都是一柄利器。比如&#xff0c;在电商行业&#xff0c;除了拼多多将低价策略贯彻到底之外&#xff0c;淘宝、京东也将性价比作为发力重点&#xff0c;并通过补贴、秒杀等方式&#xff0c;再度强调自身的“价格…

Pygame基础8-碰撞

Collisions 在Pygame中&#xff0c;我们使用矩形来移动物体&#xff0c;并且用矩形检测碰撞。 colliderect检测两个矩形是否碰撞&#xff0c;但是没法确定碰撞的方向。 Rect1.colliderect(Rect2) # collision -> return Ture # else -> return Falsecollidepoint可以…

数据结构——遍历二叉树和线索二叉树,树和森林

目录 1.遍历的算法实现 1.先序遍历 代码示例&#xff1a; 2.中序遍历 代码示例&#xff1a; 3.后序遍历 代码示例&#xff1a; 4.遍历算法的分析 2.遍历二叉树的非递归算法 1.中序遍历非递归算法 代码示例&#xff1a; 3.二叉树的层次遍历 代码示例&#xff1a; 4.二…

C#/.NET/.NET Core优秀项目和框架2024年3月简报

前言 公众号每月定期推广和分享的C#/.NET/.NET Core优秀项目和框架&#xff08;每周至少会推荐两个优秀的项目和框架当然节假日除外&#xff09;&#xff0c;公众号推文中有项目和框架的介绍、功能特点、使用方式以及部分功能截图等&#xff08;打不开或者打开GitHub很慢的同学…

BUUCTF [安洵杯 2019]吹着贝斯扫二维码 1

BUUCTF:https://buuoj.cn/challenges 题目描述&#xff1a; 得到的 flag 请包上 flag{} 提交。 密文&#xff1a; 下载附件解压&#xff0c;得到很多没有后缀的文件和一个ZIP压缩包。 解题思路&#xff1a; 1、首先&#xff0c;查看ZIP压缩包&#xff0c;发现有密码&#xf…

GreatSQL 优化技巧:将 MINUS 改写为标量子查询

GreatSQL 优化技巧&#xff1a;将 MINUS 改写为标量子查询 前言 minus 指令运用在两个 SQL 语句上&#xff0c;取两个语句查询结果集的差集。它先找出第一个 SQL 所产生的结果&#xff0c;然后看这些结果有没有在第二个 SQL 的结果中&#xff0c;如果在&#xff0c;那这些数据…

2024年山东临沂教育人才引进报名流程

2024年山东临沂教育人才引进报名流程

表单全选反选(前端)

1.Html和JavaScript <table><tr><th class"allCheck"><input type"checkbox" name"" id"checkAll"> <span class"all">全选</span></th><th>商品</th><th>商…

Hive函数笔试题(简单)

第1题 有如下的用户访问数据 userId visitDate visitCount u01 2017/1/21 5 u02 2017/1/23 6 u03 2017/1/22 8 u04 2017/1/20 3 u01 2017/1/23 6 u01 2017/2/21 8 u02 2017/1/23 6 u01 2017/2/22 4 要求使用SQL统计出每个用户的累积访问次数&…

Qt中继承QCheckBox的类结合QTableWidget实现多选并且每个多选的id都不一样

1.相关描述 继承QCheckBox的类MyCheckBox&#xff0c;利用QTableWidget的setCellWidget方式添加MyCheckBox类的对象 2.相关页面 3.相关代码 mycheckbox.h #ifndef MYCHECKBOX_H #define MYCHECKBOX_H#include <QCheckBox> #include <QObject>class MyCheckBox : pu…

DSSS-UQPSK学习笔记

文章目录 非平衡四相键控-直接序列扩频&#xff08;UQPSK-DSSS&#xff09;信号因其能同时传输两路不同功率、不同速率信号的特点&#xff0c;在需要图象和数据综合业务传输的领域得到了广泛应用。 系统信号的调制方式为非平衡四相键控&#xff08;Unbalanced Quadrature Phase…

SpringBoot 整合Redis第1篇

SpringBoot是一个开发框架&#xff0c;Redis是一个高性能的键值存储数据库&#xff0c; 常用于缓存、会话管理、消息队列等应用场景。 定义 Redis是什么&#xff1f; 它是一个存储层级&#xff0c; 在实际项目中&#xff0c;位于关系数据库之上&#xff0c; 类似Android分为5…

vue3封装Element导航菜单

1. 导航外层布局 AsideView.vue <template><el-menu:default-active"defaultActive"class"my-menu":collapse"isCollapse":collapse-transition"false"open"handleOpen"close"handleClose"><menu…

【机器学习入门】拥抱人工智能,从机器学习开始

拥抱人工智能&#xff0c;从机器学习开始 目录&#xff1a; 1. 机器学习&#xff1a;一种实现人工智能的方法2. 机器学习算法&#xff1a;是使计算机具有智能的关键3. Anaconda&#xff1a;初学Python、入门机器学习的首选4. 总结 转载链接&#xff1a;文章-阿里云开发者社区…

PyTorch深度学习入门-1

PyTorch深度学习快速入门教程&#xff08;绝对通俗易懂&#xff01;&#xff09;【小土堆】_哔哩哔哩_bilibili \ PyTorch 和 TensorFlow 是两个深度学习框架&#xff0c;TensorBoard 是 TensorFlow 提供的可视化工具&#xff0c;Transforms是 PyTorch 中用于数据预处理的工具…

可视化图表:K线图,快速搞清价格波动。

2023-08-21 21:20贝格前端工场 Hi&#xff0c;我是贝格前端工场的老司机&#xff0c;本文分享可视化图表设计的K线图设计&#xff0c;欢迎老铁持续关注我们。 一、K线图的含义 K线图&#xff08;K Line Chart&#xff09;是一种常用于股票、期货等金融市场的可视化图表&…