08 字符串转换整数(atoi)
难度:中等
请你来实现一个 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) 。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/string-to-integer-atoi
题解:一道非常恶心的题,不难,但是恶心。需要考虑到很多种情况。提交的时候有点急了,导致错误了很多次。应尽可能枚举出所有的情况。自己没有考虑到的情况包括,±2的情况,- 234的情况。因此解题时可以先找符号和空格,之后再去判断数字。同时,在数字相乘的时候,要考虑到算乘法的过程中也可能超过int的界限。
class Solution {
public:
int myAtoi(string str) {
int flag = 0;
long long ans = 0;
int i;
for (i = 0; i < str.size(); i++) {
if (str[i] == ' ' && flag ==0){
continue;
}
if (str[i] == '+' && flag == 0) {
flag = 1;
continue;
}
if (str[i] == '-' && flag == 0) {
flag = -1;
continue;
}
break;
}
for (; i < str.size(); i++) {
if (str[i] >= '0' && str[i] <= '9') {
if (ans > INT_MAX) break;
if (ans < INT_MIN) break;
ans *= 10;
ans += str[i] - '0';
}
else break;
}
if (flag == -1)
ans *= -1;
if (ans > INT_MAX)
return INT_MAX;
if (ans < INT_MIN)
return INT_MIN;
return ans;
}
};
09 回文数
难度:简单
判断一个整数是否是回文数。回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数。
示例 1:
输入: 121
输出: true
示例 2:
输入: -121
输出: false
解释: 从左向右读, 为 -121 。 从右向左读, 为 121- 。因此它不是一个回文数。
示例 3:
输入: 10
输出: false
解释: 从右向左读, 为 01 。因此它不是一个回文数。
进阶:
你能不将整数转为字符串来解决这个问题吗?
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/palindrome-number
题解:这道题是一道题,重点在要不通过字符串的方式来进行反转,那就通过取模的方式来转换成反转后的数字,判断两数字是否相等。注意的是,对于INT_MAX反转后会超过int的存储范围,所以可以使用long来存储数值。
class Solution {
public:
bool isPalindrome(int x) {
if (x < 0) return false;
long y = 0, tmp = x;;
while (x) {
y *= 10;
y += x % 10;
x /= 10;
}
return tmp == y ? true: false;
}
};
11 盛最多水的容器
难度:中等
给你 n 个非负整数 a1,a2,…,an,每个数代表坐标中的一个点 (i, ai) 。在坐标内画 n 条垂直线,垂直线 i 的两个端点分别为 (i, ai) 和 (i, 0)。找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。
说明:你不能倾斜容器,且 n 的值至少为 2。
图中垂直线代表输入数组 [1,8,6,2,5,4,8,3,7]。在此情况下,容器能够容纳水(表示为蓝色部分)的最大值为 49。
示例:
输入:[1,8,6,2,5,4,8,3,7]
输出:49
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/container-with-most-water
题解:开始想的是用O(n^2)的动态规划来解,瞄了一眼题解,原来还有线性的解法,于是开始冥思苦想。开始想着两个指针都从左端开始,后来发现无法更新,才想明白,一定是两个指针分别在左右端点向中间靠拢的。聚拢的方式为左右端点谁更小就谁先向中间聚拢,聚拢的同时维护最大值即可,没有坑点。
class Solution {
public:
int maxArea(vector<int>& height) {
int ans = 0;
int l = 0, r = height.size() - 1;
while (l < r) {
if (height[l] < height[r]) {
ans = max(ans, height[l] * (r - l));
l++;
}
else {
ans = max(ans, height[r] * (r - l));
r--;
}
}
return ans;
}
};
12 整数转罗马数字
难度:中等
罗马数字包含以下七种字符: 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。
给定一个整数,将其转为罗马数字。输入确保在 1 到 3999 的范围内。
示例 1:
输入: 3
输出: “III”
示例 2:
输入: 4
输出: “IV”
示例 3:
输入: 9
输出: “IX”
示例 4:
输入: 58
输出: “LVIII”
解释: L = 50, V = 5, III = 3.
示例 5:
输入: 1994
输出: “MCMXCIV”
解释: M = 1000, CM = 900, XC = 90, IV = 4.
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/integer-to-roman
题解:一道非常无脑,考验耐心的题目,可以把字符都提前存放到数组中。我直接无脑模拟了。
class Solution {
public:
string intToRoman(int num) {
string ans = "";
if (num >= 1000) {
for (int i = 0; i < num / 1000; i++) {
ans += "M";
}
num %= 1000;
}
if (num >= 500) {
if (num / 100 == 9) {
ans += "CM";
num %= 100;
}
else {
ans += "D";
num -= 500;
}
}
if (num >= 100) {
if (num / 100 == 4) {
ans += "CD";
}
else {
for (int i = 0; i < num / 100; i++) {
ans += "C";
}
}
num %= 100;
}
if (num >= 50) {
if (num / 10 == 9) {
ans += "XC";
num %= 10;
}
else {
ans += "L";
num -= 50;
}
}
if (num >= 10) {
if (num / 10 == 4) {
ans += "XL";
}
else {
for (int i = 0; i < num / 10; i++) {
ans += "X";
}
}
num %= 10;
}
if (num >= 5) {
if (num == 9) {
ans += "IX";
num -= 9;
}
else {
ans += "V";
num -= 5;
}
}
if (num > 0) {
if (num == 4) {
ans += "IV";
}
else {
for (int i = 0; i < num; i++) {
ans += "I";
}
}
num = 0;
}
return ans;
}
};
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。
给定一个罗马数字,将其转换成整数。输入确保在 1 到 3999 的范围内。
示例 1:
输入: “III”
输出: 3
示例 2:
输入: “IV”
输出: 4
示例 3:
输入: “IX”
输出: 9
示例 4:
输入: “LVIII”
输出: 58
解释: L = 50, V= 5, III = 3.
示例 5:
输入: “MCMXCIV”
输出: 1994
解释: M = 1000, CM = 900, XC = 90, IV = 4.
提示:
题目所给测试用例皆符合罗马数字书写规则,不会出现跨位等情况。
IC 和 IM 这样的例子并不符合题目要求,49 应该写作 XLIX,999 应该写作 CMXCIX 。
关于罗马数字的详尽书写规则,可以参考 罗马数字 - Mathematics 。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/roman-to-integer
题解:这道题和12题非常的类似,只是变成了从罗马数字转换成整数。这次使用了一个map,用来找对应的位置。左边的比右边数字小就减,否则就加。通过看大佬的写法发现了一个新的东西,map不用非得用map<char, int> 这样的声明。可以直接用一维int数组,把罗马数字对应成下标,这样可以加快运行速度。
class Solution {
public:
int romanToInt(string s) {
map<char, int> mp;
mp['I'] = 1, mp['V'] = 5, mp['X'] = 10, mp['L'] = 50;
mp['C'] = 100, mp['D'] = 500, mp['M'] = 1000;
int ans = 0;
for (int i = 0; i < s.size() - 1; i++) {
if (mp[s[i]] < mp[s[i + 1]]) {
ans -= mp[s[i]];
}
else {
ans += mp[s[i]];
}
}
ans += mp[s[s.size() - 1]];
return ans;
}
};
14 最长公共前缀
难度:简单
编写一个函数来查找字符串数组中的最长公共前缀。
如果不存在公共前缀,返回空字符串 “”。
示例 1:
输入: [“flower”,“flow”,“flight”]
输出: “fl”
示例 2:
输入: [“dog”,“racecar”,“car”]
输出: “”
解释: 输入不存在公共前缀。
说明:
所有输入只包含小写字母 a-z 。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/longest-common-prefix
题解:可以从第0个字符串按顺序取字母,都相同就加在答案字符串上,有不相同或字符串长度不够的,直接返回答案。注意的是,要判断字符串数组是否为空,不然访问strs[0]会运行错误。
class Solution {
public:
string longestCommonPrefix(vector<string>& strs) {
string ans = "";
for (int i = 0; strs.size() && i < strs[0].size(); i++) {
for (int j = 1; j < strs.size(); j++) {
if (strs[j].size() < i || strs[j][i] != strs[0][i]){
return ans;
}
}
ans += strs[0][i];
}
return ans;
}
};