无重复字符的最长子串
给定一个字符串,找出不含有重复字符的最长子串的长度。
示例:
给定 "abcabcbb"
,没有重复字符的最长子串是 "abc"
,那么长度就是3。
给定 "bbbbb"
,最长的子串就是 "b"
,长度是1。
给定 "pwwkew"
,最长子串是 "wke"
,长度是3。请注意答案必须是一个子串,"pwke"
是 子序列 而不是子串
package com.mhc.pf;
import com.sun.istack.internal.NotNull;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
/**
* 给定一个字符串,找出不含有重复字符的最长子串的长度。
* 示例:
* 给定 "abcabcbb" ,没有重复字符的最长子串是 "abc" ,那么长度就是3。
* 给定 "bbbbb" ,最长的子串就是 "b" ,长度是1。
* 给定 "pwwkew" ,最长子串是 "wke" ,长度是3。请注意答案必须是一个子串,"pwke" 是 子序列 而不是子串
*
* @author :tigermeng.
* @date :13:04 2019-07-12
*/
public class TestMaxSubUniqueString {
public int lengthOfLongestSubstring(String s) {
int num = 0;//记录最长子串长度
int current = 0;//记录当前子串长度
char[] arr = s.toCharArray();
LinkedList<Character> temp = new LinkedList<>();
for (int i = 0; i < arr.length; i++) {
if (!temp.contains(arr[i])) {
temp.add(arr[i]);
current = temp.size();
if (current > num)
num = current;
} else//如果新增字符与原子串中字符有重复的,删除原子串中重复字符及在它之前的字符,与新增字符组成新的子串
{
temp.add(arr[i]);
int first = temp.indexOf(arr[i]);
for (int j = 0; j < first; j++)
temp.remove();
temp.remove();
}
}
return num;
}
public static void main(String[] args) {
TestMaxSubUniqueString test = new TestMaxSubUniqueString();
System.out.println(test.lengthOfLongestSubstring("abcabcbb"));
System.out.println(test.lengthOfLongestSubstring("bbbbb"));
System.out.println(test.lengthOfLongestSubstring("pwwkewa"));
System.out.println("=======");
System.out.println(test.getMaxUniqueStrLength("abcabcbb"));
System.out.println(test.getMaxUniqueStrLength("bbbbb"));
System.out.println(test.getMaxUniqueStrLength("pwwkewa"));
}
/**
* @param str
* @return 小于0代表字符串不符合要求
*/
public int getMaxUniqueStrLength(String str) {
int maxLen = -1;
//不用数组,数组需要定义固定的长度
LinkedList<Character> charLst = new LinkedList<>();
if (null == str || str.length() == 0) {
return maxLen;
}
char[] strChars = str.toCharArray();
for (char strChar : strChars) {
if (charLst.contains(strChar)) {
//有重复的,需要记录下当前字符串的最长大小,清空第一次出现当前char之前的字符
//记录大小
if (maxLen < charLst.size()) {
maxLen = charLst.size();
}
//ArrayList是有顺序的,清除之前的字符
//清除当前的第一次出现的字符
int first = charLst.indexOf(strChar);//返回第一次出现的位置
for (int i = 0; i < first + 1; i++) {
charLst.remove();// remove是从头结点开始移除的
}
}
charLst.add(strChar);
}
//最后一次可能是最大的
if (maxLen < charLst.size()) {
maxLen = charLst.size();
}
return maxLen;
}
}
知识点:
1、数组变量定义时需要固定大小申请,List则不需要
2、LinkedList是有序的,双向链表结构,remove时从head处开始移除
3、循环操作List时,如何避免ConcurrentModificationException异常(用迭代器或者增强for循环(基于迭代器)会出现)