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]中
- 若存在,则返回s[i]在[left,right]中的下标index(index是在整个字符串中的下标),left=index+1;right++
- 若不存在,则子串长度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'找当前字符是否曾经出现过
- 是,则更新搜索起始位置i = hash_index[s[k]-'a'] + 1
- 否,则更新长度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其实没有更新
}
梦想还是要有的,万一实现了呢~~~~ヾ(◍°∇°◍)ノ゙~~~~