Leetcode763. 划分字母区间(C语言)
算法-贪心思想:算法与数据结构参考
题目:
字符串 S 由小写字母组成。我们要把这个字符串划分为尽可能多的片段,同一个字母只会出现在其中的一个片段。返回一个表示每个字符串片段的长度的列表。例:
输入: S = “ababcbacadefegdehijhklij”
输出: [9,7,8]
解释:
划分结果为 “ababcbaca”, “defegde”, “hijhklij”。每个字母最多出现在一个片段中。像 “ababcbacadefegde”, “hijhklij” 的划分是错误的,因为划分的片段数较少。
思路:
贪心算法。用map记录每个元素最后位置,以此为范围遍历,范围内有最后位置更靠后的(二次遍历)则更新范围。
代码:
/**
* Note: The returned array must be malloced, assume caller calls free().
*/
void initmap(char *S, int map[26]){ //记录所有元素最后出现位置
for (int i = 0; S[i]; ++i) {
int k = S[i] - 'a'; //记录字符索引(0-25)
if (i > map[k]) map[k] = i; //之前遇到过的字符更新位置
}
}
int* partitionLabels(char * S, int* returnSize){
if (!S) return NULL;
int len = strlen(S);
int *result = (int *)malloc(sizeof(int) * len);
int map[26] = {0}; initmap(S, map);
*returnSize = 0;
int pos = 0,start = 0,end = 0; //初始化,不能放在for内,否则每次改变
for (int i = 0; i < len; ++i) {
pos = map[S[i] - 'a']; //当前位置
if (pos == end && i == end) { //需要断开,开始下一个区间
result[(*returnSize)++] = end - start + 1; //记录当前区间元素个数
end = i + 1;
start = end;
}
else if (pos > end) end = pos; //区间范围内有更靠后的位置,更新范围
}
return result;
}