(1)两数之和:(简单)
实现思路:我们要求两个数的和是等于对应的target的,哪么我们就可以先设立一个哈希表,查找哈希表中个是否存在对应的数(target-nums[i]),如果存在的话,就返回二者对应的下标,不存在就继续寻找知道找到为止。
具体代码如下:
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
unordered_map<int,int> heap;
for(int i=0;i<nums.size();i++)
{
int k=target-nums[i];
if(heap.count(k)) return {heap[k],i};
else
{
heap[nums[i]]=i;
}
}
return {};
}
};
(2)两数相加(中等)
实现思路:因为是针对链表进行的算法,所以我们先创建一个链表来存储二者相加之后的值,这里我们创建一个哨兵位(dummy)来防止头结点不存在的情况,同时创建一个对应的尾结点(cur),之后我们创建一个变量为t来存储对应每一位相加的值,对应新链表存储的就是t%10之后的结果,同时对t进行更新(t/10)。
具体代码实现如下:
class Solution {
public:
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
auto dummy =new ListNode(-1),cur=dummy;
int t=0;
while(l1 || l2 || t)
{
if(l1) t+=l1->val,l1=l1->next;
if(l2) t+=l2->val,l2=l2->next;
cur->next=new ListNode(t%10);
cur=cur->next;
t/=10;
}
return dummy->next;
}
};
(3)无重复字符的最长子串(中等)
实现思路:这里使用的是双指针的思想,i表示在前面的指针,j表示在后面的指针,有j到i这一段区间就是我们所要找的最长无重复子串,我们利用哈希表来进行对无重复特性的维护,这样就解决1了这道问题。
具体代码如下:
class Solution {
public:
int lengthOfLongestSubstring(string s) {
unordered_map<char,int> count;
int res=0;
for(int i=0,j=0;i<s.size();i++)
{
count[s[i]]++;
while(count[s[i]]>1) //表示此时就是有重复了,count()函数的意思就是当前数字存在的话就返回1,不存在就返回0
{
count[s[j++]]--;//此时j就往后走一位,同时对应的在哈希表中的次数也减少1,在s[i]次数没有减少为1前,循环不会结束
}
res=max(res,i-j+1);
}
return res;
}
};
(4)寻找两个正序数组的中位数(困难)
实现思路:我们的思路是这样的,首先我们写一个函数可以求出两个数组从小到大合并之后的第个值是什么,哪么我们就可以使k等于(length1+length2)/2来等于数组合并后的中位数
具体代码实现如下:
class Solution {
public:
double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
int total=nums1.size()+nums2.size();
if(total%2==0)//如果是一个偶数的话
{
int left=find(nums1,0,nums2,0,total/2);
int right=find(nums1,0,nums2,0,total/2+1);//因为是偶数,所以中位数就要是中间两个数和平均数,也就是(left+right)/2
return (left+right)/2.0;
}
else//否则的话就就是计数
{
return find(nums1,0,nums2,0,total/2+1);
}
}
int find(vector<int>&nums1,int i,vector<int>&nums2,int j,int k)//i,j对应的就是开始查找的位置
{
if(nums1.size()-i > nums2.size()-j) return find(nums2,j,nums1,i,k);//如果此时nums1比较长的话,我们就对nums2进行查找
if(k==1) {//如果此时就只有一个数的话,哪么我们只需找到两个数组前两个数的最小值即可
if(nums1.size()==i)//如果此时nums1.size()==i,就说明第一个数组是空的,哪么我们就返回第二个数组的前面的数
{
return nums2[j];
}
else return min(nums1[i],nums2[j]);
}
if(nums1.size()==i)
{
return nums2[j+k-1];
}
//上述都是对于边界的处理
int si=min((int)nums1.size(),i+k/2);//参照我们的图,可以假设这就是A数组
int sj=k-k/2+j;//参照我们的图,对应的就是B数组,因为一定可以删除k/2个数,所以代码就如左边操作,注:si与sj对应的是我们所要求的数组第k/2个元素的下一个元素坐标。
if(nums1[si-1]>nums2[sj-1])//对应的就是图中第二种情况A[k/2]<B[k/2]
{
return find(nums1,i,nums2,sj,k-(sj-j));//此时对应删除的就是B中蓝色的部分,也就是nums2的sj-1下标之间的部分,所以我们此时在新数组中寻找的对应的坐标就是k-(sj-j)
}
else
{
return find(nums1,si,nums2,j,k-(si-i));
}
}
};
(5)最长回文子串(中等)
实现思路:
首先如果回文串是奇数的话,此时就只需要中间字符左右两边相同即可,如果是偶数回文串的话,只需要让左右两边两两相同即可,具体思路如下图:
class Solution {
public:
string longestPalindrome(string s) {
string res;//表示的是最长回文串的长度
for(int i=0;i<s.size();i++)
{
int l=i-1,r=i+1;
while(l>=0 && r<s.size() && s[l]==s[r]) l--,r++;
if(res.size()<r-l-1) res=s.substr(l+1,r-l-1);
l=i,r=i+1;
while(l>=0 && r<s.size() && s[l]==s[r]) l--,r++;
if(res.size()<r-l-1) res=s.substr(l+1,r-l-1);
}
return res;
}
};