📅  最后修改于: 2023-12-03 15:10:37.819000             🧑  作者: Mango
当涉及到字符串处理时,找到其最长的子串是一个常见的问题。在Java中,有几种方法可以解决这个问题,其中包括暴力解法、滑动窗口和动态规划等。
暴力解法是最简单的解法,但是它的时间复杂度很高,需要O(n^3)的时间才能找到最长的子串。该方法的思路是从字符串的开头开始,获取所有可能的子串,然后通过比较它们的长度找到最长的子串。下面是一个示例代码:
public static String longestSubstring(String s) {
String longest = "";
for (int i = 0; i < s.length(); i++) {
for (int j = i + 1; j <= s.length(); j++) {
if (s.substring(i, j).length() > longest.length() && isUnique(s.substring(i, j))) {
longest = s.substring(i, j);
}
}
}
return longest;
}
private static boolean isUnique(String s) {
HashSet<Character> set = new HashSet<>();
for (char c : s.toCharArray()) {
if (!set.add(c)) return false;
}
return true;
}
滑动窗口是另一种方法,它可以在不重复遍历所有子串的情况下找到最长的子串。该方法的思路是将一个窗口放置在字符串的开头,并将其向右滑动,直到与窗口重叠的子串不重复为止。然后将窗口扩大并再次滑动,直到找到最长的子串。下面是一个示例代码:
public static String longestSubstring(String s) {
int i = 0, j = 0;
String longest = "";
HashSet<Character> set = new HashSet<>();
while (j < s.length()) {
if (!set.contains(s.charAt(j))) {
set.add(s.charAt(j++));
longest = Math.max(longest.length(), j - i) == j - i ? s.substring(i, j) : longest;
} else {
set.remove(s.charAt(i++));
}
}
return longest;
}
动态规划是另一种更高效的解法。它使用一个二维数组来保存最长子串的长度。该数组的行代表字符串中的字母,而列代表字母的数量。当填充数组时,可以使用一个变量来记录最长子串的长度,并在每次更新数组时进行比较。下面是一个示例代码:
public static String longestSubstring(String s) {
int i = 0, j = 0, maxLength = 0;
boolean[] bitSet = new boolean[256];
String longest = "";
while (j < s.length()) {
if (!bitSet[s.charAt(j)]) {
bitSet[s.charAt(j++)] = true;
maxLength = Math.max(maxLength, j - i);
longest = maxLength == j - i ? s.substring(i, j) : longest;
} else {
bitSet[s.charAt(i++)] = false;
}
}
return longest;
}
无论使用哪种方法,确保测试你的代码以确保它可以正常工作。