最长不重复字符的子字符串问题

leetcode 3. Longest Substring Without Repeating Characters

一、问题描述

给定一个字符串,找到最长的子字符串的长度而不重复字符。
【举例】
给定“abcabcbb”,答案是“abc”,长度为3。
给定“bbbbb”,答案是“b”,长度为1。

给定“pwwkew”,答案是“wke”,长度为3.请注意,答案必须是子字符串,“pwke”是子序列而不是子字符串。

二、方法一:贪心法 -- 滑动窗口

以abcabcbb为例
定义一个left游标和一个right游标,[left,right]表示不含重复字符的子串范围
探测s[i]是否在[left,right]中

  1. 若存在,则返回s[i]在[left,right]中的下标index(index是在整个字符串中的下标),left=index+1;right++
  2. 若不存在,则子串长度len++,right++
/********************************************************
author:tmw
date:2018-6-5
*********************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>

//返回字符ch在字符串str中子串范围[sub_left,sub_right]中的下标,没找到则返回-1
int find_ch_in_substr(char* str, int sub_left, int sub_right, char ch)
{
    int i;
    for(i=sub_left; i<=sub_right; i++)
        if(str[i] == ch)
            return i;
    return -1;
}

#define max(a,b) (a>b?a:b)
int lengthOfLongestSubstring(char* s)
{
    int len;
    int max_len = 0;
    int i;
    int index;

    int left = 0;
    int right = 0;

    if( strlen(s) == 1 ) return 1;
    for( i=1; i<strlen(s); i++ )
    {
        //找s[i]在子串[left,right]中的下标
        index = find_ch_in_substr(s,left,right,s[i]);

        //len最少是1
        len = right-left>=0?right-left+1:1;

        //没找到
        if( index == -1 )
            len++;
        //找到,更新left值
        else
            left = index+1;
        right++;

        max_len = max(max_len,len);
    }
    return max_len;
}

三、方法二:贪心法 -- 滑动窗口+哈希存储

        从左往右扫描,当遇到重复字母时,以上一个重复字母的index+1,作为新的搜索起始位置,直到最后一个字母,复杂度是O(n)。

        用一个hash数组hash_index[s[k]-'a']记录字符s[k]曾经出现的位置,从左往右扫描中,通过同样的hash方法s[i]-'a'找当前字符是否曾经出现过

  1. 是,则更新搜索起始位置i = hash_index[s[k]-'a'] + 1
  2. 否,则更新长度len++
#define max(a,b) (a>b?a:b)
#define SIZE 128 //asci表一共177个字符  其中空字符是第一个
int lengthOfLongestSubstring(char* s)
{
    int hash_index[SIZE];
    int i;

    //0也算有效位置,因此无效位置初始化设为-1
    memset(hash_index,-1,sizeof(hash_index));

    int len = 0;//记录当前不重复字符的子串长度
    int max_len = 0;//记录截止当前最长不重复子字符串的长度

    for( i=0; i<strlen(s); i++ )
    {
        int index = hash_index[s[i]-' '];

        /**如果该字符曾经出现过**/
        if( index >= 0 )
        {
            max_len = max(max_len,len); //保留截止当前的最大子串长度

            //更新当前记录的len
            len = 0;

            //更新搜索起始位置
            i = index + 1;

            //清空所有记录的有效位置,从新的搜索起始位置重新记录
            memset(hash_index,-1,sizeof(hash_index));
        }
        //将当前字符s[i]的位置记录在hash表中
        hash_index[s[i]-' '] = i;
        len++;
    }
    return max(max_len,len); //eg:"abcd"这种,max_len其实没有更新
}



梦想还是要有的,万一实现了呢~~~~ヾ(◍°∇°◍)ノ゙~~~~


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值