想着靠leecode刷题来提升下自己,发现leecode好像不能查看以前做过的题目,所以还是自己写了保存下吧,以后想看的时候还能找到。
题目链接:763. 划分字母区间
字符串 S
由小写字母组成。我们要把这个字符串划分为尽可能多的片段,同一个字母只会出现在其中的一个片段。返回一个表示每个字符串片段的长度的列表。
示例 1:
输入: S = "ababcbacadefegdehijhklij"
输出: [9,7,8]
解释:
划分结果为 "ababcbaca", "defegde", "hijhklij"。
每个字母最多出现在一个片段中。
像 "ababcbacadefegde", "hijhklij" 的划分是错误的,因为划分的片段数较少。
注意:
S
的长度在[1, 500]
之间。S
只包含小写字母'a'
到'z'
。
一、解题思路
举例子说明来得更快,先定义一个结构体struct ord和结构体ord的容器vector<ord> co;
typedef struct coordiation{
char word;
int start;
int end;
} ord;//存储字符word的最前一个位置和最后一个位置坐标vector<ord> co;//结构体ord的容器
我们假如要分割的字符串为s="bbvemgjwruuwalp",我们把每一个不同字符的开始位置和结束位置找出来,一定是不同字符,记录进该字符对应的结构体,比如字符b的开始位置为0,结束位置为1,则b对应的结构体为{‘b’,0,1},我们将出现过的字符在原始字符串中置为字符0,这样就能保证每一个不同的字符在结构体容器co中只出现一次了。依次遍历原始字符串s中的每一个字符,将不同字符对应的结构体推入co中。
现在s="bbvemgjwruuwalp",则得到的结构体分别为(IDE为CLion):
得到了结构体co,也就清楚了每一个不重复字符的开始和结束位置,现在则合并那些有交集的字符并计算有交集字符的开始和结束位置。观察上面的co结构体,我们发现co[0]=b和co[1]=v是没有交集的(因为v.start>b.end),所以就有了字符串片段"bb",片段长度为end-start+1=1-0+1=2,再观察co[6]=w和co[7]=r,我们发现它们是交集的(因为r.start<w.end),而且w之间是包含r的,差不多是这种形式,r...w..r,所以要合并,合并后的start取两者较小的start(其实是不变的),合并后的end,则取较大的end。将所有有交集的字符进行合并,没有交集的字符则做为一个单独的片段。最后就可以计算出每一个片段的长度。我这里得到的结果是:
二、CLion代码(有一些帮助理解的注释)
#include <iostream> #include <vector> using namespace std; typedef struct coordiation{ char word; int start; int end; } ord;//字符word的最前一个位置和最后一个位置坐标 //救出字符串S中每一个不重复字符的ord结构体 vector<ord> HaveCoordination(string &s){ vector<ord> co; for(int i=0;i<s.length();i++){ if('0'==s[i]) continue; ord temp; temp.word=s[i];//存储字符 temp.start=i;//存储字符的开始位置 int flag=0;//字符s[i]是否出现的标志 for(int j=i+1;j<s.length();j++){ if(s[i]==s[j]) {//如果遇到重复字符,则将字符的最后位置给temp并入容器,否则不给,也不入容器 temp.end = j; s[j]='0'; flag=1; } } if(0==flag){ temp.end=i; } co.push_back(temp); s[i]='0'; } return co; }; //得到每个不同字母的坐标后,执行partitionLabels函数,返回 vector<int> partitionLabels(const vector<ord> &co) { vector<int> result; int start_temp=co[0].start; int end_temp=co[0].end; int result_temp=end_temp-start_temp;//每片不重复字符串的长度 for(int i=1;i<co.size();i++){ //如果i的start小于end_temp,就要合并两个长度 if(co[i].start<=end_temp){ if(co[i].end>end_temp) end_temp=co[i].end; result_temp=end_temp-start_temp; //continue;-var-create: unable to create variable object } //不然更新start_temp和end_temp else{ result.push_back(result_temp+1); start_temp=co[i].start; end_temp=co[i].end; result_temp=end_temp-start_temp; } } result.push_back(result_temp+1); return result; } int main() { //std::cout << "Hello, World!" << std::endl; vector<ord> co_m; vector<int> result; string s="bbvemgjwruuwalp"; co_m=HaveCoordination(s); result=partitionLabels(co_m); cout<<result[0]<<endl; return 0; }
三、leecode代码
class Solution { typedef struct coordiation{ char word; int start; int end; } ord;//字符word的最前一个位置和最后一个位置坐标 public: //求出字符串S中每一个不重复字符的ord结构体 vector<ord> HaveCoordination(string &s){ vector<ord> co; for(int i=0;i<s.length();i++){ if('0'==s[i]) continue; ord temp; temp.word=s[i];//存储字符 temp.start=i;//存储字符的开始位置 int flag=0;//字符s[i]是否出现的标志 for(int j=i+1;j<s.length();j++){ if(s[i]==s[j]) {//如果遇到重复字符,则将字符的最后位置给temp并入容器,否则不给,也不入容器 temp.end = j; s[j]='0'; flag=1; } } if(0==flag){ temp.end=i; } co.push_back(temp); s[i]='0'; } return co; }; //得到每个不同字母的坐标后,执行partitionLabels函数,返回 vector<int> partitionLabels(string &s) { vector<ord> co=HaveCoordination(s); vector<int> result; int start_temp=co[0].start; int end_temp=co[0].end; int result_temp=end_temp-start_temp;;//每片不重复字符串的长度 for(int i=1;i<co.size();i++){ //如果i的start小于end_temp,就要合并两个长度 if(co[i].start<=end_temp){ if(co[i].end>end_temp) end_temp=co[i].end; result_temp=end_temp-start_temp; //continue; } //不然更新start_temp和end_temp else{ result.push_back(result_temp+1); start_temp=co[i].start; end_temp=co[i].end; result_temp=end_temp-start_temp; } } result.push_back(result_temp+1); return result; } };