华为机试——字符统计

输入一个字符串,对字符串中的各个英文字符,数字,空格进行统计(可反复调用),按照统计个数的多少输出统计结果,如果统计的个数相同,则按照ACSII码由小到大排序输出。调用者会保证:输入的字符串以’\0’结尾

#include<iostream>
#include<algorithm>

using namespace std;
struct Count
{
    int c;
    int count;
};
bool cmp(const struct Count& a,const struct Count& b)
{
    if(a.count==b.count)
        return a.c<b.c;
    else
        return 
        a.count>b.count;
}

int main()
{
    struct Count a[256];
    char b[200];
    for(int i=0;i<256;i++)
    {
        a[i].c=i;
        a[i].count=0;
    }
    gets(b);
    for(int i=0;b[i]!='\0';i++)
    {
        if(b[i]>='a' && b[i]<='z' || b[i]>='A' && b[i]<='Z'|| b[i]>= '0' && b[i] <='9'||b[i]==' ')
        {
            unsigned char temp=b[i];
            a[temp].count++;
        }
    }
    sort(a,a+256,cmp);
    for(int i=0;i<256;i++)
    {
        if(a[i].count != 0)
            cout<<char(a[i].c);
    }
    return 0;
}
<think>好的,我现在需要帮用户解决如何用JavaScript编写统计射击比赛成绩的功能,尤其是类似华为OD中的题目。用户提到的题目要求是根据选手的最高三个分数之和进行降序排名,并且满足特定条件。首先,我得仔细分析题目条件和要求。 首先,题目有三个主要条件:选手成绩不足三个的忽略,按最高三个之和排序,相同分数则按ID降序排列。那我需要将输入数据解析成选手ID和对应的分数列表,然后处理每个选手的数据。 接下来,我需要考虑数据结构的处理。可能需要一个对象来存储每个选手的成绩,键是选手ID,值是一个数组保存所有分数。然后遍历每个选手,过滤掉分数少于三个的。对于符合要求的选手,取出最高的三个分数求和。 排序部分需要考虑两个关键点:总分降序,同分时ID降序。这可以通过Array.sort的自定义比较函数来实现。比较函数需要先比较总分,如果总分相同,再比较ID的降序。 然后,代码的结构大致分为几个步骤:解析输入数据,处理每个选手的成绩,过滤无效选手,计算总分,排序,输出结果。需要注意的是输入数据的格式,题目中可能输入是类似数组的结构或者字符串,但用户没有具体说明,所以可能需要假设输入格式。例如,假设输入一个数组,每个元素是对象,包含选手ID和分数,或者是一个二维数组? 不过根据用户提供的引用内容,比如引用2和3中的描述,题目中的输入可能是一个成绩单,可能结构类似每个选手的多次射击记录。例如,输入可能是一个数组,其中每个元素是[选手ID, 分数],或者是这样的结构。因此,在JavaScript中,需要将这样的输入转换为按选手ID分组的结构。 比如,输入可能是这样的数组: const input = [ ['001', 9], ['002', 8], ['001', 7], // 更多记录... ]; 然后需要将这些记录按选手ID分组,收集他们的分数。可以用一个对象来存储,例如: const scoresMap = {}; input.forEach(([id, score]) => { if (!scoresMap[id]) { scoresMap[id] = []; } scoresMap[id].push(score); }); 接着,遍历这个scoresMap,处理每个选手的数据。过滤掉分数不足三个的。对于剩下的,将分数排序,取前三的和。例如: const validPlayers = []; for (const [id, scores] of Object.entries(scoresMap)) { if (scores.length >= 3) { const sorted = [...scores].sort((a, b) => b - a); // 降序排序 const sum = sorted[0] + sorted[1] + sorted[2]; validPlayers.push({ id, sum }); } } 然后排序这些validPlayers,先按sum降序,相同的话按id降序: validPlayers.sort((a, b) => { if (b.sum !== a.sum) { return b.sum - a.sum; } else { return b.id.localeCompare(a.id); // 因为id是字符串,用localeCompare进行降序比较 } }); 最后提取排序后的id数组: const result = validPlayers.map(player => player.id); 现在需要考虑如何将这个过程用JavaScript函数实现。可能需要一个函数,接收输入数据,返回排序后的id数组。例如: function calculateRanking(records) { const scoresMap = {}; // 假设records的结构是数组,每个元素是[id, score]的数组 records.forEach(([id, score]) => { if (!scoresMap[id]) { scoresMap[id] = []; } scoresMap[id].push(score); }); const validPlayers = []; for (const [id, scores] of Object.entries(scoresMap)) { if (scores.length >= 3) { const sorted = [...scores].sort((a, b) => b - a); const sum = sorted[0] + sorted[1] + sorted[2]; validPlayers.push({ id, sum }); } } validPlayers.sort((a, b) => { if (b.sum !== a.sum) { return b.sum - a.sum; } else { return b.id.localeCompare(a.id); } }); return validPlayers.map(player => player.id); } 测这个函数的话,例如: 假设输入: const records = [ ['001', 10], ['001', 9], ['001', 8], ['001', 7], // 001有四个成绩,取前三的和是10+9+8=27 ['002', 9], ['002', 8], ['002', 7], // 002有三个成绩,和为9+8+7=24 ['003', 10], ['003', 10], ['003', 10], // 003和为30 ['004', 5], // 只有1个成绩,无效 ]; 则结果应为['003','001','002'] 注意,当sum相同时,比如两个选手sum相同,id较大的排在前面。例如,假设两个选手sum都是30,id是003和004,则004排在003前面。 可能还需要处理id的字符串比较是否正确,比如如果是数字型id,比如'3'和'4',则localeCompare可能会按字符串顺序,即'3'比'4'小,所以降序的话'4'在前。但题目中的条件3要求相同成绩的按ID降序排列,即更大的ID排在前面。假设id是字符串,比如'002'比'001'大,所以在排序时,比如两个sum相同的选手,id较大的排在前面。 在localeCompare中,如果a.id是'003',b.id是'002',那么b.id.localeCompare(a.id)会是正数吗?需要测。例如: '002'.localeCompare('003') 返回-1,因为'002'在'003'之前。而如果要降序的话,应该将较大的id排在前面,比如当比较a和b时,希望如果a.id > b.id,则排在前面。例如在比较函数中,如果是a和b,要按b.id - a.id的方式,但字符串无法相减,所以用localeCompare的结果。例如: 在sort函数中,a和b的比较,若返回正数,则a排在b后面。比如: 当比较a和b时,如果希望按id降序,那么应该比较b.id和a.id。例如,a.id是'003',b.id是'002',则比较a.id和b.id,如果希望更大的id排在前面,那么应该是b.id.localeCompare(a.id)的话,当a.id > b.id时,返回负数,这样在排序函数中,a会排在前面。或者可能需要调整顺序。 或者,可能更简单的方式是使用b.id.localeCompare(a.id),这样当b.id在字母表中排在前面时,返回正数,这样在sort函数中,a会被排在后面。例如: 假设a.id是'003',b.id是'002'。b.id.localeCompare(a.id)会返回-1,因为'002'在'003'前面。此时比较函数返回-1,那么sort会将a排在b前面吗? JavaScript的sort函数根据比较函数的返回值决定顺序。如果返回负数,则a排在b前面;返回正数,则b排在前面。比如: array.sort((a, b) => b - a) 会降序排列数字。 所以,在比较id的时候,希望按id降序排列,即较大的id排前面。假设id是字符串,例如'004'和'003',那么'004'比'003'大吗?按字符串比较的话,'004'在字典顺序中比'003'大吗? 例如,'004'.localeCompare('003') 返回1,因为'004'在字典中排在'003'之后。所以,如果我们要让较大的id排在前面,当比较a和b时,如果a.id应该排在前面,则比较函数应返回负数。例如: a和b是两个选手,假设我们想要降序排列id,那么比较函数应该比较b.id和a.id,如果b.id在a.id之前,则返回正数,这样b会被排在前面。或者,可能需要交换顺序。 例如,比较函数写成: (a, b) => b.id.localeCompare(a.id) 这样,当b.id在a.id之后时,返回负数,a排在b前面?或者可能弄反了。 例如,a.id是'003',b.id是'002'。b.id.localeCompare(a.id)会是-1,所以返回-1,这时在sort函数中,a会被排在b前面。这会导致排序后的顺序是'003', '002',这与期望的降序(从大到小)不符,因为'003' > '002'。此时,正确的降序应该是按id从大到小排列,所以'003'在'002'前面,所以这个比较函数是正确的? 或者,假设id是字符串,例如'100'和'99',按字符串比较的话,'100'比'99'小,因为第一个字符'1'比'9'小。这时候,用localeCompare的话,会导致排序不正确,可能题目中的id是数字字符串,需要当作数值来比较? 这可能是一个潜在的问题。题目中的条件3说“如果选手的成绩之和相等,则成绩相等的选手按照其 ID 降序排列。”这里的ID降序排列,如果ID是字符串,可能需要按照数值比较,或者按照字符串的字典序? 题目中的示例引用中,例如引用4中的输入是AAAA,输出是3,可能ID是字符串,但具体题目中的ID类型可能需要根据实际情况处理。但用户的问题中的示例代码可能需要处理ID为字符串的情况,例如'001','002'等。 假设ID是字符串,需要按字符串的字典序降序排列。例如,'002' 和 '001' 相比,'002' 在字典序中比 '001' 大,所以按降序的话,'002' 应该排在前面。在这种情况下,使用b.id.localeCompare(a.id)是否正确? 例如,当a.id是'002',b.id是'001'时,比较a.id和b.id的话,localeCompare返回正数?或者反过来? 例如,'002'.localeCompare('001') 返回正数,因为'002'在'001'之后。所以,如果比较函数是(a, b) => b.id.localeCompare(a.id),那么当a.id是'002',b.id是'001'时,比较函数返回的是'001'.localeCompare('002'),即返回负数,这样在排序时,a会被排在b的前面,而正确的降序应该是'002'排在'001'前面,所以此时比较函数返回负数,导致排序正确? 或者我可能搞混了比较函数的逻辑。假设我们有数组中的元素a和b,比较函数返回负数时,a会被排在b前面。例如,当比较函数是(a, b) => b - a(数值比较),如果a=3,b=2,则比较函数返回1,导致b排在前面?不对,应该返回b - a的话,如果a=3,b=2,则3-2=1,所以比较函数返回正数,意味着a应该排在b后面,所以结果是降序排列。 同理,在字符串比较中,如果我们希望按字符串的降序排列,即大的字符串在前,应该让比较函数返回b.id.localeCompare(a.id)。例如: 比较a.id和b.id时,如果b.id在字典序中排在a.id之后,那么localeCompare返回正数,所以比较函数返回正数,此时a会被排在后面,b排在前面。这样,最终的排序就是按降序排列。 例如,a.id是'001',b.id是'002'。比较函数返回的是b.id.localeCompare(a.id)即'002'.localeCompare('001'),返回正数,所以比较函数返回正数,因此a会被排在b的后面,所以排序后的顺序是b('002')在a('001')前面,符合降序的要求。 所以,正确的比较函数应该是: (a, b) => b.id.localeCompare(a.id) 这样处理的话,在相同sum的情况下,id较大的会排在前面。 综上,代码中的排序部分是正确的。 现在需要考虑输入数据格式的问题。用户的问题中,可能输入一个数组,每个元素代表一个射击记录,包括选手ID和分数。例如,输入可能是一个二维数组,如: const input = [ ['player1', 90], ['player2', 85], ['player1', 95], // 更多记录... ]; 所以在函数中,可以处理这样的输入结构。另外,在测时,可能需要注意选手ID的格式是否为字符串,例如是否带有前导零,比如'001',但JavaScript中处理字符串比较时,'001'和'01'会被视为不同的字符串。 现在,编写示例代码: function calculateShootingRank(records) { // 按选手ID分组统计分数 const scoreMap = {}; for (const [id, score] of records) { if (!scoreMap[id]) { scoreMap[id] = []; } scoreMap[id].push(score); } // 处理每个选手,计算最高三个分数的和 const validPlayers = []; for (const [id, scores] of Object.entries(scoreMap)) { if (scores.length >= 3) { // 降序排序并取前三 const sorted = [...scores].sort((a, b) => b - a); const sum = sorted.slice(0, 3).reduce((a, b) => a + b, 0); validPlayers.push({ id, sum }); } } // 排序:先按sum降序,sum相同按id降序 validPlayers.sort((a, b) => { if (b.sum !== a.sum) { return b.sum - a.sum; } else { return b.id.localeCompare(a.id); } }); // 提取id数组 return validPlayers.map(player => player.id); } // 示例输入 const records = [ ['001', 10], ['001', 9], ['001', 8], ['001', 7], ['002', 9], ['002', 8], ['002', 7], ['003', 10], ['003', 10], ['003', 10], ['004', 5], ]; console.log(calculateShootingRank(records)); // 期望输出: ['003', '001', '002'] 这个示例中,选手003的和是30,001是27,002是24,所以排序正确。如果存在sum相同的选手,比如两个sum都是30,id较大的会排在前面。 另外,需要注意JavaScript中的sort函数对字符串的处理是否正确。例如,如果id是数字字符串,比如'100'和'20',按字符串比较的话'100'会被认为比'20'小,因为第一个字符'1'比'2'小。而如果题目中的ID是数值型的,可能需要转换为数字进行比较。但题目中的示例可能使用字符串ID,如引用中的输入是“AAAA”,所以假设ID是字符串,按字典序降序排列是正确的。 此外,在代码中处理分数时,需要确保分数是数值类型。假设输入的score已经是数字,否则需要转换为数字。 综上,这个JavaScript函数应该满足题目的要求。用户可能需要根据具体的输入格式调整函数的参数处理,例如如果输入字符串形式的数据,需要先解析成数组。但根据用户提供的引用,特别是引用3中的描述,函数应该能处理给定的输入结构。</think>以下是使用 JavaScript 实现射击比赛成绩统计的代码示例,满足题目要求的三个核心条件: ```javascript function calculateShootingRank(records) { const scoreMap = {}; // 1. 按选手ID分组统计成绩 for (const [id, score] of records) { scoreMap[id] ? scoreMap[id].push(score) : (scoreMap[id] = [score]); } // 2. 筛选有效选手并计算最高三个分数之和 const validPlayers = []; for (const [id, scores] of Object.entries(scoreMap)) { if (scores.length >= 3) { const sum = [...scores] .sort((a, b) => b - a) .slice(0, 3) .reduce((acc, val) => acc + val, 0); validPlayers.push({ id, sum }); } } // 3. 按规则排序 validPlayers.sort((a, b) => b.sum - a.sum || b.id.localeCompare(a.id) ); // 4. 提取排序结果 return validPlayers.map(player => player.id); } // 测用例 const testData = [ ['001', 10], ['001', 9], ['001', 8], ['001', 7], ['002', 9], ['002', 8], ['002', 7], ['003', 10], ['003', 10], ['003', 10], ['004', 5] ]; console.log(calculateShootingRank(testData)); // 输出: ['003','001','002'] ``` ### 代码解析 1. **数据分组**:通过 `scoreMap` 对象按选手ID分组存储所有成绩 2. **有效性筛选**:过滤成绩不足3次的选手,使用 `sort + slice` 取最高3个分数求和 3. **双条件排序**: - 主排序条件:总分降序 (`b.sum - a.sum`) - 次排序条件:ID字符串降序 (`localeCompare`)[^3] 4. **结果提取**:通过 `map` 提取最终排序后的ID序列
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值