【算法题】小红书2023秋招提前批算法真题解析

题目来源

红书2023秋招提前批算法真题解析

T1:5900: 【DP】小红书2023秋招提前批-连续子数组最大和

https://oj.algomooc.com/problem.php?id=5900

在这里插入图片描述

做这题之前可以先做一下力扣中的:53. 最大子数组和 作为前置知识。

每次询问就是一批输入数据。
定义 dp 数组 [n][2] 表示 以 a[i] 为结尾且选 a[i] 的子数组的最大和是多少,第二维的 0 和 1 分别表示当前有没有将元素换成 x 的操作。

import java.util.*;

class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int t = sc.nextInt();
        while (t-- != 0) {
            int n = sc.nextInt(), x = sc.nextInt();
            int[] a = new int[n];
            int[][] dp = new int[n][2];     // 没变和变了
            
            for (int i = 0; i < n; ++i) a[i] = sc.nextInt();
            
            dp[0][0] = a[0];
            dp[0][1] = x;
            int ans = Math.max(dp[0][0], dp[0][1]);
            for (int i = 1; i < n; ++i) {
                dp[i][0] = Math.max(dp[i - 1][0] + a[i], a[i]);
                dp[i][1] = Math.max(dp[i - 1][1] + a[i], dp[i - 1][0] + x);
                ans = Math.max(ans, Math.max(dp[i][0], dp[i][1]));
            }
            System.out.println(ans);
        }
    }
}

5801: 【二分查找】小红书2023秋招提前批-精华帖子

https://oj.algomooc.com/problem.php?id=5801
在这里插入图片描述

这道题目很像:2271. 毯子覆盖的最多白色砖块数

解法1——排序+滑动窗口

该解法的解析见:【LeetCode周赛】2022上半年题目精选集——双指针

在这里插入图片描述

import java.util.*;

class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt(), m = sc.nextInt(), k = sc.nextInt();
        int[][] e = new int[m][2];
        for (int i = 0; i < m; ++i) {
            e[i][0] = sc.nextInt();
            e[i][1] = sc.nextInt();
        }
        // 排序
        Arrays.sort(e, (x, y) -> x[0] - y[0]);
        int ans = 0, sum = 0;
        // 开滑(枚举右端点,尝试移动左端点)
        for (int l = 0, r = 0; r < m; ++r) {
            sum += e[r][1] - e[r][0];
            // 把超过的移出去
            while (e[r][1] - e[l][1] > k) {
                sum -= e[l][1] - e[l][0];
                l++;
            }
            // 检查第一个区间是否占完了
            if (e[r][1] - k > e[l][0]) {
                ans = Math.max(ans, sum - (e[r][1] - k - e[l][0]));
            } else ans = Math.max(ans, sum);
        }
        System.out.println(ans);
    }
}

解法2——前缀和 + 二分查找

前缀和是为了快速求出一个区间中的精华区一共有多少个精华帖子。
二分查找是为了快速找出以某一个精华区为起点时,最后一个被覆盖到的精华区的索引。

import java.util.*;

class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt(), m = sc.nextInt(), k = sc.nextInt();
        int[][] e = new int[m][2];
        int[] s = new int[m + 1];
        for (int i = 0; i < m; ++i) {
            e[i][0] = sc.nextInt();
            e[i][1] = sc.nextInt();
            s[i + 1] = s[i] + e[i][1] - e[i][0];
        }
        
        int ans = 0;
        for (int i = 0; i < m; ++i) {   // 枚举每个瓷砖作为起始瓷砖
            // 使用二分查找最后一个被覆盖到的瓷砖
            int l = i, r = m - 1;
            while (l < r) {
                int mid = l + r + 1 >> 1;
                if (e[i][0] + k < e[mid][0]) r = mid - 1;
                else l = mid;
            }
            ans = Math.max(ans, s[l] - s[i] + Math.min(e[i][0] + k, e[l][1]) - e[l][0]);
        }
        System.out.println(ans);
    }
}

5000: 【模拟】小红书2023秋招提前批-小红的数组构造

在这里插入图片描述

解法——数学

冷静思考!—— 最后的数组是这样的 k , 2 ∗ k , 3 ∗ k , . . . n ∗ k {k,2*k,3*k,...n*k} k,2k,3k,...nk

使用等差数列求和公式得答案为 k ∗ n ∗ ( n + 1 ) / 2 k * n * (n + 1) / 2 kn(n+1)/2

import java.util.*;

class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt(), k = sc.nextInt();
        System.out.println((long)k * n * (n + 1) / 2);
    }
}

记得要转 long 否则答案会溢出 int。

5300: 【哈希表】小红书2023秋招-推荐系统

https://oj.algomooc.com/problem.php?id=5300#
在这里插入图片描述

按照题目要求读取数据,存入哈希表做计数统计。
将结果放入列表,自定义筛选和排序即可。

import java.util.*;

class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        Map<String, Integer> cnt = new HashMap<>();
        while (sc.hasNext()) {
            String word = sc.next();
            cnt.merge(word, 1, Integer::sum);
        }
        List<Pair> ls = new ArrayList<>();
        for (Map.Entry<String, Integer> entry: cnt.entrySet()) {
            if (entry.getValue() >= 3) {
                ls.add(new Pair(entry.getKey(), entry.getValue()));
            }
        }
        Collections.sort(ls, (x, y) -> {
            int c1 = x.value, c2 = y.value;
            return c1 != c2? c2 - c1: x.key.compareTo(y.key);
        });
        for (Pair p: ls) {
            System.out.println(p.key);
        }
    }
}


class Pair {
    String key;
    Integer value;
    Pair(String key, Integer value) {
        this.key = key;
        this.value = value;
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Wei *

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值