下面的题目要使用的主要思路为滑动窗口,但是还需要使用哈希表来储存窗口中的元素个数
题目一:无重复字符的最长子串
给定一个字符串 s
,请你找出其中不含有重复字符的 最长子串 的长度。
示例 1:
输入: s = "abcabcbb"
输出: 3
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。
示例 2:
输入: s = "bbbbb"
输出: 1
解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。
示例 3:
输入: s = "pwwkew"
输出: 3
解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。
请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。
那么要如何去寻找s中不含有重复字符的最长子串呢?
我首先会定义两个整型名字为left(代表的是左窗口指向元素的下标),right(代表的是右窗口指向元素的下标)。以及一个哈希表,(因为题目中只会出现char类型的数据,所以我们可以使用一个大小为128的整型数组来模拟实现哈希表,因为char类型的asc2码范围为-127到128,那么使用一个大小为128的整型数组肯定能够装下)这个哈希表的用途是记录窗口中的元素个数。那么一开始窗口中没有元素,left和right下标肯定是从0开始,接下来right会将下标为0的元素放入窗口中去,同时在哈希表中下标为这个元素的大小也就会加1。然后如果这个元素的个数不大于1就继续让右指针移动往窗口中放元素,直到放入的一个元素大小大于1了,我们在让左指针加加,同时让左指针代表的原数在哈希表中的数量减去1,直到这个窗口中没有数量大于1的元素。
下面是代码实现:
int lengthOfLongestSubstring(char * s)
{
//使用思路为滑动窗口
//其中在窗口内的元素我们使用一个哈希表来维护
int ret = 0;//先假定最长的字串为0
int left = 0;//左窗口坐标
int right = 0;//右窗口坐标
int haxi[128];//因为只会出现字符,那么只需要使用127大小的哈希表即可解决
//并且因为题目中出现的字符不存在重复的情况也不会导致出现哈希表下标表示冲突的情况
memset(haxi,0,sizeof(haxi));//将哈希表内的所有值修改为0
int len = strlen(s);
while(right<len)
{
char ch = s[right];//将这个要放入窗口中的元素先储存起来
right++;//让right指向下一个即将将进入窗口的元素
//用来作为访问哈希表的下标
haxi[ch]++;//放入窗口中去了自然要更新哈希表的数据
while(haxi[ch]>1)//如果窗口里面之前就存在了这个元素那么就要将left位置的元素移除出窗口
//直到我们删除了这个新进入元素在窗口里面重复的那一部分
{
char del = s[left];
haxi[del]--;
left++;
}
ret = ret>(right - left)?ret:(right - left);
}
return ret;
}
题目二:找到字符串中所有字母异位词
给定两个字符串 s
和 p
,找到 s
中所有 p
的 异位词 的子串,返回这些子串的起始索引。不考虑答案输出的顺序。
异位词 指由相同字母重排列形成的字符串(包括相同的字符串)。
示例 1:
输入: s = "cbaebabacd", p = "abc"
输出: [0,6]
解释:
起始索引等于 0 的子串是 "cba", 它是 "abc" 的异位词。
起始索引等于 6 的子串是 "bac", 它是 "abc" 的异位词。
示例 2:
输入: s = "abab", p = "ab"
输出: [0,1,2]
解释:
起始索引等于 0 的子串是 "ab", 它是 "ab" 的异位词。
起始索引等于 1 的子串是 "ba", 它是 "ab" 的异位词。
起始索引等于 2 的子串是 "ab", 它是 "ab" 的异位词。
这道题目先创建一个大小为128的哈希表1,用于储存字符串p中各个字符出现的次数。
然后我们在s上使用一个固定大小的滑动窗口,滑动窗口的大小也就是p的长度。然后我们比较窗口内的元素个数和p中的元素个数是否相等,相等则为异位词并且将左窗口的值放入到结果数组里面,不等则将窗口向右推进。
下面是代码实现:
int* findAnagrams(char* s, char* p, int* returnSize)
{
int lenp = strlen(p);
int lens = strlen(s);
if (lens < lenp)//不可能存在字母异位词
{
*returnSize = 0;
return NULL;
}
int haxis[128] = { 0 };
int haxip[128] = { 0 };
int* ret = (int*)malloc(sizeof(int) * (lens - lenp + 1));
int count = 0;//用于记录满足条件的索引有多少个
if (ret == NULL)
{
perror("malloc fail");
return NULL;
}
for (int i = 0; i < lenp; i++)
{
haxip[p[i]]++;//p字符里面的所有元素都放入到记录p元素个数的哈希表中去
}
int left = 0;
int right = 0;//这是s哈希表的左下标和右下标
for (; right < lens; right++)
{
haxis[s[right]]++;
if (haxis[s[right]] > haxip[s[right]])//这里就表示放入到haxis中的这个元素的个数大于了
//在p中的这个元素的个数
{
while (haxis[s[right]] > haxip[s[right]])
{
haxis[s[left]]--;//我们要利用左窗口指针让左窗口的元素移除出窗口
left++;//直到窗口中新增加的元素等于p中这个元素的个数
}
}
if (right - left + 1 == lenp && memcmp(haxip, haxis, sizeof(int) * 128) == 0)//如果现在在窗口中的元素等于p的长度
//并且两个哈希数组相等则可以将索引放入结果数组中去
{
ret[count++] = left;
}
}
*returnSize = count;
return ret;
}
标签:right,题目,int,元素,哈希,滑动,解析,窗口,left
From: https://blog.51cto.com/u_15838996/6454754