7. 整数反转
本题来自 LeetCode:7. 整数反转[1]
题目描述
给出一个 32 位的有符号整数,你需要将这个整数中每位上的数字进行反转。
示例 1:
输入: 123
输出: 321
示例 2:
输入: -123
输出: -321
示例 3:
输入: 120
输出: 21
注意:
假设我们的环境只能存储得下 32 位的有符号整数,则其数值范围为
[−2^31, 2^31 − 1]
。请根据这个假设,如果反转后整数溢出那么就返回 0。
题目分析
本题题意为反转整数的数字,主要需要考虑反转后,是否越界。
对于整数
num = i * 10 + j
是否越界,即无法通过
[−2^31, 2^31 − 1]
正确表示。主要分两种情况分析。
题目解答
class Solution {
// 最大值除10的余数
private static final int maxValueMod = Integer.MAX_VALUE % 10;
// 最小值除10的余数
private static final int minValueMod = Integer.MIN_VALUE % 10;
// 最大值除10的结果值
private static final int maxValue_10 = Integer.MAX_VALUE / 10;
// 最小值除10的结果值
private static final int minValue_10 = Integer.MIN_VALUE / 10;
public int reverse(int x) {
// 是否为正数
boolean positive = x 0;
int reverse = 0;
while(x != 0) {
int digit = x % 10;
x /= 10;
// 判读是否越界
if(positive) {
// 判断正数是否越界
if(reverse maxValue_10) {
return 0;
} else if(reverse == maxValue_10) {
if(digit maxValueMod) {
return 0;
}
}
} else {
// 判断负数是否越界
if(reverse minValue_10) {
return 0;
} else if(reverse == minValue_10) {
if(digit minValueMod) {
return 0;
}
}
}
reverse = reverse * 10 + digit;
}
return reverse;
}
}
复杂度分析:
时间复杂度:
O(n)
,表示有
n
位数字
空间复杂度:
O(1)
9. 回文数
本题来自 LeetCode:9. 回文数[2]
题目描述
判断一个整数是否是回文数。回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数。
示例 1:
输入: 121
输出: true
示例 2:
输入: -121
输出: false
解释: 从左向右读, 为 -121 。从右向左读, 为 121- 。因此它不是一个回文数。
示例 3:
输入: 10
输出: false
解释: 从右向左读, 为 01 。因此它不是一个回文数。
进阶:
你能不将整数转为字符串来解决这个问题吗?
解法一
题目分析
本题判断一个整数是否为回文数,可以通过将整数的每一位的数字按顺序存储到数组中,最后判断该数组是否为回文数组即可。
注意负数不是回文数。
题目解答
class Solution {
public boolean isPalindrome(int x) {
if(x 0) {
return false;
}
int n = 0;
ListInteger digits = new ArrayList();
while(x != 0) {
digits.add(x % 10);
x /= 10;
}
int left = 0;
int right = digits.size() - 1;
while(left = right) {
if(digits.get(left) != digits.get(right)) {
return false;
}
left ++;
right --;
}
return true;
}
}
复杂度分析:
时间复杂度:
O(n)
,
n
为整数数字位数。空间复杂度:
O(n)
解法二
题目分析
解法一
使用了额外的空间,也可以通过题
7. 整数反转
的思路,将整数反转后,直接和原整数比较是否相等。需要注意判断是否越界的问题。
题目解答
class Solution {
public boolean isPalindrome(int x) {
// 负数不是回文数
if(x 0) {
return false;
}
// 存储反转后的整数
int y = 0;
int temp = x;
// 反转整数
while(temp != 0) {
int digit = temp % 10;
// 判断是否越界
if(y Integer.MAX_VALUE / 10
|| (y == Integer.MAX_VALUE / 10 && digit Integer.MAX_VALUE % 10)) {
return false;
}
y = y * 10 + digit;
temp /= 10;
}
// 判断反转后的整数和原整数是否相等
return x == y;
}
}
复杂度分析:
时间复杂度:
O(n)
空间复杂度:
O(1)
8. 字符串转换整数 (atoi)
本题来自 LeetCode:8. 字符串转换整数 (atoi)[3]
题目描述
请你来实现一个 atoi 函数,使其能将字符串转换成整数。
首先,该函数会根据需要丢弃无用的开头空格字符,直到寻找到第一个非空格的字符为止。
当我们寻找到的第一个非空字符为正或者负号时,则将该符号与之后面尽可能多的连续数字组合起来,作为该整数的正负号;假如第一个非空字符是数字,则直接将其与之后连续的数字字符组合起来,形成整数。
该字符串除了有效的整数部分之后也可能会存在多余的字符,这些字符可以被忽略,它们对于函数不应该造成影响。
注意:假如该字符串中的第一个非空格字符不是一个有效整数字符、字符串为空或字符串仅包含空白字符时,则你的函数不需要进行转换。
在任何情况下,若函数不能进行有效的转换时,请返回 0。
说明:
假设我们的环境只能存储 32 位大小的有符号整数,那么其数值范围为 [−231, 231 − 1]。如果数值超过这个范围,请返回 INT_MAX (231 − 1) 或 INT_MIN (−231) 。示例 1:
输入: "42"
输出: 42
示例 2:
输入: " -42"
输出: -42
解释: 第一个非空白字符为 '-', 它是一个负号。
我们尽可能将负号与后面所有连续出现的数字组合起来,最后得到 -42 。
示例 3:
输入: "4193 with words"
输出: 4193
解释: 转换截止于数字 '3' ,因为它的下一个字符不为数字。
示例 4:
输入: "words and 987"
输出: 0
解释: 第一个非空字符是 'w', 但它不是数字或正、负号。
因此无法执行有效的转换。
示例 5:
输入: "-91283472332"
输出: -2147483648
解释: 数字 "-91283472332" 超过 32 位有符号整数范围。
因此返回 INT_MIN (−231) 。
题目分析
本题是一条体力题,需要注意好各细节问题。可以分析成三步来解答。
题目解答
class Solution {
public int myAtoi(String str) {
if(str == null && str.length() == 0) {
return 0;
}
// 1. 跳过字符串开头的所有空格
int i = 0;
while(i str.length() && str.charAt(i) == ' ') {
i ++;
}
if(i = str.length()) {
return 0;
}
// 2. 校验第一个字符是否合法,并确定正负
int flag = 1;
char first = str.charAt(i);
if(first == '-') {
flag = -1;
i ++;
} else if(first == '+') {
i ++;
} else if(first - '0' 0 || first - '0' 9) {
return 0;
}
// 3. 转换有效的字符
int num = 0;
while(i str.length()) {
int digit = str.charAt(i) - '0';
if(digit 0 || digit 9) {
return num;
}
digit *= flag;
// 判断是否越界
if(num = 0) {
// 正整数越界
if(num Integer.MAX_VALUE / 10
|| (num == Integer.MAX_VALUE / 10 && digit Integer.MAX_VALUE % 10)) {
return Integer.MAX_VALUE;
}
} else {
// 负整数越界
if(num Integer.MIN_VALUE / 10
|| (num == Integer.MIN_VALUE / 10 && digit Integer.MIN_VALUE % 10)) {
return Integer.MIN_VALUE;
}
}
num = num * 10 + digit;
i ++;
}
return num;
}
}
复杂度分析:
时间复杂度:
O(n)
空间复杂度:
O(1)
190. 颠倒二进制位
本题来自 LeetCode:190. 颠倒二进制位[4]
题目描述
颠倒给定的 32 位无符号整数的二进制位。
示例 1:
输入: 00000010100101000001111010011100
输出: 00111001011110000010100101000000
解释: 输入的二进制串 00000010100101000001111010011100 表示无符号整数 43261596,
因此返回 964176192,其二进制表示形式为 00111001011110000010100101000000。
示例 2:
输入:11111111111111111111111111111101
输出:10111111111111111111111111111111
解释:输入的二进制串 11111111111111111111111111111101 表示无符号整数 4294967293,
因此返回 3221225471 其二进制表示形式为 10101111110010110010011101101001。
提示:
请注意,在某些语言(如 Java)中,没有无符号整数类型。在这种情况下,输入和输出都将被指定为有符号整数类型,并且不应影响您的实现,因为无论整数是有符号的还是无符号的,其内部的二进制表示形式都是相同的。
在 Java 中,编译器使用二进制补码记法来表示有符号整数。因此,在上面的 示例 2 中,输入表示有符号整数 -3,输出表示有符号整数 -1073741825。
进阶:
如果多次调用这个函数,你将如何优化你的算法?
题目分析
题目解答
public class Solution {
// you need treat n as an unsigned value
public int reverseBits(int n) {
int reverse = 0;
int count = 0;
while(n != 0) {
reverse = (reverse 1) | (n & 1);
n = 1;
count ++;
}
// 补足32位
while(count 32) {
reverse = 1;
count ++;
}
return reverse;
}
}
复杂度分析:
时间复杂度:
O(1)
空间复杂度:
O(1)
参考资料
字符串转换整数 (atoi): https://leetcode-cn.com/problems/string-to-integer-atoi/
原文始发于微信公众号(xiaogan的技术博客):