1. 两数之和
给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。
你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。
你可以按任意顺序返回答案。
示例
输入:nums = [2,7,11,15], target = 9
输出:[0,1]
解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1] 。
思路:
采用暴力枚举法时间复杂度为O(n^2),采用哈希表时间复杂度为O(n)。创建的哈希表,key为元素值,value为元素下标。在数组中寻找和为target的两个数,遍历数组元素,当前元素为nums[i],查找数值中是否有存在值为target-nums[i]的元素存在。若存在,则返回哈希表中该元素对应value即下标即当前元素下标i。若不存在,则存入哈希表中。
题解:
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
unordered_map<int, int> hashmap;
for(int i = 0; i < nums.size(); i++){
int temp = target - nums[i];
//查找以temp为key的值
if(hashmap.find(temp) != hashmap.end()){
//找到则返回temp下标和该值下标
return {hashmap[temp], i};
}
//未找到则写入哈希表并记录该值下标
hashmap[nums[i]] = i;
}
return {};
}
};
3. 无重复字符的最长子串
给定一个字符串 s ,请你找出其中不含有重复字符的 最长子串 的长度。
示例 1:
输入: s = "abcabcbb"
输出: 3
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。
示例 2:
输入: s = "bbbbb"
输出: 1
解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。
示例 3:
输入: s = "pwwkew"
输出: 3
解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。
请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。
示例 4:
输入: s = ""
输出: 0
思路:
left、right分别记录无重复元素子串的最左最右元素。用哈希表记录无重复子串中的元素。right循环右移,每次判断right指向的元素是否存在哈希表中,即是否是重复元素。若是重复元素,则循环右移left并删除子串中最左元素,直到子串中无重复元素为止。若不是重复元素,则将该元素插入哈希表中。
代码:
class Solution {
public:
int lengthOfLongestSubstring(string s) {
//哈希表记录子串元素
unordered_set<char> ooc;
int left = 0, right = 0;//记录子串位置
int maxlen = 0;
if(s.size() == 0 )
return maxlen;
for(int right = 0; right < s.size(); right++){
//查找子串中的重复元素逐一删除
while(ooc.find(s[right]) != ooc.end()){
ooc.erase(s[left]);
left++;
}
//未重复则插入哈希表
ooc.insert(s[right]);
maxlen = max(maxlen, right - left + 1);
}
return maxlen;
}
};
4. 寻找两个正序数组的中位数
给定两个大小分别为 m 和 n 的正序(从小到大)数组 nums1 和 nums2。请你找出并返回这两个正序数组的 中位数 。
示例 1:
输入:nums1 = [1,3], nums2 = [2]
输出:2.00000
解释:合并数组 = [1,2,3] ,中位数 2
示例 2:
输入:nums1 = [1,2], nums2 = [3,4]
输出:2.50000
解释:合并数组 = [1,2,3,4] ,中位数 (2 + 3) / 2 = 2.5
示例 3:
输入:nums1 = [0,0], nums2 = [0,0]
输出:0.00000
示例 4:
输入:nums1 = [], nums2 = [1]
输出:1.00000
示例 5:
输入:nums1 = [2], nums2 = []
输出:2.00000
思路:
若nums1和nums2长度之和为偶数,则中位数为第len/2个数和第len/2+1个数之和的平均值,若为奇数,则中位数为第len/2+1个数。
代码:
class Solution {
public:
double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
int len1 = nums1.size();
int len2 = nums2.size();
int len = len1 + len2;
int left = 0;
int right = 0;
for(int i = 0, j = 0, k = 0; i <= len/2; i++){
left = right;
if(j < len1 && (k >= len2 || nums1[j] < nums2[k]) ){
right = nums1[j++];
}else{
right = nums2[k++];
}
}
if(len % 2 == 0){
return (left + right)/2.0;
}else{
return right;
}
}
};
5. 最长回文子串
给你一个字符串 s,找到 s 中最长的回文子串。
示例 1:
输入:s = "babad"
输出:"bab"
解释:"aba" 同样是符合题意的答案。
示例 2:
输入:s = "cbbd"
输出:"bb"
示例 3:
输入:s = "a"
输出:"a"
示例 4:
输入:s = "ac"
输出:"a"
思路:
长度为1的子串都是回文,长度为2的子串若元素相等是回文。长度为3即right-left<3时左右元素相等即是回文。其他情况,判断最左元素s[left]与最右元素s[right]是否相等,相等且s[left-1,right+1]的子串是回文则s[left, right]也是回文。
代码:
class Solution {
public:
string longestPalindrome(string s) {
if(s.length() == 1 ||(s.length() == 2 && s[0] == s[1])){
return s;
}
//子串左右位置
int left = 0, right = 0;
int len = s.length();
//记录最长子串长度,初始为1
int maxLen = 1;
//记录最长子串开始位置
int maxStrBegin = 0;
//dp[left][right]值为1表示 以left开头 right结尾的子串是回文子串
vector<vector <int> > dp(len, vector<int> (len));
//初始化,单个元素都为长度为1的回文子串
for(int i = 0; i < len; i++){
dp[i][i] = 1;
}
//枚举子串长度
for(int i = 2; i <= len; i++){
//枚举子串起始位置
for(int left = 0; left < len; left++){
int right = left + i -1;
if(right >= len){
break;
}
//若左边元素不等于右边元素则不是回文
if(s[left] != s[right]){
dp[left][right] = 0;
}else{
//长度为3的情况 左右相等是回文
if(right - left < 3){
dp[left][right] = 1;
}else{
dp[left][right] = dp[left + 1][right - 1];
}
}
//是回文且长度大于当前记录的最大值,则更新
if(dp[left][right] == 1 && right - left + 1 > maxLen){
maxLen = right - left + 1;
maxStrBegin = left;
}
}
}
return s.substr(maxStrBegin, maxLen);
}
};
6. Z字形变换
将一个给定字符串 s 根据给定的行数 numRows ,以从上往下、从左到右进行 Z 字形排列。
比如输入字符串为 “PAYPALISHIRING” 行数为 3 时,排列如下:
P A H N
A P L S I I G
Y I R
之后,你的输出需要从左往右逐行读取,产生出一个新的字符串,比如:“PAHNAPLSIIGYIR”。
请你实现这个将字符串进行指定行数变换的函数:
string convert(string s, int numRows);
示例 1:
输入:s = "PAYPALISHIRING", numRows = 3
输出:"PAHNAPLSIIGYIR"
示例 2:
输入:s = "PAYPALISHIRING", numRows = 4
输出:"PINALSIGYAHRPI"
解释:
P I N
A L S I G
Y A H R
P I
示例 3:
输入:s = "A", numRows = 1
输出:"A"
思路:
按Z字形填充,可理解为从第0行开始向下填充至第numRows - 1行为止,然后斜向上填充至第0行。所以在第0行和第numRows - 1行时需改变填充方向。向下填充时行数依次加1,向上填充时行数依次减1。由此将每个元素从左到右填入相应的行,各行拼接得到的字符串即为转换后的字符串。
代码:
class Solution {
public:
string convert(string s, int numRows) {
if(numRows == 1){
return s;
}
vector<string> rows(min(numRows, (int)s.size()));
int curRow = 0;
//填充方向
bool goingDown = false;
for(char c : s){
rows[curRow] += c;
//若在第一行或最后一行需更换方向
//第一行goingDown为true,最后一行goingDown为false
if(curRow == 0 || curRow == numRows - 1){
goingDown = !goingDown;
}
//在第一行row加1 最后一行row-1
curRow += goingDown ? 1 : -1;
}
string ans;
for(string row : rows){
ans += row;
}
return ans;
}
};
7. 整数反转
给你一个 32 位的有符号整数 x ,返回将 x 中的数字部分反转后的结果。
如果反转后整数超过 32 位的有符号整数的范围 [−231, 231 − 1] ,就返回 0。
假设环境不允许存储 64 位整数(有符号或无符号)。
示例 1:
输入:x = 123
输出:321
示例 2:
输入:x = -123
输出:-321
示例 3:
输入:x = 120
输出:21
示例 4:
输入:x = 0
输出:0
代码:
class Solution {
public:
int reverse(int x) {
int num = 0;
while( x != 0){
if (num < INT_MIN/10 || num > INT_MAX/10) {
return 0;
}
int digit = x % 10;
x = x/10;
num = num*10 + digit;
}
return num;
}
};