这个系列将是Leetcode的刷题记录贴,按照题库顺序,每五题为一贴,主要目的做自己的记录、总结之用,但若有同学或同好看到此贴,并有所帮助,也算额外之喜,共勉!
给定一个整数数组 nums 和一个整数目标值 target ,请你在该数组中找出和为目标值 target 的那两个整数,并返回它们的数组下标。
示例:
输入:nums = [3,2,4], target = 6
输出:[1,2]
题解:
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
for(int i=0;i<nums.size();i++)
for(int j=i+1;j<nums.size();j++)
if(nums[i]+nums[j]==target) return {i,j};
return {};
}
思路:暴力做法,遍历两遍数组,时间复杂度O(n^2),空间复杂度O(1)
总结:
1.注意 vector 类型返回值的函数,若要返回空值写 return 语句时如下:
return {}
给定两个非空的链表,表示两个非负的整数。它们每位数字都是按照逆序的方式存储的,并且每个节点只能存储一位数字。请你将两个数相加,并以相同形式返回一个表示和的链表。这两个数都不会以 0 开头。
示例:
输入:L1 = [9,9,9,9,9,9,9], L2 = [9,9,9,9]
输出:[8,9,9,9,0,0,0,1]
题解:
class Solution {
public:
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
int carry=0,digit=0;
ListNode *head=nullptr,*tail=nullptr;
while(l1||l2){
int m=(l1)?l1->val:0;
int n=(l2)?l2->val:0;
digit=(m+n+carry)%10;
carry=(m+n+carry)/10;
if(!head) head=tail=new ListNode(digit);
else{
tail->next=new ListNode(digit);
tail=tail->next;
}
if(l1) l1=l1->next;
if(l2) l2=l2->next;
}
if(carry!=0){
tail->next=new ListNode(carry);
tail=tail->next;
}
return head;
}
};
思路:新建两个指针,同时遍历两个链表并加和计算,头指针指向第一位,尾指针随位数向后移动,每一位相加后再与上一位的进位相加,最后判断是否还有进位,有的话再附加一个节点,输出。时间复杂度为O(m+n),空间复杂度为O(1)
总结:
1.ListNode 的操作,ListNode 的定义如下所示:
struct ListNode {
int val;
ListNode *next;
ListNode() : val(0), next(nullptr) {}
ListNode(int x) : val(x), next(nullptr) {}
ListNode(int x, ListNode *next) : val(x), next(next) {}
};
2.可以使用 *ptr=new ListNode(int) 语句来新建一个链表节点,其值为 int,指针为 *ptr
3.声明一个指针后立刻进行初始化,*ptr=nullptr
4. A ? B : C 是一个条件运算符表达式,其值取决于 A 的计算结果。如果 A 为真,则 B 为整个表达式的值。如果 A 为假,则 C 为表达式的值
5.本题解的空间复杂度为 O(1) ,而非 O(m+n) ,考虑算法的空间复杂度时不计入返回值
给定一个字符串 s ,请你找出其中不含有重复字符的 最长子串 的长度。
示例:
输入: s = “abcabcbb”
输出: 3
题解:
class Solution {
public:
int lengthOfLongestSubstring(string s) {
unordered_map<char,int> findstr;
int count=0,res=0,i=0,start=0;
for(int i=0;i<s.size();i++){
if(s.size()==0) break;
if(findstr.find(s[i])==findstr.end()){
findstr[s[i]]=i;
count++;
res=max(res,count);
}
else{
if(findstr[s[i]]>start-1){
start=findstr[s[i]];
count=i-start;
}
else{
count++;
res=max(res,count);
}
findstr[s[i]]=i;
}
}
return res;
}
};
思路:使用hash_map存储字符串中每一个字符及其位置,遍历字符串,若是新的字符,将其存入hash_map, 对count加1,否则判断是否需要更新字串的起点,例如对于字符串’abba’,由于b第二次出现时,子串的起点为0,我们将字串的起点更新为第二个b的位置,将count的值更新为第二个b和第一个b之间的字符个数,紧接着a第二次出现,这时a并不会与第一个a重复,不需要再次更新起点,而是对count进行+1操作。
总结:
1.hash_map的定义与基本的函数操作
2.对map的某个key进行注意赋值时使用的是 [] 而非 ()
给定两个大小分别为 m 和 n 的正序(从小到大)数组 nums1 和 nums2。请你找出并返回这两个正序数组的 中位数 。
示例:
输入:nums1 = [1,2], nums2 = [3,4]
输出:2.50000
题解:
class Solution {
public:
double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
int m=nums1.size(),n=nums2.size();
for(int i=0;i<n;i++){
nums1.push_back(nums2[i]);
}
sort(nums1.begin(),nums1.end());
if((m+n)%2==0) return ((nums1[(m+n)/2]+nums1[(m+n)/2-1])/2.0);
else return nums1[(m+n-1)/2];
}
};
思路:先将两个数组合并,使用sort进行排序,再根据合并后的数组的奇偶性输出中间数字。
总结:
1.当数组为偶数时,要对两个数字求和再相除,最终得到一个包含小数的数字,这时使用 / 符号时,除数应写为2.0而不是2
给你一个字符串 s,找到 s 中最长的回文子串。(回文子串,正反顺序读取相同的字符串)
示例:
输入:s = “babad”
输出:“bab”
题解:
class Solution {
public:
string longestPalindrome(string s) {
int slen=s.size();
int subbegin=0,maxsublen=1;
if(slen<2) return s;
//记录是否是回文子串的数组
bool ifPalindrome[slen][slen];
for(int i=0;i<slen;i++)
ifPalindrome[i][i]=true;
//从长度为2的字串开始枚举
for(int sublen=2;sublen<=slen;sublen++){
for(int l=0;l<slen;l++){
int r=l+sublen-1;
//判断右边界越界
if(r>=slen) break;
if(s[l]!=s[r]) ifPalindrome[l][r]=false;
//小于3长度的子串边界相同即为回文子串
else if(r-l<3) ifPalindrome[l][r]=true;
//大于3则取决于边界内的子串
else ifPalindrome[l][r]=ifPalindrome[l+1][r-1];
//判断是否需要更新最长子串
if(ifPalindrome[l][r]==true&&sublen>maxsublen){
maxsublen=sublen;
subbegin=l;
}
}
}
return s.substr(subbegin,maxsublen);
}
};
思路:动态规划思想,对于每一个长度为一的子串其一定是回文子串,对一个长度为 n 的子串 s[i]~s[i+n-1],首先判断其边界是否相等,如果相等那么其回文性取决于子串 s[i+1]~s[i+n-2],以此类推。在这个过程中,每得到一个回文子串,都与当前记录的最长子串长度 maxsublen 比较,并记录此子串的起始位置 subbegin。
总结:
1.动态规划的思想,笔者目前的理解更像是一种“递归”,将大问题化解为一个个小问题,找到其中的基本元素。笔者在这里第一次接触到动态规划算法,书本上讲到动态规划动辄便是状态转移方程之类,看起来非常高大上,实则真正用起来关键是要想明白如何从要解决的问题经过同一个“递归”的过程变成小的基本问题。在此基础上,要时刻注意边界条件,例如本题中首先想到的便是,使用左边界和长度相加得到的右边界不能超过原串的长度
2.string 的函数 string.substr(x,y),其中 x 标识子串的起始位置, y 表示子串的长度
题目来源:力扣(LeetCode)
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
博客著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。