C语言:复用后的哈希表能否高效置零?最长无重复子串解法咨询
最长无重复字符子串解法疑问解答
一、当前解法思路是否正确?
你的代码思路存在明显问题,无法正确解决最长无重复字符子串问题,具体问题如下:
- 逻辑漏洞:遇到重复字符时直接重置计数并跳过当前字符,这种方式会丢失中间可能存在的更长子串。比如字符串
"abba",当遇到第二个b时直接清零,会忽略掉有效窗口的正确调整逻辑,导致结果错误。 - 循环死锁:代码中没有移动指针
s++,也没有count++的逻辑,会陷入无限循环。 - 最大值更新错误:
max_count = count - 1的赋值会覆盖之前的最大值,比如如果之前已经有更长的子串,遇到重复时会错误地将max_count设为当前窗口的长度,无法保留历史最大值。 - 未处理遍历结束的情况:当字符串遍历完成后,当前的
count可能比max_count更大,但代码没有做最后一次比较。
正确的思路应该采用滑动窗口(双指针):用左右两个指针维护一个始终无重复字符的窗口,通过哈希表记录字符的最新位置,遇到重复字符时将左指针移动到重复字符上一次出现位置的下一位,动态调整窗口范围并更新最大长度。
二、哈希表(hist数组)高效置零的替代方案
循环遍历256个元素置零确实会增加不必要的开销,尤其是频繁重置时效率更低。这里有两种更高效的替代方案:
1. 使用时间戳替代计数,彻底避免置零
不用数组存储字符的出现次数,而是存储字符最后一次出现的索引位置。初始化时将所有位置设为-1(表示未出现过),当处理字符时,只需判断该字符的最后出现位置是否在当前窗口范围内:如果是,就移动左指针到该位置的下一位;否则直接更新字符的最新位置。这种方式完全不需要置零操作,每个字符仅处理一次,时间复杂度为O(n)。
示例代码:
int lengthOfLongestSubstring(char * s){ int last_pos[256]; memset(last_pos, -1, sizeof(last_pos)); // 初始化所有位置为-1 int left = 0; int max_len = 0; int str_len = strlen(s); for (int right = 0; right < str_len; right++) { unsigned char c = s[right]; // 如果当前字符在窗口内已出现,移动左指针到重复位置的下一位 if (last_pos[c] >= left) { left = last_pos[c] + 1; } // 更新当前字符的最新位置 last_pos[c] = right; // 计算当前窗口长度并更新最大值 int current_len = right - left + 1; if (current_len > max_len) { max_len = current_len; } } return max_len; }
2. 仅重置窗口内的字符(不推荐)
如果一定要用计数的方式,可以维护一个临时列表记录当前窗口内出现过的字符,当需要重置窗口时,只遍历这个列表将对应数组位置置零,而不是遍历整个256长度的数组。不过这种方式需要额外的存储空间,且实现复杂度高于时间戳方法,实际应用中不推荐。
内容的提问来源于stack exchange,提问作者user1188938
相关产品推荐
相关产品推荐

