文章目录
- 复习——寻找特定中位数
- 新作——最长回文子串
- 个人思路分析
- 实现代码
- 参考学习
- 和上述思路相同,枚举中心点
- 字符串哈希+二分
- 新作——Z 字形变换
- 个人做法
- 思路分析
- 实现代码
- 参考解法
- 分析总结
复习——寻找特定中位数
- 第一次的链接:寻找中位数
- 本来以为已经会做了,第二遍写还是遇到了很多问题,没写出来,有很多参数不是很懂。重新做了一遍,在重新思考,现在懂了。
- k是寻找第几个数字,加上初始坐标应该是 i+k-1
- 当nums1.size() == i,表示对于nums1找个数组而言,已经遍历到头了,所以直接返回nums2即可
- 当k=1,两个数组都没有遍历完,表示在两个有序数组中寻找第一小的数字,不就是比较一下头部吗?
double findMedianSortedArray(vector<int> nums1,vector<int> nums2){int tot = nums1.size() + nums2.size();if(tot % 2 == 0){int left = find(nums1,0,nums2,0,tot / 2 );int right = find(nums1,0,nums2,0,tot / 2 + 1);return (left + right) / 2.0;}else{return find(nums1,0,nums2,0,tot / 2 + 1);}}int find(vector<int> nums1,int i,vector<int> nums2,int j,int k){// 保证第一个数组短,第二个数组长if((nums1.size() - i) > (nums2.size() - j)) return find(nums2,j,nums1,i,k);// 找第一小的元素,有两个有序列表,就是选择开头元素最小的那个元素即可// 第一个列表已经遍历完毕了,然后就剩下第二个列表,也是求第一个元素,所以就直接返回if (k == 1){if(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),sj = j + k - k / 2;if(nums1[si - 1] > nums2[sj - 1]){return find(nums1,i,nums2,sj,k - (j - sj));}else{return find(nums1,si,nums2,j,k - (i - si));}}
新作——最长回文子串
- 嘿嘿,头一次,中等题没做过,二十分分钟写出来,调整出来了。
个人思路分析
- 双指针,但是有两种模式:
- 针对奇数个字符的回文字符串
- 针对偶数个字符的回文字符串
- 还有一个特征
- 长的回文字符串是由短的回文字符串,所以如果不行,就不会存在更长的回文,直接跳转到下一个即可
实现代码
string longestPalindrome(string s) {int mid = 0,l,r;int res = 0,lRes = 0,RRes = 0;for(;mid < s.size();mid ++){// 奇数的模式l = mid,r= mid;while(l >= 0 && r < s.size()){if(s[l] == s[r]) {if(res <= r- l){lRes = l;RRes = r;res = r - l;}l --;r ++;}elsebreak;}// 偶数模式l = mid,r = mid + 1;while(l >= 0 && r < s.size()){if (s[l] == s[r]){if(res < r- l){lRes = l;RRes = r;res = r - l;}l --;r ++;}elsebreak;}}return s.substr(lRes,RRes - lRes);}
参考学习
和上述思路相同,枚举中心点
- 这里代码写的真简洁,可以好好学习一下
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;}
字符串哈希+二分
- 时间不够了,这里贴一下人家的代码和思路吧,还有论文要写,不能花太多时间。
#include<iostream>
#include<algorithm>
#include<cstring>
#include<string>
using namespace std;
typedef unsigned long long ULL;
const int N = 2e6 + 10 , base = 131;
ULL hr[N] , hl[N] , p[N];
char str[N];
ULL get(ULL h[] , int l , int r)
{return h[r] - h[l - 1] * p[r + 1 - l];
}
int main()
{int T = 1;while(cin >> str + 1 , strcmp(str + 1 , "END")){int n = strlen(str + 1), res = 0;for(int i = 2 * n ; i >= 0 ; i -= 2){str[i] = str[i / 2];str[i - 1] = 'z' + 1;}n *= 2; p[0] = 1;for(int i = 1 , j = n; i <= n ; i ++ , j -- ){p[i] = p[i - 1] * base;hl[i] = hl[i - 1] * base + str[i];hr[i] = hr[i - 1] * base + str[j];}for(int i = 1 ; i <= n ; i ++ ){int l = 0 , r = min(n - i , i - 1);while(l < r){int mid = l + r + 1 >> 1;if(get(hl, i - mid, i - 1) == get(hr, n + 1 - (i + mid), n + 1 - (i + 1)))l = mid;else r = mid - 1;}if(str[i - l] <= 'z')res = max(res , l + 1);else res = max(res , l);}printf("Case %d: %d\n",T ++ , res);}return 0;
}
作者:tom233
链接:https://www.acwing.com/solution/content/33154/
来源:AcWing
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
新作——Z 字形变换
个人做法
思路分析
- 绘制一个二维矩阵,然后找规律,按照规律放到二维矩阵里面,然后在输出对应的矩阵。
- 注意点,以下有一些小细节可以帮助你提高代码的可读性
- 矩阵的坐标从1开始到边界结束,不要从零开始计算
实现代码
string convert(string s, int numRows) {int row = numRows ,col = s.size() / (numRows * 2 -2) * (numRows - 1);if (s.size() % (numRows * 2 -2) != 0)col ++;char m[row][col];int sIdx = 0;string res;for (int i = 0; i < col; ++i) {for (int j = 0; j < row; ++j) {if (sIdx == s.size()) break;// 竖线模式,顺次往下填if (i == 0 || i % (numRows - 1) == 0){m[j][i] = s[sIdx];res += s[sIdx];sIdx ++;}// 斜线模式,一次往上,主要是判定斜线是都会有对应的元素else{int iR = i % (numRows - 1), jR = (row - j - 1 )% (numRows - 1);if (j != 0 && iR == jR){m[j][i] = s[sIdx];res += s[sIdx];sIdx ++;}elsem[j][i] = ' ';}}}for (int i = 0; i < row; ++i) {for (int j = 0; j < col; ++j) {if (m[i][j] != ' ')res += m[i][j];}}return res;
}
- 这个代码还是有问题,因为是在原来的逻辑上缝缝补补,还有很多漏洞
综合上述观察到的问题,重新进行编程,代码如下
- 虽然很不想承认,但是确实中间那个斜杠的关系表达式,写了半天,没有调整出来,太丢人了,后来补了一个if表达式,始终没有找到能够用一个式子表达的情况!
string convert(string s, int numRows) {if(numRows == 1 || s.size() == 1) return s;int row = numRows ,col = s.size() / (numRows * 2 -2) * (numRows - 1);if (s.size() % (numRows * 2 -2) != 0)col ++;char m[row + 1][col + 1];int sIdx = 0;string res;for (int i = 1; i <= col; ++i) {for (int j = 1; j <= row; ++j) {if (sIdx == s.size()) break;// 竖线模式,顺次往下填if ( i % (numRows - 1) == 1){m[j][i] = s[sIdx];sIdx ++;}// 斜线模式,一次往上,主要是判定斜线是都会有对应的元素else{int iR = i % (numRows - 1) , jR = row - j + 1;if (iR == 0) iR = (numRows - 1);if ( iR == jR){m[j][i] = s[sIdx];sIdx ++;}elsem[j][i] = ' ';}}}for (int i = 1; i <= row; ++i) {for (int j = 1; j <= col; ++j) {if (m[i][j] <= 'Z' && m[i][j] >= 'A')res += m[i][j];}}return res;
}
- 还是有部分样例不通过,这里不好费时间了,花了差不多一个半小时,不值得,下次不能再这样了!!
参考解法
- 直接从根本上找问题,我靠,没有创建数组,然后直接找输出的序列,因为这本来就是一个等差序列,具体如下
- 这个思路真的简洁,我靠,直接从根本上考虑
分析总结
-
矩阵建议不要从零开始,因为要单独处理j为零的情况,出错的概率太高了,不建议,还是从1开始吧
-
要跳出题目去看,不能被限制住。