*3-3牛客网 重新排列

本文解析了一道涉及字符串处理和尺取法的经典编程题,重点讲解了如何通过`solve`函数判断元素个数,并利用尺取法技巧高效寻找满足条件的子串。通过实例代码展示了如何避免暴力搜索,提高解题效率。

题目描述

在这里插入图片描述

样例

在这里插入图片描述

源代码

#include<iostream>
using namespace std;
string s = "puleyaknoi";
const int maxn = 1e5 + 10;
const int inf = 0x3f3f3f3f;
int a[maxn], b[maxn];
char c[maxn];
int solve() //判断函数,判断元素的个数是否满足题目要求
{
    for (int i = 0; i < 26; ++i)
        if (a[i] < b[i])
            return false;
    return true;
}
int main()
{
    int t;
    scanf("%d", &t);
    for (int i = 0; i < s.size(); ++i)
        b[s[i] - 'a']++; //记录目标子串每个元素的个数
    getchar();           //获取回车,防止干扰后序字符串的输入
    for (int i = 1; i <= t; ++i)
    {
        scanf("%s", c);
        int lc = strlen(c);
        int r = 0, ans = inf;
        for (int l = 0; l < lc; ++l)
        {
            while (!solve() && r < lc) //寻找目标子串,r一直右移直到当前区间[l,r]内出现目标子串
                a[c[r++] - 'a']++;
            if (solve()) //一旦出现目标子串就记录一下此时的最小区间
                ans = min(ans, r - l);
            a[c[l] - 'a']--; //l不断的右移,每次都除去一个最左边的元素,目标就是找到最小区间
        }
        if (ans == inf) //没有找到
            puts("-1");
        else
            printf("%d\n", ans);
    }
    return 0;
}

关于这题

刚刚开始看到这个题目的时候,感觉很不好做,唯一想到的方法就是暴力,但是很显然暴力一定会超时,一看题解发现是个尺取法的经典例题,无奈这种题目做的比较少,看懂代码也花了一定的时间,也参考了博客理解尺取法的概念与用法。具体题目分析见代码
题解的关键就是 solve 这个判断函数

### 如何在牛客网上使用SQL查询每个月播放量前3的歌曲 为了实现这一目标,可以基于题目描述中的数据需求构建解决方案。以下是详细的分析和代码示例。 #### 数据准备与逻辑解析 根据引用的内容[^1],我们需要筛选满足以下条件的数据: - 用户年龄范围为 **18-25 岁**- 时间限定为 **2022 年**- 歌手限定为 **周杰伦** 的歌曲。 - 统计每月每首歌的播放次数,并按降序排列取 Top 3- 如果播放次数相同,则依据 `song_id` 排列顺序决定优先级。 为此,我们可以采用窗口函数来完成分组排名操作。具体步骤如下: 1. 过滤符合条件的数据(如时间、歌手、用户年龄段等)。 2. 使用聚合函数计算每首歌的播放次数。 3. 利用窗口函数 `ROW_NUMBER()` 或者 `RANK()` 对结果进行排序并标记排名。 4. 提取出排名为前 3 的记录。 下面是具体的 SQL 实现代码: ```sql WITH filtered_data AS ( SELECT song_id, MONTH(play_time) AS month_num, COUNT(*) AS play_count FROM user_plays WHERE YEAR(play_time) = 2022 -- 条件:仅限于2022年的播放记录 AND artist_name = &#39;周杰伦&#39; -- 条件:仅限周杰伦的歌曲 AND age BETWEEN 18 AND 25 -- 条件:用户的年龄区间为18到25岁 GROUP BY song_id, MONTH(play_time) ), ranked_songs AS ( SELECT *, ROW_NUMBER() OVER (PARTITION BY month_num ORDER BY play_count DESC, song_id ASC) AS rank_num FROM filtered_data ) SELECT month_num, song_id, play_count FROM ranked_songs WHERE rank_num <= 3; -- 取出每个月播放量Top3的歌曲 ``` 上述代码解释如下: - 首先通过子查询过滤掉不符合条件的数据,并对剩余部分按照月份和歌曲 ID 聚合得到播放次数。 - 然后利用窗口函数 `ROW_NUMBER()` 按照播放次数降序以及 `song_id` 升序分配排名号给每一行。 - 最终选取排名小于等于 3 的那些记录作为最终输出结果。 此方法能够高效解决此类问题,同时也符合实际业务场景下的复杂度要求[^2]。 --- ### 注意事项 如果存在其他约束或者特殊规则,请进一步补充说明以便调整方案适应更多情况。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值