1、两数之和:
给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。
你可以假设每种输入只会对应一个答案。但是,你不能重复利用这个数组中同样的元素。
示例:
给定 nums = [2, 7, 11, 15], target = 9
因为 nums[0] + nums[1] = 2 + 7 = 9
所以返回 [0, 1]
方法一:暴力
方法二:
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
vector<int> res;
if(nums.empty()){
return res;
}
int n=nums.size();
unordered_map<int,int> maps;
for(int i=0;i<n;i++){
maps[nums[i]]=i;
}
for(int i=0;i<n;i++){
auto item=maps.find(target-nums[i]);
if(item!=maps.end() && item->second!=i){
res.push_back(i);
res.push_back(item->second);
break;
}
}
return res;
}
};
方法三:
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
vector<int> res;
if(nums.empty()){
return res;
}
int n=nums.size();
unordered_map<int,int> maps;
for(int i=0;i<n;i++){
auto item=maps.find(target-nums[i]);
if(item!=maps.end() && item->second!=i){
res.push_back(item->second);
res.push_back(i);
break;
}
maps[nums[i]]=i;
}
return res;
}
};
2、两数相加
给出两个 非空 的链表用来表示两个非负的整数。其中,它们各自的位数是按照 逆序 的方式存储的,并且它们的每个节点只能存储 一位 数字。
如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的和。
您可以假设除了数字 0 之外,这两个数都不会以 0 开头。
示例:
输入:(2 -> 4 -> 3) + (5 -> 6 -> 4)
输出:7 -> 0 -> 8
原因:342 + 465 = 807
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
if(l1==NULL && l2==NULL) return NULL;
if(l1==NULL) return l2;
if(l2==NULL) return l1;
ListNode * newHead=new ListNode(-1);
ListNode * p=newHead;
int add=0;
while(l1!=NULL && l2!=NULL){
int sum=l1->val+l2->val+add;
add=sum/10;
ListNode * temp=new ListNode(sum%10);
p->next=temp;
p=p->next;
l1=l1->next;
l2=l2->next;
}
while(l1!=NULL){
int sum=l1->val+add;
add=sum/10;
ListNode * temp=new ListNode(sum%10);
p->next=temp;
p=p->next;
l1=l1->next;
}
while(l2!=NULL){
int sum=l2->val+add;
add=sum/10;
ListNode * temp=new ListNode(sum%10);
p->next=temp;
p=p->next;
l2=l2->next;
}
//重点别忘了最后的进位
if(add==0)
return newHead->next;
ListNode * temp=new ListNode(add);
p->next=temp;
return newHead->next;
}
};
缩减代码:
class Solution {
public:
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
if(l1==NULL && l2==NULL) return NULL;
if(l1==NULL) return l2;
if(l2==NULL) return l1;
ListNode * newHead=new ListNode(-1);
ListNode * p=newHead;
int add=0;
while(l1!=NULL || l2!=NULL){
int sum=l1!=NULL?l1->val:0;
sum+=l2!=NULL?l2->val:0;
sum+=add;
add=sum/10;
ListNode * temp=new ListNode(sum%10);
p->next=temp;
p=p->next;
if(l1!=NULL) l1=l1->next;
if(l2!=NULL) l2=l2->next;
}
if(add>0)
p->next=new ListNode(add);
return newHead->next;
}
};
3. 无重复字符的最长子串
class Solution {
public:
int lengthOfLongestSubstring(string s) {
if(s.empty()){
return 0;
}
int n=s.size();
if(n==1){
return 1;
}
vector<int> count(256,0);
int left=0,right=0;
int maxLen=-1;
while(right<n){
int index=s[right];
while(count[index]==1){
count[s[left]]--;
left++;
}
count[index]++;
right++;
maxLen=max(maxLen,right-left);
}
return maxLen;
}
};
方法二:
class Solution {
public:
int lengthOfLongestSubstring(string s) {
if(s.empty()){
return 0;
}
int n=s.size(),ans=0;
vector<int> index(128);//current index of char
for(int j=0,i=0;j<n;j++){
i=max(index[s[j]],i);
ans=max(ans,j-i+1);
index[s[j]]=j+1;
}
return ans;
}
};
5. 最长回文子串
给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为 1000。
示例 1:
输入: “babad”
输出: “bab”
注意: “aba” 也是一个有效答案。
示例 2:
输入: “cbbd”
输出: “bb”
方法一:暴力
方法二:
class Solution {
public:
string longestPalindrome(string s) {
if(s.empty()){
return "";
}
int n=s.size();
int start=0,maxLen=0;
for(int i=0;i<n;i++){
int len1=patter(s,i,i);
int len2=patter(s,i,i+1);
if(len1>maxLen && len1>len2){
start=i-len1/2;
maxLen=len1;
}
if(len2>maxLen && len2>len1){
start=i-len2/2+1;
maxLen=len2;
}
}
return s.substr(start,maxLen);
}
int patter(string s,int i,int j){
while(i>=0 && j<s.size() && s[i]==s[j]){
i--;
j++;
}
return j-i-1;
}
};
方法三:动态规划
class Solution {
public:
string longestPalindrome(string s) {
if(s.empty()){
return "";
}
int n=s.size();
vector<vector<bool> > dp(n,vector<bool>(n,false));
int start=0,maxLen=0;
for(int i=0;i<n;i++){
for(int j=i;j>=0;j--){
dp[j][i]=(s[i]==s[j] && (i-j<2 || dp[j+1][i-1]));
if(dp[j][i] && i-j+1>maxLen){
start=j;
maxLen=i-j+1;
}
}
}
return s.substr(start,maxLen);
}
};
6. Z 字形变换
将一个给定字符串根据给定的行数,以从上往下、从左到右进行 Z 字形排列。
比如输入字符串为 “LEETCODEISHIRING” 行数为 3 时,排列如下:
L C I R
E T O E S I I G
E D H N
之后,你的输出需要从左往右逐行读取,产生出一个新的字符串,比如:“LCIRETOESIIGEDHN”。
请你实现这个将字符串进行指定行数变换的函数:
string convert(string s, int numRows);
示例 1:
输入: s = “LEETCODEISHIRING”, numRows = 3
输出: “LCIRETOESIIGEDHN”
class Solution {
public:
string convert(string s, int numRows) {
if(s.empty() || numRows==1){
return s;
}
int len=numRows+numRows-2;
vector<string> res(numRows,"");
for(int i=0;i<s.size();i++){
int yu=i%len;
if(yu<numRows){
res[yu]+=s[i];
}else{
int index=numRows-(yu-numRows+2);
res[index]+=s[i];
}
}
string result;
for(int i=0;i<res.size();i++){
result+=res[i];
}
return result;
}
};
7. 整数反转
给出一个 32 位的有符号整数,你需要将这个整数中每位上的数字进行反转。
示例 1:
输入: 123
输出: 321
示例 2:
输入: -123
输出: -321
示例 3:
输入: 120
输出: 21
注意:
假设我们的环境只能存储得下 32 位的有符号整数,则其数值范围为 [−231, 231 − 1]。请根据这个假设,如果反转后整数溢出那么就返回 0。
class Solution {
public:
int reverse(int x) {
long res=0;
while(x!=0){
res=res*10+x%10;
x=x/10;
}
long left=pow(-2,31),right=pow(2,31)-1;
if(res<INT_MIN || res>INT_MAX){
return 0;
}
return res;
}
};
9. 回文数
class Solution {
public:
bool isPalindrome(int x) {
// 特殊情况:
// 如上所述,当 x < 0 时,x 不是回文数。
// 同样地,如果数字的最后一位是 0,为了使该数字为回文,
// 则其第一位数字也应该是 0
// 只有 0 满足这一属性
if(x < 0 || (x % 10 == 0 && x != 0)) {
return false;
}
long long res=0;
int y=x;
while(x>res){
res=res*10+x%10;
x=x/10;
}
// 当数字长度为奇数时,我们可以通过 revertedNumber/10 去除处于中位的数字。
// 例如,当输入为 12321 时,在 while 循环的末尾我们可以得到 x = 12,
//revertedNumber = 123,
// 由于处于中位的数字不影响回文(它总是与自己相等),所以我们可以简单地将其去除。
return x==res || x==res/10;
}
};
11. 盛最多水的容器

class Solution {
public:
int maxArea(vector<int>& height) {
if(height.empty()){
return 0;
}
int maxArea=-1;
int left=0,right=height.size()-1;
while(left<right){
maxArea=max(min(height[left],height[right])*(right-left),maxArea);
if(height[right]>height[left]){
left++;
}else{
right--;
}
}
return maxArea;
}
};
12. 整数转罗马数字


class Solution {
public:
string intToRoman(int num) {
int values[]={1000,900,500,400,100,90,50,40,10,9,5,4,1};
string reps[]={"M","CM","D","CD","C","XC","L","XL","X","IX","V","IV","I"};
string res;
for(int i=0;i<13;i++){
while(num>=values[i]){
num-=values[i];
res+=reps[i];
}
}
return res;
}
};
15. 三数之和
给定一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?找出所有满足条件且不重复的三元组。
注意:答案中不可以包含重复的三元组。
例如, 给定数组 nums = [-1, 0, 1, 2, -1, -4],
满足要求的三元组集合为:
[
[-1, 0, 1],
[-1, -1, 2]
]
class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums) {
vector<vector<int> > res;
if(nums.empty() || nums.size()<3){
return res;
}
sort(nums.begin(),nums.end());
for(int i=0;i<nums.size()-2;i++){
if(nums[i]>0){
break;
}
if(i>0 && nums[i]==nums[i-1]) continue;
int left=i+1,right=(int)nums.size()-1;
while(left<right){
if(nums[left]+nums[right]==0-nums[i]){
res.push_back({nums[i],nums[left],nums[right]});
while(left<right && nums[left] == nums[left+1]) left++;
while(left<right && nums[right]==nums[right-1]) right--;
left++;
right--;
}else if(nums[left]+nums[right]<0-nums[i]){
left++;
}else{
right--;
}
}
}
return res;
}
};
18. 四数之和

class Solution {
public:
vector<vector<int>> fourSum(vector<int>& nums, int target) {
vector<vector<int> > res;
if(nums.empty() || nums.size()<4){
return res;
}
sort(nums.begin(),nums.end());
for(int i=0;i<nums.size()-3;i++){
if(i>0 && nums[i]==nums[i-1]) continue;
for(int j=i+1;j<nums.size()-2;j++){
if(j>i+1 && nums[j]==nums[j-1]) continue;
int left=j+1,right=nums.size()-1;
while(left<right){
int sum=nums[i]+nums[j]+nums[left]+nums[right];
if(sum==target){
res.push_back({nums[i],nums[j],nums[left],nums[right]});
while(left<right && nums[left]==nums[left+1]) left++;
while(left<right && nums[right]==nums[right-1]) right--;
left++;
right--;
}else if(sum<target){
left++;
}else{
right--;
}
}
}
}
return res;
}
};
19. 删除链表的倒数第N个节点
注意边界问题

class Solution {
public:
ListNode* removeNthFromEnd(ListNode* head, int n) {
if(head==NULL){
return head;
}
ListNode * fast=head,* slow=head;
int k=1;
while(fast!=NULL){
if(k<=n+1){
fast=fast->next;
k++;
}else{
slow=slow->next;
fast=fast->next;
}
}
if(k<=n+1)
return head->next;
slow->next=slow->next->next;
return head;
}
};
22. 括号生成

class Solution {
public:
vector<string> generateParenthesis(int n) {
vector<string> res;
help(res,"",0,0,n);
return res;
}
void help(vector<string> &res,string cur,int open,int close,int max){
if(cur.size()==max*2){
res.push_back(cur);
return ;
}
if(open<max)
help(res,cur+"(",open+1,close,max);
if(close<open)
help(res,cur+")",open,close+1,max);
}
};
本文精选LeetCode上的经典算法题目,包括两数之和、两数相加、无重复字符的最长子串等,详细解析了每道题目的解题思路与代码实现,旨在帮助读者深入理解算法设计与优化。
458

被折叠的 条评论
为什么被折叠?



