1. 两数之和
给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。
你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。
你可以按任意顺序返回答案。
输入:nums = [2,7,11,15], target = 9
输出:[0,1] 解释:因为 nums[0] + nums[1] == 9,返回 [0, 1]。
解决方法:
vector<int> twoSum(vector<int>& nums, int target) {
int n = nums.size();
unordered_map<int, int> mp;
mp[nums[0]] = -1;
for(int i=1;i<n;i++){
if(mp[target-nums[i]]==false){
mp[nums[i]] = i;
}else{
if(mp[target-nums[i]]==-1){
return {0, i};
}
return {mp[target-nums[i]],i};
}
}
return {};
}
2. 两数相加
给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。
请你将两个数相加,并以相同形式返回一个表示和的链表。
你可以假设除了数字 0 之外,这两个数都不会以 0 开头。
输入:l1 = [2,4,3], l2 = [5,6,4] 输出:[7,0,8] 解释:342 + 465 = 807.
解决方法:
顺序的比较容易,加一个flag判断进位,不断生成一条链表,最后也要判断flag
class Solution {
public:
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
ListNode* p = l1;
ListNode* q = l2;
ListNode* t = new ListNode();
ListNode* r = t;
int flag = 0;
while(p && q){
int x = (p->val + q->val + flag) % 10;
flag = (p->val + q->val + flag) / 10;
r->next = new ListNode(x);
r = r -> next;
p = p->next;
q = q->next;
}
while(p){
int x = (p->val + flag) % 10;
flag = (p->val + flag) / 10;
r->next = new ListNode(x);
r = r -> next;
p = p->next;
}
while(q){
int x = (q->val + flag) % 10;
flag = (q->val + flag) / 10;
r->next = new ListNode(x);
r = r -> next;
q = q->next;
}
if(flag){
r->next = new ListNode(1);
}
return t->next;
}
};
3. 无重复字符的最长子串
给定一个字符串 s ,请你找出其中不含有重复字符的 最长子串 的长度。
输入: s = “abcabcbb” 输出: 3 解释: 因为无重复字符的最长子串是 “abc”,所以其长度为 3。
输入: s = “bbbbb” 输出: 1 解释: 因为无重复字符的最长子串是 “b”,所以其长度为 1。
解题1:
滑动窗口,使用一个unordered_map来作为滑动窗口,每次无重复fast前进,重复了slow往前走到重复的位置,再+1
class Solution {
public:
int lengthOfLongestSubstring(string s) {
int n = s.size();
int slow = 0, fast = 0;
int res = 0;
unordered_map<char,bool> mp;
for(fast=0;fast<n;fast++){
if(!mp[s[fast]]){
mp[s[fast]] = true;
res = max(res, fast-slow+1);
}else{
while(s[slow]!=s[fast]){
mp[s[slow]] =false;
slow++;
}
slow++;
}
}
return res;
}
};
5. 最长回文子串
给你一个字符串 s,找到 s 中最长的回文子串。
如果字符串的反序与原始字符串相同,则该字符串称为回文字符串。
示例 1:
输入:s = “babad” 输出:“bab”
解释:“aba” 同样是符合题意的答案。
示例 2:
输入:s = “cbbd” 输出:“bb”
1 <= s.length <= 1000
s 仅由数字和英文字母组成
解题1:
双指针,每个字符的左右间隙都看作一个回文的中心点,每个字符也是,就有2倍n大小的回文中心点,从中心点往两边扩散,对比是否相同,记录最长的
string longestPalindrome(string s) {
int n = s.size();
int res = 1;
int begin = 0;
for(int i=0;i<n*2;i++){
int a = i/2;
int b = i/2 + i%2;
while(a>=0 && b<n && s[a]==s[b]){
if(b-a+1>res){
begin = a;
res = b-a+1;
}
a--;
b++;
}
}
return s.substr(begin, res);
}
解题2:
动态规划,dp[i][j]表示字符串i到j是否是回文串,以L从2开始往上计算
string longestPalindrome(string s){
int n = s.size();
vector<vector<int>> dp(n, vector<int>(n,false));
for(int i=0;i<n;i++)dp[i][i] = true;
int begin = 0;
int res = 1;
for(int L=2;L<=n;L++){
for(int i=0;i<n;i++){
int j = i + L - 1;
if(j>=n)break;
if(s[i]!=s[j])dp[i][j] = false;
else{
if(j-i+1<3)dp[i][j] = true;
else dp[i][j] = dp[i+1][j-1];
}
if(dp[i][j] && (j-i+1)>res){
begin = i;
res = j-i+1;
}
}
}
return s.substr(begin, res);
}
6. N 字形变换
将一个给定字符串 s 根据给定的行数 numRows ,以从上往下、从左到右进行 Z 字形排列。
比如输入字符串为 “PAYPALISHIRING” 行数为 3 时,排列如下:
之后,你的输出需要从左往右逐行读取,产生出一个新的字符串,比如:“PAHNAPLSIIGYIR”。
解题:
看成线性的,设置一个flag和index,每次index=0或者index=numRows-1时,flag取反,加到index,这样index就在一个范围里折返,使用一个vector记录每行的字符,最后读取
class Solution {
public:
string convert(string s, int numRows) {
int n = s.size();
if(numRows==1)return s;
vector<string> ans(numRows);
int flag = 1;
int index = 0;
for(int i=0;i<n;i++){
ans[index].push_back(s[i]);
index += flag;
if(index==numRows-1 || index==0)flag = -flag;
}
string res;
for(auto str : ans)res+=str;
return res;
}
};
19.删除链表的倒数第 N 个结点
给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。
输入:head = [1,2,3,4,5], n = 2 输出:[1,2,3,5]
解题思路:
双指针一遍遍历,或者遍历两遍第一次查数量第二次计算,或者使用一个栈存储
class Solution {
public:
ListNode* removeNthFromEnd(ListNode* head, int n) {
ListNode* h = new ListNode();
h->next = head;
ListNode* p = head;
for(int i=0;i<n;i++)p = p->next;
ListNode* q = h;
while(p){
p = p->next;
q = q->next;
}
p = q->next;
q->next = q->next->next;
delete(p);
return h->next;
}
};
20.有效的括号
给定一个只包括 ‘(’,‘)’,‘{’,‘}’,‘[’,‘]’ 的字符串 s ,判断字符串是否有效。
有效字符串需满足:
左括号必须用相同类型的右括号闭合。
左括号必须以正确的顺序闭合。
每个右括号都有一个对应的相同类型的左括号。
示例 1:输入:s = “()” 输出:true
示例 2:输入:s = “()[]{}” 输出:true
示例 3:输入:s = “(]” 输出:false
解题思路:
使用一个栈来存储,遍历字符串,当是左边的3种括号时入栈,当是右边3种括号需要判断,栈为空或者栈顶不为对应的左括号返回false,都正确就出栈一个,最后判断栈是否为空
class Solution {
public:
ListNode* removeNthFromEnd(ListNode* head, int n) {
ListNode* h = new ListNode();
h->next = head;
ListNode* p = head;
for(int i=0;i<n;i++)p = p->next;
ListNode* q = h;
while(p){
p = p->next;
q = q->next;
}
p = q->next;
q->next = q->next->next;
delete(p);
return h->next;
}
};