草庐IT

蓝桥杯真题:字串排序

lsgoose 2023-08-15 原文

输入输出样例

示例 1

输入

4

输出

bbaa

示例 2

输入

100

输出

jihgfeeddccbbaa

运行限制

  • 最大运行时间:1s
  • 最大运行内存: 256M

思路:把这题拆成两个部分,第一个部分是确定最小长度,第二个部分是确定最小字符序

求最小长度

给出一个定义:交换的次数等于字符串的逆序对个数

例如ba,b比a大,逆序对个数是1,cba,b产生1个,a产生两个,逆序对是3。

于是很自然想到,在长度相同的情况下,逆序数越多,交换次数越多。为了保证逆序对尽可能的多,我们构造的字符串尽量是递减序列。

例如:

长度 len = 1时,我们构造的字符串要形如 a,逆序对个数为 0,交换次数为 0。

当长度 len = 2 时,我们构造的字符串要形如 ba,逆序对个数 1,交换次数为 1。

当长度 len=3 时,我们构造的字符串要形如 cba,逆序对个数为 3,交换次数为 3。

当长度 len=26时,我们构造的字符串得为 zyxwvutsrqponmlkjihgfedcba,逆序对个数为 325,交换次数为 325。

题目中的要求是V最大是10000,所以这个325是远远达不到要求的,所以势必有字符是要重复的。

那接下来我们考虑一个新的问题,在只有a,b,c的情况下,构造出一个长度为7,交换次数最多的字符串,怎么想呢?给定一个字符串,插入一个字符,逆序对增加的个数=前面比该字符小的字符数量 + 后面比该字符大的字符数量。所以呢,每次我们只要插入当前字符串中字符个数最少的字符就好了~所以我们有三种方案cccbbaa,ccbbbaa,ccbbaaa,字符序最小的话,当然是ccbbaaa了。

不过我们现在的问题是:在给定的长度为len的字符串,其最大逆序数个数是多少?为什么要求这个呢,因为当我们找到第一个长度len,其最大逆序数>=V时,我们就可以从这个长度产生字符序最小的字符串,而这个len也就是最小的长度。

那回到正题,有了上边的例子,我们明白了,一个长度为len的字符串里边,要达到最大逆序数,每个字符个数最好是平均分配的,又要字符序最小,个数多的应该是字符顺序小的。字符数量为len/26+1(向下取整)的字符有len%26​个,字符数量为len/26的字符有26-len%26个。那给定len,最大的交换次数的公式如下所示:

解释一下每一项吧,拿前半部分来说,含义是抽取每一个长度为len/26+1的字母,用这个长度乘剩下的长度也就是len-(len/26+1),这样就是该字母产生的逆序对,由于每个

代码如下所示:

int get_max(int len){
    return ((len - (len / 26 + 1)) * (len / 26 + 1) * (len % 26) + (26 - len % 26) * (len / 26) * (len - len / 26)) / 2;
}

确定最小字符序

在上面我们已经求出了最小的长度len,也就是第一个len使得max(len)=X>=V,那么我们肯定也可以改变字符顺序,构造出逆序对个数为X,X-1......0的字符串。

于是我们可以从字符串的第一个位置往后构造,具体为:

从小到大枚举字符ch(ch∈[a~z]),判断当前位置的字符为ch是否可以构造出长度为len,且逆序对大于等于V的字符串。

  • 我们设当前位置为pos,那么1~pos-1的位置已经构造好了,那么当前选择字符ch可以新增的逆序对个数就是1~pos-1中比ch大的字符个数
  • 对于pos+1~len的位置,我们总共要添加len-pos个字符,且要保证这些字符能够产生最多的逆序对。我们可以暴力点一个一个插入。若插入字符x,则产生的逆序对个数(最多)=(1~pos中大于x的字符数量)+(pos后添加的总字符数量-字符x的数量)

最后若第pos个位置放置ch可以构造出长度为len,逆序对个数大于等于V的字符串,我们就令第pos个位置的字符串为ch,继续构造,否则在pos放下一个字符ch+1,继续构造。

具体代码如下所示:

#include<bits/stdc++.h>
using namespace std;
int V , len , now , cnt[27] , sum[27];
int get_max(int len){
    return ((len - (len / 26 + 1)) * (len / 26 + 1) * (len % 26) + (26 - len % 26) * (len / 26) * (len - len / 26)) / 2;
}
bool check(int x , int n){
    memset(cnt , 0 , sizeof(cnt));//cnt记录后面n个位置放置的对应字符数量
    int add1 = 0 , add2 = 0;
    for(int j = 26 ; j >= x + 1 ; j --) add1 += sum[j];//1~pos-1里边比当前插入字符大的字符数量
    sum[x] ++ ;//当前字符数量增加1
    for(int L = 1 ; L <= n ; L ++){
        //ma保存最大逆序对个数 L-1-cnt[j]+num
        //L-1-cnt[j]是当前字符之后的比当前字符小的字符数量的最大值
        //num是1~pos+L-1前的比当前放置字符字典序大的字符数量
        int ma = -1 , pos = 0 , num = 0;
        for(int j = 26 ; j >= 1 ; j --){
            if(L - 1 - cnt[j] + num > ma){
                ma = L - 1 - cnt[j] + num;
                pos = j;
            }
            num += sum[j];
        }
        add2 += ma , cnt[pos] ++;
    }
    if(now + add1 + add2 >= V) {
        now += add1;
        return true;
    }
    else {
        sum[x] -- ;
        return false;
    }
}
signed main()
{
    string ans = "";
    cin >> V;
    for(int i = 1 ; ; i ++) {
        if(get_max(i) >= V){
            len = i;
            break ;
        }
    }
    for(int i = 1 ; i <= len ; i ++){
        for(int j = 1 ; j <= 26 ; j ++){
            if(check(j , len - i)){
                ans += char(j + 'a' - 1);
                break ;
            }
        }
    }
    cout << ans << '\n';
    return 0;
}

转载自蓝桥云课中的思路~

其实其中第pos之后的每个位置选择一个字符颇有点动态规划的味道,很nb的思路很好的一题~

有关蓝桥杯真题:字串排序的更多相关文章

  1. ruby-on-rails - 需要帮助最大化多个相似对象中的 3 个因素并适当排序 - 2

    我需要用任何语言编写一个算法,根据3个因素对数组进行排序。我以度假村为例(如Hipmunk)。假设我想去度假。我想要最便宜的地方、最好的评论和最多的景点。但是,显然我找不到在所有3个中都排名第一的方法。Example(assumingthereare20importantattractions):ResortA:$150/night...98/100infavorablereviews...18of20attractionsResortB:$99/night...85/100infavorablereviews...12of20attractionsResortC:$120/night

  2. ruby-on-rails - 在具有 ActiveRecord 条件的相关模型中按字段排序 - 2

    我正在尝试按Rails相关模型中的字段进行排序。我研究的所有解决方案都没有解决如果相关模型被另一个参数过滤?元素模型classItem相关模型:classPriority我正在使用where子句检索项目:@items=Item.where('company_id=?andapproved=?',@company.id,true).all我需要按相关表格中的“位置”列进行排序。问题在于,在优先级模型中,一个项目可能会被多家公司列出。因此,这些职位取决于他们拥有的company_id。当我显示项目时,它是针对一个公司的,按公司内的职位排序。完成此任务的正确方法是什么?感谢您的帮助。PS-我

  3. ruby - 按数字(从大到大)然后按字母(字母顺序)对对象集合进行排序 - 2

    我正在构建一个小部件来显示奥运会的奖牌数。我有一个“国家”对象的集合,其中每个对象都有一个“名称”属性,以及奖牌计数的“金”、“银”、“铜”。列表应该排序:1.首先是奖牌总数2.如果奖牌相同,按类型分割(金>银>铜,即2金>1金+1银)3.如果奖牌和类型相同,则按字母顺序子排序我正在用ruby​​做这件事,但我想语言并不重要。我确实找到了一个解决方案,但如果感觉必须有更优雅的方法来实现它。这是我做的:使用加权奖牌总数创建一个虚拟属性。因此,如果他们有2个金牌和1个银牌,加权总数将为“3.020100”。1金1银1铜为“3.010101”由于我们希望将奖牌数排序为最高的,因此列表按降序排

  4. ruby-on-rails - 在不重新查询数据库的情况下重新排序 Rails 中的事件记录? - 2

    例如,假设我有一个名为Products的模型,并且在ProductsController中,我有以下代码用于product_listView以显示已排序的产品。@products=Product.order(params[:order_by])让我们想象一下,在product_listView中,用户可以使用下拉菜单按价格、评级、重量等进行排序。数据库中的产品不会经常更改。我很难理解的是,每次用户选择新的order_by过滤器时,rails是否必须查询,或者rails是否能够以某种方式缓存事件记录以在服务器端重新排序?有没有一种方法可以编写它,以便在用户排序时rails不会重新查询结果

  5. ruby-on-rails - 如何对对象数组进行排序? - 2

    我有一个对象如下:[{:id=>2,:fname=>"Ron",:lname=>"XXXXX",:photo=>"XXX"},{:id=>3,:fname=>"Dain",:lname=>"XXXX",:photo=>"XXXXXXX"},{:id=>1,:fname=>"Bob",:lname=>"XXXXXX",:photo=>"XXXX"}]我想按fname排序,不区分大小写,所以它会导致编号:1,3,2我该如何排序?我正在尝试:@people.sort!{|x,y|y[:fname]x[:fname]}但这没有任何效果。 最佳答案

  6. ruby - 使用自定义排序首选项对数组进行排序? - 2

    有人可以告诉我如何根据自定义字符串对嵌套数组进行排序吗?比如有没有办法排序:[['Red','Blue'],['Green','Orange'],['Purple','Yellow']]“橙色”、“黄色”,然后是“蓝色”?最终结果如下所示:[['Green','Orange'],['Purple','Yellow'],['Red','Blue']]它不是按字母顺序排序的。我很想知道我是否可以定义要排序的值以实现上述目标。 最佳答案 sort_by对于这种排序总是非常方便:a=[['Red','Blue'],['Green','Ora

  7. Ruby 将对象插入现有的已排序对象数组 - 2

    我有以下现有的Dog对象数组,它们按age属性排序:classDogattr_accessor:agedefinitialize(age)@age=ageendenddogs=[Dog.new(1),Dog.new(4),Dog.new(10)]我现在想插入一条新的狗记录,并将它放在数组中的正确位置。假设我想插入这个对象:another_dog=Dog.new(8)我想把它插入到数组中,让它成为数组中的第三项。这是一个人为的示例,旨在演示我特别想如何将一个项目插入到现有的有序数组中。我意识到我可以创建一个全新的数组并重新对所有对象进行排序,但这不是我的目标。谢谢!

  8. ruby - 如何排序不是简单的哈希(哈希的哈希) - 2

    我有一个这样的哈希{55=>{:value=>61,:rating=>-147},89=>{:value=>72,:rating=>-175},78=>{:value=>64,:rating=>-155},84=>{:value=>90,:rating=>-220},95=>{:value=>39,:rating=>-92},46=>{:value=>97,:rating=>-237},52=>{:value=>73,:rating=>-177},64=>{:value=>69,:rating=>-167},86=>{:value=>68,:rating=>-165},53=>{:va

  9. ruby - 根据值然后键对ruby中的哈希进行排序 - 2

    如何在ruby​​中先根据值然后根据键对散列进行排序?例如h={4=>5,2=>5,7=>1}将排序为[[7,1],[2,5],[4,5]]我可以根据值进行排序h.sort{|x,y|x[1]y[1]}但我不知道如何根据值进行排序,然后在值相同时键入 最佳答案 h.sort_by{|k,v|[v,k]}这使用了Array的事实混入Comparable并定义逐元素。注意上面等价于h.sort_by{|el|el.reverse}相当于h.sort_by(&:reverse)这可能会或可能不会更具可读性。如果你知道Hashes一般都是先

  10. ruby - 在 ruby​​ 中对字符串进行排序以使空字符串位于末尾的好方法是什么? - 2

    在Ruby中,默认排序将空字符串放在第一位。['','g','z','a','r','u','','n'].sort给予:["","","a","g","n","r","u","z"]但是,在end处需要空字符串是很常见的。做类似的事情:['','g','z','a','r','u','','n'].sort{|a,b|a[0]&&b[0]?ab:a[0]?-1:b[0]?1:0}工作并给予:["a","g","n","r","u","z","",""]但是,这不是很可读,也不是很灵活。在Ruby中是否有一种合理且干净的方法让sort将空字符串放在最后?只映射到一个没有空字符串的数组,

随机推荐