【发布时间】:2021-03-21 12:01:51
【问题描述】:
给定一个数字数组(0 到 9)。找出可以由数组的部分或全部数字组成且能被 3 整除的最大数。同一个元素可能在数组中出现多次,但数组中的每个元素只能使用一次。 例子: 输入:arr[] = {5, 4, 3, 1, 1} 输出:4311
算法
- 获取数组大小和数组输入,并在获取输入时计算总和。
- 按升序对数组进行排序
- 取三个队列,迭代数组并将数字除以 3,然后根据余数放入各自的队列中,
队列 0 保存数字 % 3 == 0
队列 1 保存数字 % 3 == 1
Queue2 保存数字 % 3 == 2 - 计算余数 = sum % 3,
如果余数等于 1,则从 Queue1 中取出一个元素或从 Queue2 中取出两个元素
如果余数等于 2,则从 Queue2 中取出一个元素或从 Queue1 中取出两个元素 - 将 Queue0、Queue1 和 Queue2 合并为一个队列
- 按降序对合并队列进行排序
- 打印合并队列。
代码
#include<stdio.h>
int main()
{
int n,sum=0;
scanf("%d",&n);
int a[n],q1[n],q2[n],q3[n];
int c1=0,c2=0,c3=0;
for(int i=0;i<n;i++) {
scanf("%d",&a[i]);
sum+=a[i]; }
for(int i=0;i<n;i++){
if(a[i]%3==0) {
q1[c1]=a[i]; c1++; }
else if(a[i]%3==1) {
q2[c2]=a[i]; c2++; }
else {
q3[c3]=a[i]; c3++; }
}
if(sum%3==1&&c1!=0)
c1--;
else {
if(c2>1)
c2-2;
else
printf("Not Possible");
}
if(sum%3==2&&c2!=0)
c2--;
else {
if(q1>1)
c1-2;
else
printf("Not Possible");
}
int k=0,b[n];
for(int i=0;i<c1;i++) {
b[k]=q1[i]; k++; }
for(int i=0;i<c2;i++) {
b[k]=q2[i]; k++; }
for(int i=0;i<c3;i++) {
b[k]=q3[i]; k++; }
}
我是编码新手,无法弄清楚 O(n) 中的排序和合并队列。在第 2 步和第 5 步方面需要帮助。
【问题讨论】:
-
由于数组只包含一位数字,所以不需要三个队列。您需要的是数字的直方图。
-
我们不需要 2 个循环来生成直方图吗?代码需要在 O(n) for (i = 0; i
-
@Arjun 你可以用一个循环来完成。
int h[10]={0}; for (i=0; i<n; i++) h[a[i]]++;实际上,您可以在读取输入的同时计算直方图。你甚至不需要a数组。读取每个数字,更新总和,更新直方图。 -
在第 4 步中,您将减少直方图中一位或两位数字的计数。然后生成输出需要两个循环:
for (i=9; i>=0;i--) for (count=h[i]; count>0; count--) result[r++] = i;但是这两个循环总共执行了n次,因为直方图中的计数总和为n。 -
如果想提出我认为总体上更快的方法。不仅仅是没有队列,而是一个简单的判断可分性的条件。
标签: c