刷题1:成绩排序

刷题1:成绩排序

来源:https://www.nowcoder.com/practice/0383714a1bb749499050d2e0610418b1
题目:
查找和排序

题目:输入任意(用户,成绩)序列,可以获得成绩从高到低或从低到高的排列,相同成绩
都按先录入排列在前的规则处理。

示例:
jack 70
peter 96
Tom 70
smith 67

从高到低 成绩
peter 96
jack 70
Tom 70
smith 67

从低到高

smith 67

jack 70
Tom 70
peter 96

输入描述:
输入多行,先输入要排序的人的个数,然后输入排序方法0(降序)或者1(升序)再分别输入他们的名字和成绩,以一个空格隔开

输出描述:
按照指定方式输出名字和成绩,名字和成绩之间以一个空格隔开
示例1
输入

3
0
fang 90
yang 50
ning 70

输出
fang 90
ning 70
yang 50



这是我最近刷的第一道题,虽然是比较简单的题,但是收获不少。先放上我的解法吧,当然不是我写的,是我看讨论里一个高票回答的:

#include<bits/stdc++.h>
using namespace std;
int n,method,score[500],myIndex[500];
string name[500];
bool cmpSmall(int i,int j){
    return score[i]<score[j];
}
bool cmpBig(int i,int j){
    return score[i]>score[j];
}
int main(){
    while(cin>>n){
        cin>>method;
        for(int i=0;i<n;i++){
            cin>>name[i]>>score[i];
            myIndex[i]=i;
        }
        if(method==0){
            stable_sort(myIndex,myIndex+n,cmpBig);
        }
        else{
            stable_sort(myIndex,myIndex+n,cmpSmall);
        }
        for(int i=0;i<n;i++){
            cout<<name[myIndex[i]]<<" "<<score[myIndex[i]]<<endl;
        }
    }
    return 0;
}

收获如下:

  1. 本题限制了C/C++ 1秒,而对于该时限,通常,我们所设计的算法复杂度不能超过百万级别,即不能超过一千万。即如果算法的时间复杂度是O(n^2),则n不能大于3000.这对于我们选择算法是有意义的。而且据我所知,一般的题目都是对时间要求严格,对空间的要求就松很多。例如本题空间限制:C/C++ 32M,其实运行下来实际使用的就几百k。所以可以考虑采用一些空间换时间的操作,例如本题中有人想到的利用成绩的离散性和有限性做哈希表,把name往各个位置插,这个思路不错,我写了一下:
#include<bits/stdc++.h>
using namespace std;
int n,method;
vector<vector<string>*> myHash;
int main(){
    for(int i=0;i<101;i++){
        myHash.push_back(new vector<string>());
    }
    int score;
    string name;
    while(cin>>n){
        cin>>method;
        for(int i=0;i<n;i++){
            cin>>name>>score;
            myHash[score]->push_back(name);
            name.clear();
        }
        if(method==0){
            for(int i=100;i>=0;i--){
                if(!myHash[i]->empty()){
                    int length=myHash[i]->size();
                   for(int j=0;j<length;j++){
                       cout<<myHash[i]->at(j)<<" "<<i<<endl;
                   }
                }
            }
        }else{
             for(int i=0;i<=100;i++){
                if(!myHash[i]->empty()){
                    int length=myHash[i]->size();
                   for(int j=0;j<length;j++){
                       cout<<myHash[i]->at(j)<<" "<<i<<endl;
                   }
                }
            }
        }
    for(int i=0;i<101;i++){
        myHash[i]->clear();
    }
    }
    return 0;
}

但是它的实际表现不如第一个解法,无论是时间上还是空间上。虽然第一个解法因为有排序,是O(lgn)的,但是使用的都是基本数据类型,也不涉及到对象的动态申请和释放;第二种虽然是O(n)的,但是使用了STL,每次用完还要释放内容,所以相比还是慢一些,当然空间占用更大是必然的了。从编写上来看,也是第一种比较简单,不容易出错,毕竟stable_sort是写好的库函数。

  1. c++ 有一个和Java容易混的地方,就是它的string\list等等首字母都是小写的,这个平常用不是什么问题,但是像OJ这种提示不完全的有时候还是挺坑的
  2. 还有一个坑的地方在于,因为用了万能头文件<bits/stdc++.h>,把c++ 的标准库都一股脑导入进来了,就特别容易发生关键字的重复。我个人觉得比较方便的解决办法就是在变量前面加个my,特别是一些看着就比较“标准”的变量名,例如map\index\hash等等
  3. c++ 的vector才是可以使用at(int index)或者下表随机访问的,list是链表,不能随机访问,这个和java还是有区别的
  4. 为啥说了这么多c++ 和java的区别,我本人也是对java更熟悉,却还是要用C++,因为我发现像算法OJ还是C++ 适合,一个是写起来简单(Java的import还有语句都是比较复杂的,只是在IDE下写的爽而已),另一个就是速度比较快,并且c++ 格式简单,写一个main就开干,java还要慢悠悠地创建类
  5. 像STL和struct还有class都是创建对象适合不需要使用new语句的,new创建出来的都是指针
  6. 区分length()和size()的含义:length()说的是长度,一般用在string上面,说字符串的长度;而size是大小,一般用在vector\list上,指的是个数
  7. 说回第一种解法,这里用到了自定义排序规则的写法。像sort函数默认是升序,默认的compare规则也是 return a<b.如果想要降序排列,可以自定义规则为return a>b(规律就是,return的大小规律和升降时候谁在前的规律一样)。但是这里这个算法实现了一个我之前一直觉得比较麻烦的事情,就是对多个项按项中的某一个指标排序。因为它有连带信息,所以不能用一个基本类型存放,而如果只对排序指标所在的基本类型排序的话从属关系会乱掉。我之前的思路是使用结构体然后自定义排序规则,使得比较结构体中的一项。但是这个算法只要基本类型就实现了,思路就是对下标排序,但是比较函数中比较的是指标。这样得到的就是按指标排好序的下标,顺序体现的是指标的大小,而信息的从属关系由下标的值保存着,很巧妙的设计。
  8. 注意sort的参数输入的是begin,end,comp.不要把长度输入进去了,end=begin+n

原文地址:https://www.cnblogs.com/jiading/p/12339926.html

时间: 2024-08-04 01:39:59

刷题1:成绩排序的相关文章

OJ题:成绩排序

题目描述 查找和排序 题目:输入任意(用户,成绩)序列,可以获得成绩从高到低或从低到高的排列,相同成绩 都按先录入排列在前的规则处理. 例示: jack 70 peter 96 Tom 70 smith 67 从高到低 成绩 peter 96 jack 70 Tom 70 smith 67 从低到高 smith 67 Tom 70 jack 70 peter 96 输入描述: 输入多行,先输入要排序的人的个数,然后分别输入他们的名字和成绩,以一个空格隔开 输出描述: 按照指定方式输出名字和成绩,

OJ刷题---ASCII码排序

题目要求: 输入代码: #include<iostream> #include<cstdio> using namespace std; int main() { char str[3],temp; int i,j; while(gets(str)) { for(i=0; i<3; i++) for(j=0; j<3; j++) if(str[j]>str[j+1])//字符串依然可以像数字一样排序 { temp=str[j]; str[j]=str[j+1];

LeetCode刷题之合并排序链表

合并两个有序链表并返回一个新的列表.新列表应该由连接在一起的节点前两个列表 给定实例:Input: 1->2->4, 1->3->4Output: 1->1->2->3->4->4 思路分析:引入第三个链表,存储合并之后的链表,开两个指针,分别遍历两个链表,当遍历到一个节点的时候,就开始判断大小,然后将小的链表节点存储到第三个链表中,依次递归判断.但是我们需要考虑临界条件,如果第一个链表的数都比第二个链表的小,那么我们就直接将第二个链表链接到第三个链表

用js刷题的一些坑

leecode可以用js刷题了,我大js越来越被认可了是吧.但是刷题中会因为忽略js的一些特性掉入坑里.我这里总结一下我掉过的坑. 坑1:js中数组对象是引用对象 js中除了object还有数组对象也是引用对象,这点常常被忽视,所以在递归的时候传递数组要用arr.slice(0)这样复制一个一样的新数组,不然会出现你传入的数组会被同级的递归改变,结果就不对了. 所以只要数组复制的地方最好都要这么写,除非你真的想引用.而且注意是slice不是splice这两个方法差别很大,你如果用splice(0

03:成绩排序

03:成绩排序 查看 提交 统计 提问 总时间限制:  1000ms 内存限制:  65536kB 描述 给出班里某门课程的成绩单,请你按成绩从高到低对成绩单排序输出,如果有相同分数则名字字典序小的在前. 输入 第一行为n (0 < n < 20),表示班里的学生数目:接下来的n行,每行为每个学生的名字和他的成绩, 中间用单个空格隔开.名字只包含字母且长度不超过20,成绩为一个不大于100的非负整数. 输出 把成绩单按分数从高到低的顺序进行排序并输出,每行包含名字和分数两项,之间有一个空格.

7、8月刷题总结

准备开学了囧,7.8月刷题记录,以后好来复习,并且还要好好总结! 数据结构: splay: [BZOJ]1503: [NOI2004]郁闷的出纳员(Splay) [BZOJ]1269: [AHOI2006]文本编辑器editor(Splay) [BZOJ]1507: [NOI2003]Editor(Splay) treap: [BZOJ]1862: [Zjoi2006]GameZ游戏排名系统 & 1056: [HAOI2008]排名系统(treap+非常小心) [BZOJ]3224: Tyvj

九度oj 题目1061:成绩排序

题目1061:成绩排序 时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:24473 解决:6960 题目描述: 有N个学生的数据,将学生数据按成绩高低排序,如果成绩相同则按姓名字符的字母序排序,如果姓名的字母序也相同则按照学生的年龄排序,并输出N个学生排序后的信息. 输入: 测试数据有多组,每组输入第一行有一个整数N(N<=1000),接下来的N行包括N个学生的数据.    每个学生的数据包括姓名(长度不超过100的字符串).年龄(整形数).成绩(小于等于100的正数). 输出: 将学

【leetcode刷题笔记】Sort List

Sort a linked list in O(n log n) time using constant space complexity. 题解:实现一个链表的归并排序即可.主要分为三部分: 1.找到中点并返回的函数findMiddle; 2.归并函数merge; 3.排序函数sortList. 数组的findMiddle函数非常容易实现,链表就有一点tricky了.首先设置两个指针,一个slow初始化为head,一个fast初始化为head.next,然后slow一次走一步,fast一次走两

Leetcode刷题录之Two Sum

题意大概是给出一个数列num,和一个目标数target,然后要找出数列中的两个数,使得这两个数之和等于目标数,输出这两个数的下标值(从1开始算). 一个比较暴力的方法是用一个二重循环直接遍历序列,在第一重循环中找到a,在第二重循环中找到b,使得a+b=target,这种做法的时间复杂度是O(n^2), 提交时提示超时. 改进方法,先对数列num复制一个副本,然后对副本进行排序.在一重循环中找到a,接着对这个有序的副本进行二分查找,找到b= target-a,二分查找的 时间复杂度是O(logn)