day2
最长回文子串
- 暴力:双指针,一个left确定“回文子串”的最左侧,right确定最右侧,验证该“回文子串”是否达标
- 滑动窗口:用一个字符串记录需要判断的子串
- 确定中间某个子串(按照子串字符个数的奇偶可以分为两种情况)是回文序列,只要两侧新增的内容依然是对称的即可(与第一条的区别在,第一条是遍历是确定子串的最左侧,本条是确定子串的中间位置)
一开始直接用一个flag来记录最长子串的字符数,然后发现在比较长度时,会出现二义性:right-left+1是当前子串的长度,而flag相当于是
pair<int, int> findHuiwen(const string& s, int left, int right){
while(left>=0 && right<s.size() && s[left]==s[right]){
left--;
right++;
}
return {left+1, right-1};
}
string longestPalindrome(string s) {
int len = s.size();
if(len<2) return s;
int flag = 0;
// int left=0, right=0;
string ans{""};
for(int i=0; i<len; ++i){
auto [L1, R1] = findHuiwen(s, i, i);
auto [L2, R2] = findHuiwen(s, i, i+1);
if(R1-L1+1 > flag) {
flag = R1-L1+1;
// right = R1;
// left = L1;
ans.assign(s, L1, flag); // assign的第三个参数是要copy的字符个数
}
if(R2-L2+1 > flag) {
flag = R2-L2+1;
// right = R2;
// left = L2;
ans.assign(s, L2, flag);
}
}
return ans;
}
看官方题解发现还能动态规划:首先是分析每一子串的状态,按照是否构成回文分成“是”与“否”;而对于回文序列,是构成对称的子串,也就是left和right对应的字符相同。跟上述第三条解法角度类似。
爬楼梯
- 斐波那契数列
我先是用递归写的,然后当n=44后,超时;所以改成递推了(还不是很熟练申请动态数组)
int climbStairs(int n) {
// if(n==1 || n==0) return 1;
// return climbStairs(n-1) + climbStairs(n-2);
std::vector<int> dp{0};
dp.push_back(1);
dp.push_back(2);
for(int i=3; i<=n; ++i){
dp.push_back(dp[i-1]+dp[i-2]);
}
return dp[n];
}
寻找两个正序数组的中位数
虽然题标出来的难度是困难,但确实直接遍历就能过,虽然时间复杂度是log(m+n)吧
double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
vector<int> res{};
int len1 = nums1.size();
int len2 = nums2.size();
int p1=0, p2=0;
while(p1<len1 && p2<len2){
if(nums1[p1] > nums2[p2]){
res.push_back(nums2[p2]);
p2++;
}else if(nums1[p1] < nums2[p2]){
res.push_back(nums1[p1]);
p1++;
}else {
res.push_back(nums1[p1]);
res.push_back(nums1[p1]);
p1++;
p2++;
}
}
while(p1<len1){res.push_back(nums1[p1]); p1++;}
while(p2<len2){res.push_back(nums2[p2]); p2++;}
float mid = res.size()%2==0 ? (float)(res[(res.size()/2)]+res[(res.size()/2-1)]) / 2 : res[(res.size()/2)];
return mid;
}