这些数字以自然数表示。按出现的升序列出这些数字的十进制表示法中出现的数字。如果两个数字出现的次数相同,则先显示较小的数字。
示例:
在
五一二四二二九一三二二四五三四
出局
5 9 1 3 4 2
这是我的代码:
#include <iostream>
using namespace std;
int v1[10],v2[10],lim,x,ok;
int main()
{
cin>>lim;
for(int i=1; i<=lim; i++)
{
cin>>x;
while (x>0)
{
v1[x&10]++;
v2[x%10]=x%10;
x=x/10;
}
}
while (!ok)
{
ok=1;
for(int i=0; i<=lim; i++)
{
if(v1[i]>v1[i+1])
{
swap (v1[i],v1[i+1]);
swap (v2[i],v2[i+1]);
ok=0;
}
}
}
ok=0;
while (!ok)
{
ok=1;
for(int i=0; i<lim; i++)
{
if(v2[i]>v2[i+1])
if(v1[i]==v1[i+1])
swap (v2[i],v2[i+1]);
}
}
for (int i=0; i<=10; i++)
{
if(v2[i]!=0)
cout<<v2[i]<<" ";
}
}
它不会按我想要的方式排序
我试过两次了
3条答案
按热度按时间w8biq8rn1#
v1[x%10]
(使用模),而不是v1[x&10]
(使用位与)v1
和v2
的10个元素进行,而不是针对lim+2
或lim+1
元素进行。v2[10]
超出范围,因此您不能访问它。固定代码:
实际上,第二次排序可以删除,因为您使用的是稳定的冒泡排序,并且
v2
中的数字在第一次排序之前就已经按升序排列了。还要注意的是,即使
0
像5 120 34 56 78 90
一样出现在输入中,程序也不会打印它。如果你想在输出中包含0
,你应该使用if(v1[i]!=0)
而不是if(v2[i]!=0)
。即使做了这样的修改,当输入中有零或负数时,程序也不会工作。siotufzp2#
你的代码产生错误输出的更深层次的原因是它太复杂了。这里只列举主要的复杂因素:
使用神秘的变量名会使代码更难读。难读的代码更容易有bug。
你可以从头开始实现而不是使用现有的算法。手动实现算法而不是使用标准库中的工具的代码更有可能有bug。
C-数组有很多怪癖,而且很复杂。也许最重要的是,它们需要你分别跟踪它们的大小(实际上,大小是现成的,因为它是类型的一部分,但那很麻烦)。使用C-数组而不是标准容器的代码更容易有bug。
因为你只需要处理单个数字,所以把输入读成字符串会更简单。要计算出现的次数,你可以使用
std::map
。counts
将所有数字作为键,将它们的出现作为Map值。它是根据数字排序的(注意,unordered_map
也可以,但顺序还不是所需的)。为了根据出现次数进行排序,我们填充一个Map,该Map将出现次数作为键,将数字作为Map值,因为两个不同的数字cabn具有相同的出现次数,并且因为输出中较小的数字应该首先出现,所以我们可以使用
set<char>
来存储数字:现在,输出只是一个嵌套循环,用于迭代所有出现的数字,以及对于每个出现的数字出现在集合中:
这就是所需要的全部内容。代码中唯一遗漏的部分是阅读
n
的值。您只需要将这些部分加在一起。knsnq2tg3#
对于给定的测试用例(5 124 229 1322 4 534),模型答案(5 9 1 3 4 2)似乎是错误的。
如果你愿意的话,你几乎可以完全使用字符来工作:它们的排序与数字相同。大量使用标准库例程,如stable_sort: