1.两数之和
给定一个整数数组 nums和一个整数目标值target,请你在该数组中找出和为目标值target的那两个整数,并返回它们的数组下标。
你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。
示例 :
输入:nums = [2,7,11,15], target = 9
输出:[0,1]
解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1] 。
用哈希表解决问题
看见了一个很有趣的解法,原作者地址画解算法:1. 两数之和 - 两数之和 - 力扣(LeetCode) (leetcode-cn.com)
这道题本身如果通过暴力遍历的话也是很容易解决的,时间复杂度在 O(n2)
由于哈希查找的时间复杂度为 O(1),所以可以利用哈希容器 map 降低时间复杂度
遍历数组 nums,i 为当前下标,每个值都判断map中是否存在 target-nums[i] 的 key 值
如果存在则找到了两个值,如果不存在则将当前的 (nums[i],i) 存入 map 中,继续遍历直到找到为止
如果最终都没有结果则抛出异常
思路图解
初始化
13 - 2 = 11 ,map中不存在该key值,在map中存入(2,0)
13 - 7 = 5 ,map中不存在该key值,在map中存入(7,1)
13 - 11 = 2 ,该key值存在,返回2的下标0和11的下标2
代码实现
class Solution {
public int[] twoSum(int[] nums, int target) {
Map<Integer, Integer> map = new HashMap<>();
for(int i = 0; i< nums.length; i++) {
if(map.containsKey(target - nums[i])) {
return new int[] {map.get(target-nums[i]),i};
}
map.put(nums[i], i);
}
throw new IllegalArgumentException("No two sum solution");
}
}
7.整数反转
给你一个 32 位的有符号整数 x ,返回将 x 中的数字部分反转后的结果。
如果反转后整数超过 32 位的有符号整数的范围,就返回 0。
假设环境不允许存储 64 位整数(有符号或无符号)。
示例 :
输入:x = -123 输出:-321
输入:x = 120 输出:21
思路图解
拿到这个整数的 末尾数字 就可以了。
以12345为例,先拿到5,再拿到4,之后是3,2,1,我们按这样的顺序就可以反向拼接处一个数字了,也就能达到反转的效果。
怎么拿末尾数字呢?好办,用取模运算就可以了
- 将12345 % 10 得到5,之后将12345 / 10
- 将1234 % 10 得到4,再将1234 / 10
- 将123 % 10 得到3,再将123 / 10
- 将12 % 10 得到2,再将12 / 10
- 将1 % 10 得到1,再将1 / 10
这么看起来,一个循环就搞定了,循环的判断条件是x>0
但这样不对,因为忽略了负数
循环的判断条件应该是while(x!=0),无论正数还是负数,按照上面不断的 x/10 这样的操作,最后都会变成0,所以判断终止条件就是 x!=0
在Java中,负数取余,得到的余数也是负数
有了取模和除法操作,对于像12300这样的数字,也可以完美的解决掉了。
看起来这道题就这么解决了,但请注意,题目上还有这么一句
如果反转后整数超过 32 位的有符号整数的范围,就返回 0。
有些数字可能是合法范围内的数字,但是反转过来就超过范围了。
假设有1147483649这个数字,它是小于最大的32位整数2147483647的,但是将这个数字反转过来后就变成了9463847411,这就比最大的32位整数还要大了,所以肯定要返回0(溢出了)。
也就是说,我们不能直接用res与比较,得提前一位比较,在res还没取到第10位时,用9位的res与前九位比较
上图中,绿色的是最大10位整数
只要res的前九位 > 214748364 就溢出了,若 = 214748364,就再判断tmp是否 > 7
对于负数也是一样的
只要res的前九位 < -214748364 就溢出了,若 = -214748364,就再判断tmp是否 < -8
代码实现
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;
}
}
9.回文数
给你一个整数 x ,如果 x 是一个回文整数,返回 true ;否则,返回 false 。
回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数。例如,121 是回文,而 123 不是。
示例 1:
输入:x = 121
输出:true
示例 2:
输入:x = -121
输出:false
解释:从左向右读, 为 -121 。 从右向左读, 为 121- 。因此它不是一个回文数。
方法1 转为字符串
class Solution {
public boolean isPalindrome(int x) {
String reversedStr = (new StringBuilder(x + "")).reverse().toString();
return (x + "").equals(reversedStr);
}
}
方法2 取后半段翻转
按照第7题回文数的思路,用如下代码段可以取出后半段并翻转
int revertedNumber = 0;
//循环
int tmp = x % 10;
revertedNumber = revertedNumber * 10 + tmp;
x /= 10;
那么如何判断是不是回文数呢
判断 x
是不是小于 revertNum
,当它小于的时候,说明数字已经对半或者过半了
判断奇偶数情况:如果是偶数的话,revertNum 和 x 相等;如果是奇数的话,最中间的数字就在revertNum 的最低位上,将它除以 10 以后应该和 x 相等。
class Solution {
public boolean isPalindrome(int x) {
// 末尾为 0 直接返回 false
if (x < 0 || (x % 10 == 0 && x != 0)) return false;
int revertedNumber = 0;
while (x > revertedNumber) {
revertedNumber = revertedNumber * 10 + x % 10;
x /= 10;
}
return x == revertedNumber || x == revertedNumber / 10;
}
}
13.罗马数字转整数
罗马数字包含以下七种字符: I, V, X, L,C,D 和 M。
字符 数值
I 1
V 5
X 10
L 50
C 100
D 500
M 1000
例如, 罗马数字 2 写做 II ,即为两个并列的 1。12 写做 XII ,即为 X + II 。 27 写做 XXVII, 即为 XX + V + II 。
通常情况下,罗马数字中小的数字在大的数字的右边。但也存在特例,例如 4 不写做 IIII,而是 IV。数字 1 在数字 5 的左边,所表示的数等于大数 5 减小数 1 得到的数值 4 。同样地,数字 9 表示为 IX。这个特殊的规则只适用于以下六种情况:
I 可以放在 V (5) 和 X (10) 的左边,来表示 4 和 9。
X 可以放在 L (50) 和 C (100) 的左边,来表示 40 和 90。
C 可以放在 D (500) 和 M (1000) 的左边,来表示 400 和 900。
思路图解
一言蔽之,把一个小值放在大值的左边,就是做减法,否则为加法。