正文
题目1.两数之和
题目链接
题目大意:
给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。
你可以假设每种输入只会对应一个答案。但是,数组中同一个元素不能使用两遍。
示例:
给定 nums = [2, 7, 11, 15], target = 9
因为 nums[0] + nums[1] = 2 + 7 = 9
所以返回 [0, 1]
题目解析:
先不考虑复杂度,直接两个for循环,对于每个数字nums[i],寻找target-nums[i]是否也在数组;
这样的时间复杂度为O(N^2),可以牺牲一些空间来换取更快的速度:比如说把已经出现过的数字用hash表直接存下来,这样下次用hash表直接循环该数字是否存在。
题目的要求还要输出数组下标,那么可以用hash表的值来存数组下标。
class Solution {
unordered_map mp;
public:
vector twoSum(vector& nums, int target) {
mp.clear();
vector ans;
for (int i = 0; i < nums.size(); ++i) {
if (mp[target - nums[i]]) {
ans.push_back(i);
ans.push_back(mp[target - nums[i]] - 1);
break;
}
mp[nums[i]] = i + 1;
}
return ans;
}
}leetcode;
2.整数反转
题目链接
题目大意:
给出一个 32 位的有符号整数,你需要将这个整数中每位上的数字进行反转。
示例 1:
输入: 123
输出: 321
示例 2:
输入: -123
输出: -321
示例 3:
输入: 120
输出: 21
注意:
假设我们的环境只能存储得下 32 位的有符号整数,则其数值范围为 [−231, 231 − 1]。请根据这个假设,如果反转后整数溢出那么就返回 0。
题目解析:
将负号单独拿出来考虑,只考虑整数的翻转。
因为最终结果可能超过int范围,那么可以用long long来处理。
class Solution {
public:
int reverse(int x) {
lld ret = 0, flag = x < 0 ? -1 : 1;
lld tmp = abs(x), sz = 1;
while (tmp) {
ret = tmp % 10 + ret * 10;
tmp /= 10;
}
lld intLeft = -(1LL << 31), intRight = (1LL << 31) - 1;
if (ret < intLeft || ret > intRight) {
ret = 0;
}
return (int)ret * flag;
}
}leetcode;
注意:
1在位移的时候,是按int来处理的,需要改成1LL;
3.字符串转换整数 (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) 。
题目解析:
按照题目的要求实现,拆分出来具体的过程。
1、还未进行数字转换的状态,hasConvert=false,此时可以允许空格跳过;
2、遇到+、-、数字之后,hasConvert=true,不允许空格跳过,遇到非数字符号结束转化;
3、符号和数字分开处理,超过int大小分别出来,可以用long long来暂存;
整体代码不复杂。
class Solution {
public:
int myAtoi(string str) {
long long ret = 0;
int flag = 0; // 前置符号, 0表示还没放过, 1 是正数,-1是负数
bool hasConvert = false;
for (int i = 0; i < str.length(); ++i) {
if (str[i] == '-' || str[i] == '+') {
if (flag) {
return flag * ret;
}
flag = str[i] == '-' ? -1 : 1;
hasConvert = true;
}
else if (str[i] >= '0' && str[i] <= '9') {
if (!flag) flag = 1;
hasConvert = true;
ret = ret * 10 + str[i] - '0';
if (flag * ret < -(1LL << 31)) {
return -(1LL << 31);
}
if (flag * ret > (1LL << 31) - 1) {
return (1LL << 31) - 1;
}
}
else if (!hasConvert && str[i] == ' ') {
continue;
}
else {
return flag * ret;
}
}
return flag * ret;
}
}lc;
注意:
题目很坑,+1 这种数据也没有说明;
+03这种,会认为是数字3,题目的严谨程度较差;
4.回文数
题目链接
题目大意:
判断一个整数是否是回文数。回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数。
示例 1:
输入: 121
输出: true
示例 2:
输入: -121
输出: false
解释: 从左向右读, 为 -121 。 从右向左读, 为 121- 。因此它不是一个回文数。
示例 3:
输入: 10
输出: false
解释: 从右向左读, 为 01 。因此它不是一个回文数。
题目解析:
将数字转成字符串,然后开始从左右两边开始遍历,如果遇到不一样的字符串则输出false;
如果没有发现不一样的字符,则左右边界递进,则最后输出true;
class Solution {
public:
bool isPalindrome(int x) {
char s[20];
sprintf(s, "%d", x);
int end = strlen(s) - 1, st = 0;
while (st < end) {
if (s[st] != s[end]) {
return false;;
}
++st;
--end;
}
return true;
}
}leetcode;
思考:
如果是要在字符串中找出最长的回文串呢?
5.最长公共前缀
题目链接
题目大意:
编写一个函数来查找字符串数组中的最长公共前缀。
如果不存在公共前缀,返回空字符串 ""。
示例 1:
输入: ["flower","flow","flight"]
输出: "fl"
示例 2:
输入: ["dog","racecar","car"]
输出: ""
解释: 输入不存在公共前缀。
说明: 所有输入只包含小写字母 a-z 。
题目解析:
前缀和,直接for循环遍历。
class Solution {
public:
string longestCommonPrefix(vector& strs) {
string ret;
while (true && strs.size()) {
for (int i = 0; i < strs.size(); ++i) {
if (strs[i].size() < ret.length() + 1) {
return ret;
}
if (i > 0 && strs[i][ret.length()] != strs[0][ret.length()]) {
return ret;
}
}
ret.push_back(strs[0][ret.length()]);
}
return ret;
}
}leetcode;
注意:
vector为空的情况。
总结
题目1,需要用hash来降低复杂度,unordered_map是很不错的hash选项;
题目2,反过来计算整数即可,边界问题是int范围,改一改就是很不错的题目;
题目3,这是一道题意比较复杂的模拟题,但是拆分出几点规则之后,代码还是比较清爽;
题目4,直接转成字符串,走字符串匹配;(思考题 O(N)回文串算法-Manacher)
题目5,直接遍历计算,算法的复杂度也没有太多优化空间;