PAT (Advanced Level) Practice 1136 A Delayed Palindrome 字符串翻转

一、概述

就是我们平常说的数字黑洞问题。判断一个数字是不是回文数,如果是,输出,不是,则翻转相加继续判断。

题很简单,体现我是一个智障的本质。

我直接就随便设了两个字符串a和b各十五位,寻思怎么也够了,然后就字符串判断,翻转,atoi转int,再sprintf转字符串。

没看见人家说的最大输入不超过1000位。

我用atoi溢出,换atol,再换atoll,简直逗比,你就算是long long,那也禁不住1000位的输入啊。因此要使用字符串的加法。

先把我自己的分析一下吧。还是有一点教训的。主要是几个点浪费了时间。

二、分析

先看我的思路,虽然蠢但是除了最后一个测试点都可以过的。

接收字符数组并判断。翻转。转int。相加。判断。继续下去。

首先是翻转函数,如下:

void reverseL(char* a,char* b)
{
	int l=strlen(a);
	for(int i=0;i<l;i++)
	{
		b[l-i-1]=a[i];
	}
}

注意这里的char* a,在调用时要事先声明为char a[50]之类,否则会报段错误。因为只声明char*a就调用,因为未分配空间会溢出。这样做不好,推荐使用reverse函数直接翻转。但是reverse翻转会破坏原来的变量,是在它之上直接反转,这样不符合我们的要求。因此可以给他套上一层壳子,如下:

string rev(string s) {
    reverse(s.begin(), s.end());
    return s;
}

利用值传递不改变原来的变量,从而返回另一个string。这种用法要记住,关键在于参数是string,返回值也会string。

判断函数如下:

int judgeL(char* a)
{
	int l=strlen(a);
	//if(l==1&&a[0]==0)
	//return 1;
	for(int i=0;i<l/2;i++)
	{
		if(a[i]!=a[l-i-1])
		return 0;
	}
	return 1;
}

也很蠢,本来直接反转然后看他们俩是否相等即可。

在这里我们明确两点,其一,想对字符串操作,形参的类型必须是char*,实参必须是char* a[100]之类,其二,在函数中改变字符串中的值那就是真的改变了。因为传进去的本质上是字符串的首地址,是直接按地址改的。与传string不同。

然后判断即可,如下:

int num=0;
	int flag=judgeL(n1);
	while(flag==0&&num<10)
	{
		reverseL(n1,n2);
		printf("%s + %s =",n1,n2);
		long long int a=atoll(n1);
		long long int b=atoll(n2);
		long long int c=a+b;
		//_itoa(c,n1,10);
		//sprintf(n1,"%d",a);
		//sprintf(n2,"%d",b);
		sprintf(n1,"%lld",c);
		printf(" %s\n",n1);
		num++;
		flag=judgeL(n1);
	}

注意itoa函数是不能使用的,但可以使用sprintf函数,重新复习一下sprintf函数,三个参数,第一个是结果b,第二个是要转换的变量a的解释方式,第三个是要转换的变量a。如上我们要把int的a转换成char*的b,那么三个变量依次是b,"%d",a,注意第二个不是"%s",这个容易记混。

这样在数字较小时是正确的。下面我们看AC代码。

翻转函数在上文我们已经分析过了。现在我们分析核心函数,string加法,如下:

string add(string s1,string s2)
{
	string s=s1;
	int len=s1.size();
	int carry=0;
	for(int i=len-1;i>=0;i--)
	{
		s[i]=(s1[i]-'0'+s2[i]-'0'+carry)%10+'0';
		carry=(s1[i]-'0'+s2[i]-'0'+carry)/10;
	}
	if(carry==1)
	s="1"+s;
	return s;
}

参数两个string,返回值亦为string。首先注意一点,要在函数中声明一个string作为和,设其为s,一定要给s初始化,这里使s=s1,不初始化会报错。然后初始化进位为0。从string的最后一位开始一直加到第一位,先求每位的和,然后求此位的进位。如果全算完了进位还是1,那么在最前面加一个1。

对于string来说,在最前面加一个1可以直接写为s=“1”+s;很方便。然后return s即可。之后判断并输出。

三、总结

本题我们要学会两种常用函数的写法:

字符串加法以及字符串翻转。

PS:代码如下:

#include<stdio.h>
#include<cstdio>
#include<iostream>
#include<map>
#include<vector>
#include<set>
#include<queue>
#include<string>
#include<cstring>
#include<math.h>
#include<stdlib.h>
#include<algorithm>
using namespace std;
string s1,s2;
string rev(string s)
{
	reverse(s.begin(),s.end());
	return s;
}
string add(string s1,string s2)
{
	string s=s1;
	int len=s1.size();
	int carry=0;
	for(int i=len-1;i>=0;i--)
	{
		s[i]=(s1[i]-'0'+s2[i]-'0'+carry)%10+'0';
		carry=(s1[i]-'0'+s2[i]-'0'+carry)/10;
	}
	if(carry==1)
	s="1"+s;
	return s;
}
int main()
{
	cin>>s1;
	s2=rev(s1);
	if(s1==s2)
	{
		cout<<s1<<" is a palindromic number.";
		return 0;
	}
	else
	{
		int now=0;
		while(now<10)
		{
			cout<<s1<<" + "<<s2<<" = ";
			s1=add(s1,s2);
			cout<<s1<<"\n";
			s2=rev(s1);
			now++;
			if(s1==s2)
			{
				cout<<s1<<" is a palindromic number.";
				return 0;
			}
		}
		cout<<"Not found in 10 iterations.";
	}
	
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值