7. 整数反转(中等)
给你一个 32 位的有符号整数
x
,返回将x
中的数字部分反转后的结果。如果反转后整数超过 32 位的有符号整数的范围
假设环境不允许存储 64 位整数(有符号或无符号)。[−231, 231 − 1]
,就返回 0。示例 1:
输入:x = 123 输出:321示例 2:
输入:x = -123 输出:-321示例 3:
输入:x = 120 输出:21示例 4:
输入:x = 0 输出:0提示:
-231 <= x <= 231 - 1
解法一、字符串操作,考虑多种情况模拟 (16mins)
复杂但不烧脑。。参考了之前一道题的边界讨论方式(即这里的bound),正负数需要分开辨别。用了StringBuffer的reverse API
使用负号记录,转换时不考虑负号,避免长度出问题(而且翻转后负号会去后面)。长度>10,越界。长度<10,三目讨论正负。长度等于10,分正负号讨论是否越界。
class Solution {
public static int reverse(int x) {
boolean negative = false;
if(x < 0){
negative = true;
x = Math.abs(x);
}
StringBuffer sb = new StringBuffer(String.valueOf(x)).reverse();
int bound = Integer.MAX_VALUE / 10;//原十位 这里九位
if(sb.length() > 10){
return 0;
}else if(sb.length() <= 9){
return negative ? -Integer.parseInt(sb.toString()):Integer.parseInt(sb.toString());
}else{
if(Integer.parseInt(sb.toString().substring(0,9)) > bound){
return 0;
}else if(Integer.parseInt(sb.toString().substring(0,10)) < bound){
return negative ? -Integer.parseInt(sb.toString()):Integer.parseInt(sb.toString());
}else{
if((negative && sb.toString().charAt(9) - '8' > 0 )|| (!negative && sb.toString().charAt(9) - '7' > 0 )){
return 0;
}else{
return negative ? -Integer.parseInt(sb.toString()):Integer.parseInt(sb.toString());
}
}
}
}
}
解法二、循环取数
这里观看评论区,有以下收获:
- 由于原始int数据,例如对于2147483647(最大情况),原数据不溢出、翻转后可以溢出的,一定是类似22*******1/2的情况。总之,尾数一定是1或者2,就不必再考虑tmp>7和<-8,因为数据限制。
- 因为这里是手动转int,不使用Integer.valueOf api的话,就可以规避报错。所以,比起转换途中考虑是否溢出,不如直接转换完毕之后讨论是否溢出,是一个非常灵巧的逆向思维。而转换的方式就是last == res / 10(last是上一步的结果,res是这一步的结果),如果溢出,显然就不相等了。也就是说,考虑溢出确实是重要的,但利用溢出也很重要。
- 模不能是负数,但负数可以取模。余数符号与被模数相同。
class Solution {
public int reverse(int x) {
int res = 0;
while(x!=0) {
//每次取末尾数字
int tmp = x%10;
//判断是否 大于 最大32位整数
if (res>214748364 || (res==214748364 && tmp>7)) {
return 0;
}
//判断是否 小于 最小32位整数
if (res<-214748364 || (res==-214748364 && tmp<-8)) {
return 0;
}
res = res*10 + tmp;
x /= 10;
}
return res;
}
}
作者:王尼玛
链接:https://leetcode.cn/problems/reverse-integer/solutions/211865/tu-jie-7-zheng-shu-fan-zhuan-by-wang_ni_ma/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
9. 回文数(简单)
给你一个整数
x
,如果x
是一个回文整数,返回true
;否则,返回false
。回文数
是指正序(从左向右)和倒序(从右向左)读都是一样的整数。
- 例如,
121
是回文,而123
不是。示例 1:
输入:x = 121 输出:true示例 2:
输入:x = -121 输出:false 解释:从左向右读, 为 -121 。 从右向左读, 为 121- 。因此它不是一个回文数。示例 3:
输入:x = 10 输出:false 解释:从右向左读, 为 01 。因此它不是一个回文数。提示:
-231 <= x <= 231 - 1
进阶:你能不将整数转为字符串来解决这个问题吗?
解法一 翻转再比对(3mins)
先转换再考虑相等。如果原数不溢出,转换数肯定也不溢出。感觉数字比字符串的回文好算的缘故是可以直接比对,不好算的缘故是无法精确且迅速地取下标
class Solution {
public static boolean isPalindrome(int x) {
if(x < 0)return false;
int t = x;
int res = 0;
while(x!=0){
int temp = x %10;
res = res * 10 + temp;
x /=10;
}
return t == res ? true:false;
}
}
解法二 解法一优化
本质上和解法一是一样的,但是①不需要声明额外变量②return里用||和/10来去除奇数位时翻转数中位的思想很天才。如,原数字是12321,处理后变成x=12 翻转数 =123 这个3不需要辨识,它总与自身相等。
while循环的条件:处理一半(即翻转一半)就足够考虑是否相等了。
class Solution {
public boolean isPalindrome(int x) {
// 特殊情况:
// 如上所述,当 x < 0 时,x 不是回文数。
// 同样地,如果数字的最后一位是 0,为了使该数字为回文,
// 则其第一位数字也应该是 0
// 只有 0 满足这一属性
if (x < 0 || (x % 10 == 0 && x != 0)) {
return false;
}
int revertedNumber = 0;
while (x > revertedNumber) {
revertedNumber = revertedNumber * 10 + x % 10;
x /= 10;
}
// 当数字长度为奇数时,我们可以通过 revertedNumber/10 去除处于中位的数字。
// 例如,当输入为 12321 时,在 while 循环的末尾我们可以得到 x = 12,revertedNumber = 123,
// 由于处于中位的数字不影响回文(它总是与自己相等),所以我们可以简单地将其去除。
return x == revertedNumber || x == revertedNumber / 10;
}
}
作者:力扣官方题解
链接:https://leetcode.cn/problems/palindrome-number/solutions/281686/hui-wen-shu-by-leetcode-solution/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
解法三、评论区的拉马努金解法
默默地服了。。
class Solution {
public boolean isPalindrome(int x) {
if(x==1122||x==123123||x==1000021||x==21120||x<0)return false;
if(x<10&&x>=0||x%11==0||x==313||x==101||x==88888||x==2222222)return true;
else return false;
}
}
479. 最大回文数乘积(困难)
给定一个整数 n ,返回 可表示为两个
n
位整数乘积的 最大回文整数 。因为答案可能非常大,所以返回它对1337
取余 。示例 1:
输入:n = 2 输出:987 解释:99 x 91 = 9009, 9009 % 1337 = 987示例 2:
输入:n = 1 输出:9提示:
1 <= n <= 8
解法一、暴力枚举
没感觉到任何这道题配是困难的地方。证明也很粗糙。。直奔题解了。原思路是二重循环转字符串开乘,感觉很艰涩,不过这个字符串乘法模板还挺有意思的。总感觉和之前做过的一道题有点像。。
字符串乘法模板
public String multiplyStrings(String num1, String num2) {
int m = num1.length(), n = num2.length();
int[] pos = new int[m + n];
for (int i = m - 1; i >= 0; i--) {
for (int j = n - 1; j >= 0; j--) {
int mul = (num1.charAt(i) - '0') * (num2.charAt(j) - '0');
int sum = mul + pos[i + j + 1];
pos[i + j] += sum / 10;
pos[i + j + 1] = sum % 10;
}
}
StringBuilder sb = new StringBuilder();
for (int p : pos) {
if (!(sb.length() == 0 && p == 0)) {
sb.append(p);
}
}
return sb.length() == 0 ? "0" : sb.toString();
}
题解
其实就是对于n位数相乘,上限2n位,往下找回文串。不用确认是不是回文,直接确定左面造右面。 甚至还用了long,不讲武德。。83ms,居然没有超时
class Solution {
public int largestPalindrome(int n) {
if (n == 1) return 9;
int max = (int) Math.pow(10, n) - 1;
for (int i = max; i >= 0; i--) {
long num = i, t = i;
while (t != 0) {
num = num * 10 + (t % 10);
t /= 10;
}
for (long j = max; j * j >= num; j--) {
if (num % j == 0) return (int)(num % 1337);
}
}
return -1;
}
}
作者:宫水三叶
链接:https://leetcode.cn/problems/largest-palindrome-product/solutions/1424568/by-ac_oier-t8j7/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
解法二、你说得对,但我打表
class Solution {
static int[] ans = new int[]{9,987,123,597,677,1218,877,475};
public int largestPalindrome(int n) {
return ans[n - 1];
}
}
564. 寻找最近的回文数(困难)
给定一个表示整数的字符串
n
,返回与它最近的回文整数(不包括自身)。如果不止一个,返回较小的那个。“最近的”定义为两个整数差的绝对值最小。
示例 1:
输入: n = "123" 输出: "121"示例 2:
输入: n = "1" 输出: "0" 解释: 0 和 2是最近的回文,但我们返回最小的,也就是 0。提示:
1 <= n.length <= 18
n
只由数字组成n
不含前导 0n
代表在[1, 1018 - 1]
范围内的整数
解法一、暴力枚举
假如例子是12345,那么取出123,造一个100001,造一个9999,造一个12221,造一个12321,造一个12421,比较五个里哪个差值最小。
是long,它用了long魔法jpg
看评论区说是字节三面。感觉这种形式暴力出来的题真的很有用吗。。甚至写完都没感觉到有特别能讲的地方
倒是明显感觉到边界处理进步了很多,造轮子速度也快了
class Solution {
public static String nearestPalindromic(String n) {
int len = n.length();
long cur = Long.parseLong(n);
Set<Long> res = new HashSet<>();
res.add((long)Math.pow(10,len) +1);
res.add((long)Math.pow(10,len-1) -1);
long t = Long.parseLong(n.substring(0,(len+1)/2));
for(long i = t-1;i <= t+1;i++){
long temp = getNum(i,len % 2 == 0);
if(temp != cur){
res.add(temp);
}
}
long r = -1;
long min = Long.MAX_VALUE;
for(long num : res){
if(r == -1)r = num;
if(Math.abs(num - cur) < min){
min = Math.abs(num - cur);
r = num;
}else if(Math.abs(num - cur) == min && num < r){
r = num;
}
}
return String.valueOf(r);
}
public static long getNum(long k,boolean isEven){
long t = k;
//123456
//122 t = 122
if(!isEven) {//偶数
t /= 10;
}
while (t != 0) {
k = k * 10 + t % 10;
t /= 10;
}
return k;
}
}
231. 2 的幂(简单)
相关标签
相关企业
给你一个整数
n
,请你判断该整数是否是 2 的幂次方。如果是,返回true
;否则,返回false
。如果存在一个整数
x
使得n == 2x
,则认为n
是 2 的幂次方。示例 1:
输入:n = 1 输出:true 解释:20 = 1示例 2:
输入:n = 16 输出:true 解释:24 = 16示例 3:
输入:n = 3 输出:false提示:
-231 <= n <= 231 - 1
进阶:你能够不使用循环/递归解决此问题吗?
解法一、暴力
试着用2一路乘了,成功超时。(。。。
解法二、换底公式
一个数字时是以e为底。如果n是2的幂,那么返回应该是个整数
class Solution {
public boolean isPowerOfTwo(int n) {
if (n <= 0) return false;
// 换底公式
double log_2_n = Math.log(n) / Math.log(2);
return log_2_n == (int) log_2_n;
}
}
解法三、和最大比较
2的幂即约数只有2,不妨和2^30取一下模。
class Solution {
static final int BIG = 1 << 30;
public boolean isPowerOfTwo(int n) {
return n > 0 && BIG % n == 0;
}
}
作者:力扣官方题解
链接:https://leetcode.cn/problems/power-of-two/solutions/796201/2de-mi-by-leetcode-solution-rny3/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
解法四、位运算
两种解法放一起了。n&(n-1),如果是2的幂,则二进制是10···00,假如是1000,n-1则是0111,按位与可以移除。 取负同理
class Solution {
public boolean isPowerOfTwo(int n) {
return n > 0 && (n & (n - 1)) == 0;
}
}
class Solution {
public boolean isPowerOfTwo(int n) {
return n > 0 && (n & -n) == n;
}
}
作者:力扣官方题解
链接:https://leetcode.cn/problems/power-of-two/solutions/796201/2de-mi-by-leetcode-solution-rny3/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
342. 4的幂
给定一个整数,写一个函数来判断它是否是 4 的幂次方。如果是,返回
true
;否则,返回false
。整数
n
是 4 的幂次方需满足:存在整数x
使得n == 4x
示例 1:
输入:n = 16 输出:true示例 2:
输入:n = 5 输出:false示例 3:
输入:n = 1 输出:true提示:
-231 <= n <= 231 - 1
进阶:你能不使用循环或者递归来完成本题吗?
解法一、换底
class Solution {
public boolean isPowerOfFour(int n) {
if(n <=0)return false;
double t = Math.log(n)/Math.log(4);
return t == (int)t ? true:false;
}
}
解法二、位运算+长度确认
比如2是10 4的二进制是100,总之1/4/16转二进制都是奇数长度
class Solution {
public static boolean isPowerOfFour(int n) {
String a = Integer.toBinaryString(n);
return n > 0 && (n & (n - 1)) == 0 && a.length() % 2 == 1 ? true:false;
}
}
用十六进制的aaaaaa作为标识(这个转换为二进制的形式是1010,偶数位是1,与可以把奇数位消掉)
class Solution {
public boolean isPowerOfFour(int n) {
return n > 0 && (n & (n - 1)) == 0 && (n & 0xaaaaaaaa) == 0;
}
}
作者:力扣官方题解
链接:https://leetcode.cn/problems/power-of-four/solutions/798268/4de-mi-by-leetcode-solution-b3ya/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
取模,4%3 = 1,2%3 = 2。。这个好厉害啊(
class Solution {
public:
bool isPowerOfFour(int n) {
return n > 0 && (n & (n - 1)) == 0 && n % 3 == 1;
}
};
作者:力扣官方题解
链接:https://leetcode.cn/problems/power-of-four/solutions/798268/4de-mi-by-leetcode-solution-b3ya/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
碎碎念
- HashSet看起来还挺好用的,第一次用到,能够用foreach也挺开心,喜欢
- 虽然是简单,但是没想到位运算的话就会很复杂,空套循环。。是真的需要提高对二进制数字的敏感度了
- 被马拉车+BF+KMP整自闭了一段时间,昨天休息了一天,今天一打开三简一中两困难(耗时三小时五分),也是又感觉有点命运多舛了