一、整体思路
先读入这K个数,再判断其中哪些是关键数,最后取出关键数并对其进行降序排列与输出
二、关键问题
1.关键数是什么
2.如何找出一个数字序列中的关键数
三、关键问题对应的解决方法
1.通过找出一个数字序列中的关键数的例子阐述什么是关键数
数字序列为:3 5 6 7 8 11
数字3的卡拉兹猜想验证过程为:3 5 8 4 2
数字5的卡拉兹猜想验证过程为:5 8 4 2
数字6的卡拉兹猜想验证过程为:6 3 5 8 4 2
数字7的卡拉兹猜想验证过程为:7 11 17 26 13 20 10 5 8 4 2
数字8的卡拉兹猜想验证过程为:8 4 2
数字11的卡拉兹猜想验证过程为:11 17 26 13 20 10 5 8 4 2
该数字序列中的关键数为:6 7
可以看出关键数即为在数字序列中的其他所有数字的卡拉兹猜想验证过程中未出现的数,也为仅在自己的卡拉兹猜想验证过程中出现的数(其为验证序列的第一个数)
2.
对应的找出关键数的方法为,对该数字序列中的所有数依次进行卡拉兹猜想验证,标记验证过程中所有出现过的数(基于上述内容,验证序列中的第一个数不应列入标记范围),最后再取数字序列与验证过程中出现过的数的交集
上述方法较为繁琐,可对其进行简化。简化方式为,为数字设立对应的状态信息,初始状态为-1,在读入数字序列的过程之中将读入数字对应的状态设置为1,在卡拉兹猜想验证过程之中,将验证过程中出现的状态为0的数字的状态设置为1,即数字序列中的数如果在验证过程中出现且不为验证序列的第一个,该数就不是关键数
四、数据结构
采用int 数组保存数字序列、数字对应的状态以及关键数
五、一些小细节
1.采用sort函数对关键数数组进行降序排列,注意其参数的意义与传参方式
2.因采用int 数组保存数字对应的状态,即flag[i]标志着数字i的状态,这就需要考虑到卡拉兹猜想验证过程之中所出现的最大数是多少,在数组初始化时需要将其作为最大下标,否则会出现数组越界错误
代码如下:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <algorithm>
using namespace std;
void keynumberjudge(int k,int number[100],int flag[4617]);
bool compare(int a,int b);
int main()
{
int k;
scanf("%d",&k);
int i;
int flag[4617];
int keynumber[4617];
for(i=0;i<4617;i++)
{
flag[i]=-1;
keynumber[i]=-1;
}
int number[100];
for(i=0;i<k;i++)
{
scanf("%d",&number[i]);
if(i!=k-1)
scanf(" ");
flag[number[i]]=0;
}
keynumberjudge(k,number,flag);
int j;
for(i=0,j=0;i<4617;i++)
{
if(flag[i]==0)
{
keynumber[j]=i;
j++;
}
}
sort(keynumber,keynumber+j,compare);
for(i=0;i<j;i++)
{
if(i!=0) printf(" ");
printf("%d",keynumber[i]);
}
return 0;
}
void keynumberjudge(int k,int number[100],int flag[4617])
{
int n;
int i;
for(i=0;i<k;i++)
{
n=number[i];
for(;n!=1;)
{
if(n%2==0)
{
n=n/2;
if(flag[n]==0)
flag[n]=1;
}
else
{
n=(3*n+1)/2;
if(flag[n]==0)
flag[n]=1;
}
}
}
}
bool compare(int a,int b)
{
return a>b;
}