1005:继续3(n+1)猜想

功能:
我们需要一种数据结构,用来记录递推过程中遇到的每一个数,但具体会有多少数,无法提前确定,所以就无法用数组来定义。
C++中有一种数据结构叫做单向链表结构,可以用它来存放递推过程中遇到的每一个数。

struct node{
	int data;
	node* next;
};

我们先递推下用例中输入的数:
被3“覆盖”的数:5,8,4,2
被5“覆盖”的数:8,4,2
被6“覆盖”的数:3,5,8,4,2
被7“覆盖”的数:11,17,26,13,20,10,5,8,4,2
被8“覆盖”的数:4,2
被11“覆盖”的数:17,26,13,20,10,5,8,4,2
被100“覆盖”的数:50,25,38,19,29,44,22,11,17,26,13,20,10,5,8,4,2

可以发现,只要依次对输入的数进行递推,并把并把递推过程中遇到的数存储到链表中(除1和这个数本身外),那么,这个数只要这个数不在链表中,它就是关键字。

程序设计:
1.输入格式:
每个测试输入包含 1 个测试用例,第 1 行给出一个正整数 K (<100),第 2 行给出 K 个互不相同的待验证的正整数 n (1<n≤100)的值,数字间用空格隔开

待验证的正整数最大为100,而被100“覆盖”数,有17个,我们可以设b的数组长度为20.

	int i,k,b[20];//①临时存放被覆盖的数  ②数组b用来存放关键字,用于输出
	cin>>k;
	int *a = new int[k]; if(!a) exit(3); //动态分配空间,数组a用来存放k个互不相同待验证的正整数
	 
	for(i = 0;i < k;i++)
		cin>>a[i];

2.创建链表
在生成链表之前,我们先做一些准备工作。
(1)求递推值:positiveSeq(int b[],int m)
函数功能:将被m“覆盖”的数存储在数组b中,并返回数组b的长度。


int positiveSeq(int b[],int m){
	int n = 0;
	while(m > 2){
		if(m % 2 == 0) m = m / 2;
		else m = (3 * m + 1) / 2;
		if(n < 20) b[n++] = m;
	}
	return n; 
}

(2)数组b逆序存储:negativeSeq(int b[],int n)
函数功能:将数组b逆序存储,n为数组b的长度。
比如:b[]={5,8,4,2},在调用negativeSeq(b,4)之后,b[] = {2,4,8,5}

void negativeSeq(int b[],int n){
	for(int i = 0;i < n / 2;i++){
		int j = n - i - 1;
		swap(&b[i],&b[j]);
	}
}

这里用到的swap()函数,比较常见,就不多做介绍了。

void swap(int *p1,int *p2){
	 int temp = *p2;
	 *p2 = *p1;
	  *p1 = temp;
}

(3)创建并生成链表:Insert(node *head,int m)
函数功能:新建一个结点n,将m的值赋给结点n,并将该结点插入head中,返回head。

node* Insert(node *head,int m){
	node *p = NULL,*n = NULL;
	n = new node;
	n->data = m;
	if(head == NULL) {head = n;n->next = NULL;}
	
	p = head;
	while(p->next != NULL && p->data != n->data)
		p = p->next;
	if(p->data != n->data){n->next = head;head = n;}
	return head;
} 

在主函数中,生成链表的过程如下:

	for(i = 0;i < k;i++){
		n = positiveSeq(b,a[i]);
		negativeSeq(b,n);
		for(j = 0;j < n;j++)
			head = Insert(head,b[j]);
	}

生成链表后,就要根据数组a[]来查找关键字,我们先创建一个函数,帮助查找关键字。
3.查找关键字:searchKey(node *head,int m)
函数功能:在head指向的链表中查找m,若链表中有m,则返回-1,否则直接返回m

int searchKey(node *head,int m){
	node *p;
	p = head;
	while(p->next != NULL && p->data != m)
		p = p->next;
	if(p->data == m) return -1;
	else return m;
}

主函数中的查找过程如下:

	for(i = 0,n = 0;i < k;i++){
		m = searchKey(head,a[i]);
		if(m != -1) b[n++] = m;
	}

因为要求按从大到小的顺序输出,所以我们还要对数组b进行排序,从大到小排序
主函数中的排序过程如下:

	for(i = 0;i < n;i++){
		for(j = i + 1;j < n;j++){
			if(b[i] < b[j]) 
				swap(&b[i],&b[j]);
		}
	}

4.输出:
一切准备就绪,我们可以用for循环遍历数组b直接输出。但是,输出又有了要求:数字间用 1 个空格隔开,但一行中最后一个数字后没有空格。,所以要用if…else分别输出。
主函数中的输出过程如下:

	for(i = 0;i < n;i++){
		if(i == n - 1) cout<<b[i]<<endl;
		else cout<<b[i]<<' ';}
}

完整的代码如下:

#include<iostream>
using namespace std;

struct node{
	int data;
	node *next;
}; 

void swap(int *p1,int *p2){
	 int temp = *p2;
	 *p2 = *p1;
	  *p1 = temp;
}

int positiveSeq(int b[],int m){
	int n = 0;
	while(m > 2){
		if(m % 2 == 0) m = m / 2;
		else m = (3 * m + 1) / 2;
		if(n < 20) b[n++] = m;
	}
	return n; 
}

void negativeSeq(int b[],int n){
	for(int i = 0;i < n / 2;i++){
		int j = n - i - 1;
		swap(&b[i],&b[j]);
	}
}

node* Insert(node *head,int m){
	node *p = NULL,*n = NULL;
	n = new node;
	n->data = m;
	if(head == NULL) {head = n;n->next = NULL;}
	
	p = head;
	while(p->next != NULL && p->data != n->data)
		p = p->next;
	if(p->data != n->data){n->next = head;head = n;}
	return head;
} 

int searchKey(node *head,int m){
	node *p;
	p = head;
	while(p->next != NULL && p->data != m)
		p = p->next;
	if(p->data == m) return -1;
	else return m;
}


int main(){
	int i,j,n,k,m;
	int b[20];
	node *head = NULL;
	
	
	cin>>k;
	int *a = new int[k]; if(!a) exit(3);
	 
	for(i = 0;i < k;i++)
		cin>>a[i];
	
	for(i = 0;i < k;i++){
		n = positiveSeq(b,a[i]);
		negativeSeq(b,n);
		for(j = 0;j < n;j++)
			head = Insert(head,b[j]);
	}
	
	for(i = 0,n = 0;i < k;i++){
		m = searchKey(head,a[i]);
		if(m != -1) b[n++] = m;//76行
	}
	
	for(i = 0;i < n;i++){
		for(j = i + 1;j < n;j++){
			if(b[i] < b[j]) 
				swap(&b[i],&b[j]);
		}
	}

	for(i = 0;i < n;i++){
		if(i == n - 1) cout<<b[i]<<endl;
		else cout<<b[i]<<' ';}
}

代码可以通过测试,但是有一个小问题,如果将第76行的

if(m != -1) b[n++] = m;

改成

if(m != -1 && n < 20) b[n++] = m;

就会有一个测试点错误,提示“您的程序未能对评测系统的数据返回正确的结果”。这个想不通哦,数组b的长度在定义时已经确定了,但是显式的写出n < 20这个限制条件,反而有了问题。

  • 7
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值