题设如链接https://leetcode-cn.com/problems/longest-substring-without-repeating-characters/
滑动窗口法:
1.两个指针分别指向子串的开始位置和结束位置
2.当下一个字符在子串中不重复时有指针前移
3当下一个字符在子串中重复时,左右指针各前移
4.重复2和3,记录最大不重复子串
/**
* 无重复字符的最长字串
*/
@Test
void slidingWindowDemo() {
// 随机取3个长度在5~10的随机字符串作样本
// Random random = new Random();
// String[] input = new String[3];
// for (int i = 0; i < input.length; i++) {
// input[i] = RandomUtils.getRandomString(random.nextInt(6) + 5);
// }
String[] input = new String[]{"qOj6Bqc", "dIKCPd", "zGbNBf6Z"};
// 滑动窗口法
List<List<String>> res = slidingWindow(input);
for (int i = 0; i < input.length; i++) {
System.out.println(String.format("输入:%s\t最大子串:%s", input[i], res.get(i)));
}
}
/**
* 滑动窗口
*
* @param inputs of type String[]
* @return List<List < String>>
*/
private List<List<String>> slidingWindow(String[] inputs) {
List<List<String>> resp = new ArrayList<>();
Set<Character> set = new HashSet<>();
for (String input : inputs) {
List<String> list = new ArrayList<>();
StringBuilder buf = new StringBuilder(input);
set.clear();
if (buf.length() == 0) {
continue;
}
int ij = 0, ik = 0;
// 界定范围
while (ij < input.length() && ik < input.length() && ij <= ik) {
boolean append = false;
// 向右滑动
while (ik < buf.length()) {
char c = buf.charAt(ik);
boolean add = set.add(c);
if (!add) {
String tmp = buf.substring(ij, ik);
appendList(list, tmp);
append = true;
break;
}
ik++;
}
if (!append) {
String tmp = buf.substring(ij, ik);
appendList(list, tmp);
}
if (ij == ik) {
break;
}
// 向左滑动
set.remove(buf.charAt(ij));
ij++;
}
resp.add(list);
}
return resp;
}
/**
* 子串追加到列表
*
* @param last of type List<String>
* @param tmp of type String
*/
private void appendList(List<String> last, String tmp) {
if (last.isEmpty() || last.get(0).length() == tmp.length()) {
last.add(tmp);
} else if (last.get(0).length() < tmp.length()) {
last.clear();
last.add(tmp);
}
}
public class RandomUtils {
/**
* Constructor RandomUtils creates a new RandomUtils instance.
*/
private RandomUtils() {
throw new UnsupportedOperationException();
}
/** 大小写字母加数字的随机种子库 */
@SuppressWarnings("SpellCheckingInspection")
private static final String RANDOM_STR = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
/**
* 获取指定长度的随机字符串(大小写字母加数字)
*
* @param length of type int
* @return String
*/
public static String getRandomString(int length) {
StringBuilder buf = new StringBuilder("");
Random random = new Random();
for (int i = 0; i < length; i++) {
buf.append(RANDOM_STR.charAt(random.nextInt(RANDOM_STR.length())));
}
return buf.toString();
}
}
复杂度O(N):一趟遍历
其实后来想到可以再进行优化:左边指针向右移动后,比较左指针开始到原字符串结束之间的子串长度,若这个长度已经比目前最大的不重复子串的长度要小了,就没必要进行后续的步骤了