C语言LeetCode题解,第三题“无重复字符的最长子串”

给定一个字符串 s ,请你找出其中不含有重复字符的 最长 子串 的长度。

示例 1:

输入: s = "abcabcbb"
输出: 3 
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。

示例 2:

输入: s = "bbbbb"
输出: 1
解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。

示例 3:

输入: s = "pwwkew"
输出: 3
解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。
     请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串
int lengthOfLongestSubstring(char* s) {
    if (s == NULL || *s == '\0') return 0;
    
    int n = strlen(s);
    if (n == 1) return 1;
    
    int charIndex[128];  // 哈希表:记录字符最近出现的位置
    memset(charIndex, -1, sizeof(charIndex));
    
    int maxLength = 0;   // 记录最大长度
    int left = 0;        // 滑动窗口左边界
    
    for (int right = 0; right < n; right++) {
        char currentChar = s[right];
        
        // 关键步骤1:检查重复字符
        if (charIndex[currentChar] >= left) {
            left = charIndex[currentChar] + 1;
        }
        
        // 关键步骤2:更新字符位置
        charIndex[currentChar] = right;
        
        // 关键步骤3:更新最大长度
        int currentLength = right - left + 1;
        if (currentLength > maxLength) {
            maxLength = currentLength;
        }
    }
    
    return maxLength;
}

分步详细解析

步骤1:初始化阶段

int charIndex[128];           // 创建哈希表(128个ASCII字符)
memset(charIndex, -1, sizeof(charIndex));  // 全部初始化为-1

int maxLength = 0;            // 最大长度初始为0
int left = 0;                 // 窗口左边界从0开始

解释:

  • charIndex 数组就是我们的哈希表

  • 数组下标对应字符的ASCII码,值记录该字符最近出现的位置

  • 初始化为-1表示所有字符都还没出现过

  • left 是滑动窗口的左边界right 是右边界

步骤2:遍历字符串(右指针移动)

for (int right = 0; right < n; right++) {
    char currentChar = s[right];  // 当前字符
    // ... 后续处理
}

解释:

  • right 指针从0开始,逐个字符向右移动

  • 每次循环处理一个字符,扩展窗口的右边界

步骤3:检查重复字符(核心逻辑)

if (charIndex[currentChar] >= left) {
    left = charIndex[currentChar] + 1;
}

详细分析:

情况1:字符第一次出现

  • charIndex[currentChar] == -1(初始值)

  • -1 >= left 为 false

  • 不进入if语句,左边界left保持不变

情况2:字符在窗口外出现过

  • 比如:"abcade",当处理第二个'a'时

  • 第一个'a'在位置0,但当前left可能在位置3

  • charIndex['a'] = 00 >= 3 为 false

  • 不进入if语句,这个'a'不算重复(因为不在当前窗口内)

情况3:字符在窗口内重复

  • 比如:"abcabc",当处理第二个'b'时

  • 第一个'b'在位置1,当前left在位置0

  • charIndex['b'] = 11 >= 0 为 true

  • 进入if语句:left = 1 + 1 = 2

  • 窗口左边界跳到重复字符的下一个位置

步骤4:更新字符位置

charIndex[currentChar] = right;

解释:

  • 无论是否重复,都要更新该字符的最新位置

  • 哈希表始终记录每个字符最后一次出现的位置

  • 为下一次检查重复做准备

步骤5:计算当前窗口长度

int currentLength = right - left + 1;
if (currentLength > maxLength) {
    maxLength = currentLength;
}

解释:

  • right - left + 1 计算当前无重复子串的长度

  • 如果比之前记录的最大值大,就更新maxLength

具体示例演示

示例:s = "abcabcbb"

步骤0: 初始化
  charIndex: 全部为-1, left=0, maxLength=0

步骤1: right=0, char='a'
  检查: charIndex['a']=-1 >=0? false → left不变=0
  更新: charIndex['a']=0
  长度: 0-0+1=1, maxLength=1

步骤2: right=1, char='b'
  检查: charIndex['b']=-1 >=0? false → left=0
  更新: charIndex['b']=1
  长度: 1-0+1=2, maxLength=2

步骤3: right=2, char='c'
  检查: charIndex['c']=-1 >=0? false → left=0
  更新: charIndex['c']=2
  长度: 2-0+1=3, maxLength=3

步骤4: right=3, char='a' ← 出现重复!
  检查: charIndex['a']=0 >=0? true → left=0+1=1
  更新: charIndex['a']=3
  长度: 3-1+1=3, maxLength=3

步骤5: right=4, char='b' ← 出现重复!
  检查: charIndex['b']=1 >=1? true → left=1+1=2
  更新: charIndex['b']=4
  长度: 4-2+1=3, maxLength=3

步骤6: right=5, char='c' ← 出现重复!
  检查: charIndex['c']=2 >=2? true → left=2+1=3
  更新: charIndex['c']=5
  长度: 5-3+1=3, maxLength=3

步骤7: right=6, char='b' ← 出现重复!
  检查: charIndex['b']=4 >=3? true → left=4+1=5
  更新: charIndex['b']=6
  长度: 6-5+1=2, maxLength=3

步骤8: right=7, char='b' ← 出现重复!
  检查: charIndex['b']=6 >=5? true → left=6+1=7
  更新: charIndex['b']=7
  长度: 7-7+1=1, maxLength=3

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值