一、题目详情
问题描述:继续(3n+1)猜想
卡拉兹(Callatz)猜想已经在1001中给出了描述。在这个题目里,情况稍微有些复杂。
当我们验证卡拉兹猜想的时候,为了避免重复计算,可以记录下递推过程中遇到的每一个数。例如对 n=3 进行验证的时候,我们需要计算 3、5、8、4、2、1,则当我们对 n=5、8、4、2 进行验证的时候,就可以直接判定卡拉兹猜想的真伪,而不需要重复计算,因为这 4 个数已经在验证3的时候遇到过了,我们称 5、8、4、2 是被 3“覆盖”的数。我们称一个数列中的某个数 n 为“关键数”,如果 n 不能被数列中的其他数字所覆盖。
现在给定一系列待验证的数字,我们只需要验证其中的几个关键数,就可以不必再重复验证余下的数字。你的任务就是找出这些关键数字,并按从大到小的顺序输出它们。
输入格式:
每个测试输入包含 1 个测试用例,第 1 行给出一个正整数 K (<100),第 2 行给出 K 个互不相同的待验证的正整数 n (1<n≤100)的值,数字间用空格隔开。
输出格式:
每个测试用例的输出占一行,按从大到小的顺序输出关键数字。数字间用 1 个空格隔开,但一行中最后一个数字后没有空格。
输入样例:
6
3 5 6 7 8 11
输出样例:
7 6
代码长度限制:16 KB
时间限制:400 ms
内存限制:64 MB
二、题目解析
代码:
#include <stdio.h>
#include <stdlib.h>
#define SIZE 100
int main()
{
/*
* num:正整数(输入数据)的个数
* input:指向动态开辟内存空间,用于存储正整数(输入数据)
* tempArr[SIZE]:用于存储中间数,初始化为0
* temp:数组排序时所需的临时变量
* value:用于存储给一个正整数(输入数据)
* first:标记数组tempArr的第一个元素,1为是,0为否
* flag:标识关键数,1为是,0为否
* i,j,k:循环变量
*/
int num = 0;
int i, j, k;
int tempArr[SIZE]={0}, temp, value;
int flag, first;
int* input = (int *)malloc(sizeof(int) * num);
//获取输入正整数(输入数据)的个数
scanf("%d", &num);
//获取正整数(输入数据)
for(i=0;i<num;i++)
scanf("%d", &input[i]);
//从大到小排序,便于结果按从大到小输出
for(i=0;i<num-1;i++)
{
for(j=i+1;j<num;j++)
{
if(input[i]<input[j])
{
temp = input[i];
input[i] = input[j];
input[j] = temp;
}
}
}
//针对每个整数(输入数据),将递推中产生的每个数,不重复且从小到大存储在数组tempArr中
flag = 1;//标识数组tempArr的第一个元素
for(i=0;i<num;i++)
{
value = input[i];
while(value != 1)//递推直至value为1
{
value = (value % 2 == 0) ? value / 2 : (value * 3 + 1)/2;
for(j=0;tempArr[j]!=0;j++)
{
if(flag == 1)//表示数组tempArr的第一个元素未赋值
{
tempArr[i] = value;//将value存储在数组tempArr的第一位
flag = 0;//数组tempArr的第一个元素已赋值
break;
}
if(tempArr[j] == value)//数组tempArr中已存在value
break;
if(tempArr[j] > value)//将value按照从小到大插入数组tempArr中
{
for(k=SIZE-1;k>j;k--)
tempArr[k] = tempArr[k-1];
tempArr[j] = value;
break;
}
}
if(j<SIZE)//将value存在在数组tempArr的最后一位
tempArr[j] = value;
}
}
//确认关键数并从大到小输出
first = 1;//标识输出第一个关键数
for(i=0;i<num;i++)
{
flag = 1;//标识关键数
for(j=0;tempArr[j]!=0;j++)
{
if(input[i] == tempArr[j])//整数(输入数据)出现在数组tempArr中
{
flag = 0;//不是关键数
break;
}
}
if(flag == 1)//是关键数
{
if(first == 1)//输出第一个关键数
{
printf("%d", input[i]);//不带空格
first = 0;//已输出第一个关键数
}
else//输出其他关键数
printf(" %d", input[i]);//带空格
}
}
return 0;
}
提交结果(分数/满分):
22/25
测试点4:段错误
表明:您的程序发生段错误,可能是数组越界,堆栈溢出(比如,递归调用层数太多)等情况引起。原因不详,高手指点,拜谢!
提示:
1. 数组排序问题
1)根据题目要求,从大到小输出关键数,故可先将数组input进行从大到小排序
本输入样例的排序结果为:
11 8 7 6 5 3
2)将递推过程中产生的一系列整数,按照从小到大的顺序依次存储在数组tempArr中
本输入样例产生的一系列整数为:
1 2 3 4 5 8 10 11 13 17 20 26
2. 关键数确定方法
数组input中的元素值不应出现在数组tempArr中,否则记为非关键数,故输出结果为:
7 6