请从字符串中找出一个最长的不包含重复字符的子字符串,计算该最长子字符串的长度。如输入: "abcabcbb" 输出: 3。
提供了两种解决办法,一个是官方提供的答案,虽然简洁,但感觉不太容易看懂;另外一种是双指针,比较容易看懂,但代码比较复杂。两种方法总体效率差不了太多。
package learnproject.offer;
import java.util.HashMap;
import java.util.Map;
/*
* 48.最长不含重复字符的子字符串
*/
public class Demo48 {
/*
* 动态规划算法
* 1.将字符串转为字节数组
* 2.不含重复子串的左边起点下表为left
* 3.不含重复子串的右边起点下表为right
* 4.当出现重复时,需要left右移到重复的字节的下一个字节
* 5.未出现重复是,right右移
* 6.最大长度为max,dp为left为i时的最大长度
* 7.定义map集合,key为字符串数组值,value为对应下标
* 8.当遍历到第i个元素时,如果发现和前面的第k个元素相同,则需要将k到i之间的元素数量记下来
* 因为下次遍历时,直接将left移动到k,right以到right+1位置上
* 但这里还有一点需要注意的就是,如果k在left的左边,则不需要移动left,
* 直接将rith后移即可。
* 9.出现相同元素时,跳出最内存循环,同时k到i的元素个数为tmpdp,tmpdp肯定是小于或等于dp的
* 所以内存循环结束时,只需要返回max和dp的最大值即可。
* 10.内存循环结束后,将tempdp赋值给dp,继续下一次的外层循环
*/
public int lengthOfLongestSubstring(String s) {
char[] chararray = s.toCharArray();
int length = chararray.length;
if(length <2) {
return length;
}
//遍历到到i个元素时最长不重复子字符串
int left = 0,right=1;
//最长不重复子字符串
int max = 1;
int dp = 1;
Map<Character,Integer> map = new HashMap<Character,Integer>();
while(left<length-1) {
map.put(chararray[left], left);
int templeft = left+1;
int tempdp = 1;
while(right<length && right>left) {
char tempchar = chararray[right];
if(map.containsKey(tempchar)) {
int value = map.get(tempchar);
if(value >= left) {
map.put(tempchar, right);
tempdp = right-value;
left = value+1;
right++;
break;
} else {
map.put(tempchar, right);
dp++;
}
}else {
map.put(tempchar, right);
dp++;
}
right++;
}
max = Math.max(max, dp);
dp = tempdp;
left = Math.max(templeft, left);
}
return max;
}
/*
* 官方答案
*/
public int lengthOfLongestSubstringNew(String s) {
char[] chararray = s.toCharArray();
int length = chararray.length;
if(length <2) {
return length;
}
int max = 0;
int dp =0;
Map<Character,Integer> map = new HashMap<Character,Integer>();
for(int i=0;i<length;i++) {
char tempchar = chararray[i];
int value = map.getOrDefault(tempchar, -1);
map.put(tempchar, i);
int temp = i-value;
if(temp > dp) {
dp++;
}else {
dp = temp;
}
max = Math.max(dp, max);
}
return max ;
}
public static void main(String args[]) {
Demo48 demo = new Demo48();
String s = "tmmzuxt";
System.out.println(demo.lengthOfLongestSubstring(s));
System.out.println(demo.lengthOfLongestSubstringNew(s));
}
}