【刷题之路】LeetCode 9.回文数

一、题目描述

原题连接: LeetCode 9.回文数

题目描述:
给你一个整数 x ,如果 x 是一个回文整数,返回 true ;否则,返回 false 。
回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数。
例如,121 是回文,而 123 不是。

示例 1:
输入: x = 121
输出: true

示例 2:
输入: x = -121
输出: false
解释:从左向右读, 为 -121 。 从右向左读, 为 121- 。因此它不是一个回文数。

示例 3:
输入: x = 10
输出: false
解释:从右向左读, 为 01 。因此它不是一个回文数。

二、解题

1、方法1——数字转化成字符串

1.1、思路分析

一个很容易想到的思路是先将数字转化成字符串,再将转化后的字符串进行逆序,逆序后再跟原来的字符串进行比较,如果相等,则返回true,否则返回false。

1.2、代码实现

有了以上思路,那我们写起代码来也就水到渠成了:

bool isPalindrome1(int x) {
	// 如果x为负数则直接返回false
	if (x < 0) {
		return false;
	}
	char num[11] = { 0 }; // 整型最长有十位
	// 先将数字转化成字符串
	int n = 0; // 记录该数字有多少位,也即转化成的字符串的长度
	while (x) {
		num[n] = (x % 10) + '0';
		n++;
		x /= 10;
	}
	// 此时得到的num的内容已经是逆序了的
	num[n] = '\0'; // 在末尾加上字符串结束标志
	char temp[11] = { 0 };
	strcpy(temp, num); // 将num拷贝到temp中
	// 再将temp逆序
	int left = 0;
	int right = n - 1;
	while (left < right) {
		char tmp = temp[left];
		temp[left] = temp[right];
		temp[right] = tmp;
		left++;
		right--;
	}
	// 比较逆序后的temp和num
	if (strcmp(num, temp) == 0) {
		return true;
}
	return false;
}

时间复杂度:O(n),n为数字的位数或字符串的长度,转化时的复杂度为log10n,逆序时的复杂度为n/2故复杂度为O(n)。
空间复杂度:O(n),我们需要用到与数组长度相等的额外空间。

改进:
其实我们并不需要在对转化好的字符串进行逆序,直接在原字符串上进行判断即可,只需要判断字符串的左右两端是否完全相等即可:

bool isPalindrome1(int x) {
	// 如果x为负数则直接返回false
	if (x < 0) {
		return false;
	}
	char num[11] = { 0 }; // 整型最长有十位
	// 先将数字转化成字符串
	int n = 0; // 记录该数字有多少位,也即转化成的字符串的长度
	while (x) {
		num[n] = (x % 10) + '0';
		n++;
		x /= 10;
	}
	num[n] = '\0'; // 在末尾加上字符串结束标志
	// 此时得到的num的内容已经是逆序了的
	int left = 0;
	int right = n - 1;
	// 对比num的左右两边是否全都相等
	while (left < right) {
		if (num[left] == num[right]) {
			left++;
			right--;
		}
		else {
			return false;
		}
	}
	return true;
}

时间复杂度:O(n),n为数字的位数或字符串的长度,转化时的复杂度为log10n,比较时的复杂度为n/2故复杂度为O(n)。
空间复杂度:O(n),我们需要用到与数组长度相等的额外空间。

2、方法2——反转数字的一半

2.1、思路分析

如果把一个整数整体反转过来那很可能就会发生溢出问题,例如INT_MAX的值为2147483647,那它或接近它的数反转过来就是七十亿多,早已远远超出了整形的范围。所以我们不能将数字整体反转。
但我们并不需要将数字整体反转过来,就像方法1中的改进思路一样,我们只需要比较左右两端的数字是否完全相同即可,所以,我们可以只把数字的一半进行反转(例如后一半),用一个变量reverse_number来保存,每取到一位数字我们就让x / 10,故随着循环的不断进行,x将越来越小,reverse_number将越来越大,对于偶数位的数字,如果出现x = = reverse_number则循环可以停止,表示x是一个回文数对于奇数,如果出现x = = reverse_number / 10或x / 10 == reverse_number则循环可以停止,表示x是一个回文数。例如:
在这里插入图片描述

2.2、代码实现

有了以上思路,那我们写起代码来也就水到渠成了:

bool isPalindrome2(int x) {
	// 如果x为负数或者末尾有0,直接返回false
	if (x < 0 || (x % 10 == 0 && x != 0)) {
		return false;
	}
	int reverse_number = 0;
	while (x > reverse_number) {
		reverse_number = reverse_number * 10 + (x % 10);
		x /= 10;
	}
	return x == reverse_number || x == reverse_number / 10;
}

时间复杂度:O(log10(N)),N为数字x的值,每取一个数字,我们都要对x进行除10操作,所以时间复杂度为O(log10(N))。
空间复杂度:O(1),我们只需要一个int类型变量reverse_number来帮我们存储反转后的数字。

3、方法3——数学解法

3.1、思路分析

思路和方法1的改进版的思路差不多,只不过我们这次是直接取出x两端的数字进行比较(即取出最高位和最低位)。不再次转化成字符串。取出x的最高位可以用x / "最高位权重"来获取,取得最低位可以用x % 10来获取,取完一轮后就要去除x的最高位和最低位,去除最高位可以用x %= "最高位权重"达到,而去除最低位则要在去除最高位的基础上用x /= 10 来完成,例如对数字1234321,我们有如下过程:
在这里插入图片描述

3.2、代码实现

有了以上思路,那我们写起代码来也就水到渠成了:

bool isPalindrome3(int x) {
	if (x < 0) {
		return false;
	}
	// 首先获得x有多少位
	int temp = x;
	int n = 0; // 标记x有多少位
	while (temp) {
		n++;
		temp /= 10;
	}
	int high = 0; // 保存x的高位
	int low = 0; // 保存x的低位
	int weight = pow(10, n - 1); // 保存x的高权重
	while (x > 0) {
		high = x / weight;
		low = x % 10;
		if (high != low) {
			return false;
		}
		x = (x % weight) / 10;
		weight /= 100; // 减少了两位
	}
	return true;
}

时间复杂度:O(n),n为x的位数。
空间复杂度:O(1)

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

林先生-1

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值