Java 如何在不重复字符的情况下查找最长的子字符串?
我正在解决leetcode上的一个问题。这是问题链接Java 如何在不重复字符的情况下查找最长的子字符串?,java,Java,我正在解决leetcode上的一个问题。这是问题链接 下面是我的解决方案,它没有通过一些测试用例: ABCABBB——不正确 pwkwkw——正确 不正确 任何帮助都将不胜感激:) 我也是这里的新手,所以你可以向我推荐我的问题陈述 class Solution { public int lengthOfLongestSubstring(String s) { int i,max=0; List<Character> list = new A
下面是我的解决方案,它没有通过一些测试用例:
我也是这里的新手,所以你可以向我推荐我的问题陈述
class Solution {
public int lengthOfLongestSubstring(String s) {
int i,max=0;
List<Character> list = new ArrayList<>();
String x = "";
for(i=0;i<s.length();i++)
{
if(!list.contains(s.charAt(i)))
{
x += s.charAt(i);
list.add(s.charAt(i));
System.out.println(x);
}
else
{
if(x != null && x.length() > max)
{
max = x.length();
System.out.println(max);
x = "";
list.clear();
System.out.println("x : "+ x);
System.out.println("list : "+ list);
}
// else
// {
// list.add(s.charAt(i));
// x += s.charAt(i);
// System.out.println("x in else : "+ x);
// System.out.println("list in else : "+ list);
// }
list.add(s.charAt(i));
x += s.charAt(i);
System.out.println("x in else : "+ x);
System.out.println("list in else : "+ list);
}
}
return max;
}
}
类解决方案{
public int lengthOfLongestSubstring(字符串s){
int i,max=0;
列表=新的ArrayList();
字符串x=“”;
对于(i=0;i最大值)
{
最大值=x.长度();
系统输出打印项次(最大值);
x=“”;
list.clear();
System.out.println(“x:+x”);
System.out.println(“列表:+list”);
}
//否则
// {
//增加(s.charAt(i));
//x+=s.charAt(i);
//System.out.println(“x-in-else:+x”);
//System.out.println(“在其他地方列出:+list”);
// }
增加(s.charAt(i));
x+=s.charAt(i);
System.out.println(“x-in-else:+x”);
System.out.println(“在其他地方列出:+list”);
}
}
返回最大值;
}
}
您可以按如下方式执行:
import java.util.HashSet;
import java.util.Set;
class Main {
public static void main(String[] args) {
// Tests
System.out.println(lengthOfLongestSubstring("abcabcbb"));
System.out.println(lengthOfLongestSubstring("pwwkew"));
System.out.println(lengthOfLongestSubstring("bbbbb"));
System.out.println(lengthOfLongestSubstring("aab"));
System.out.println(lengthOfLongestSubstring("xabycdxefghy"));
System.out.println(lengthOfLongestSubstring("aBcdBefgh"));
System.out.println(lengthOfLongestSubstring("aXbXcdXefgXh"));
}
static int lengthOfLongestSubstring(String s) {
int max = 0;
String ch;
Set<String> strSet = new HashSet<String>();
StringBuilder sb = new StringBuilder();
s = s.toLowerCase();
for (int i = 0; i < s.length(); i++) {
for (int j = i; j < s.length(); j++) {
ch = String.valueOf(s.charAt(j));
if (sb.indexOf(ch) == -1) {
sb.append(ch);
} else {
strSet.add(sb.toString());
sb = new StringBuilder(ch);
}
}
strSet.add(sb.toString());
sb = new StringBuilder();
}
for (String str : strSet) {
if (max < str.length()) {
max = str.length();
}
}
return max;
}
}
解释:创建一组(
strSet
在我的代码中)所有最长的子字符串,从字符串中的每个字符开始。然后,迭代这组子字符串并返回最长子字符串的长度。我之所以选择Set
而不是列表
,是因为我想丢弃重复的子字符串。有时尽可能多地留在问题域中是有帮助的。这种方法在考虑编码之前创建了一个解决方案。这种方法给我们留下了一组极其复杂的逻辑操作,然后需要实现
首先是我们的初始条件。列应清晰:输入(始终相同)、当前(不带重复字符的当前子字符串)、应答(字符串形式的当前应答)和逻辑(此步骤应用的逻辑:
因此,第一次迭代的开始与rest相同:获取输入中的下一个字符。检查它是否在当前子字符串中,并且因为它没有添加到当前。这里我们还问一个问题:答案是否比当前短,如果是,请将答案设置为当前
请注意,在逻辑列中,我们正在开发需要在解决方案中实现的操作
重复第二个字符输入(无新操作):
第三种情况(无新操作):
好的,现在我们在当前子字符串中找到下一个CH,所以我们需要一个新的操作:'删除current中的字符,直到但不包括CH。注意,“将CH添加到current”也在这种情况下完成。注意一些新的逻辑(答案与current一样长或更长,所以“不做任何事情”)
并完成事情-没有新的操作
现在我们到了输入的末尾,简单地问一个问题“答案有多长”,这就是结果
现在看一下逻辑列,我们看到要执行的操作:
// Initial condition
String answer = "";
String current = "";
让我们完全以字符串的形式工作,以保持事情的简单性-优化可以稍后进行
让我们定义“下一个CH(nextChar)”操作:
// Get the ith character (0-based) from 's' as a String.
private static String nextChar(String s, int i) {}
我们需要一个“检查‘当前是否包含CH’”的操作:
我们需要检查当前答案是否比当前答案短:
// True if the 'answer' String is short in length than the 'current' string.
private static boolean isAnswerShorterThanCurrent(String current, String answer) {}
// @return a String which has all characters removed from 'current' up to but not including 'ch'
private static String removeUpToChar(String current, String ch) {}
以及将nextChar附加到当前文件的功能:
// Append the 'nextChar' to the 'current' String and return the String.
private static String addChToCurrent(String current, String nextChar) {}
最后,能够删除当前字符中最多但不包括当前字符的所有字符:
// True if the 'answer' String is short in length than the 'current' string.
private static boolean isAnswerShorterThanCurrent(String current, String answer) {}
// @return a String which has all characters removed from 'current' up to but not including 'ch'
private static String removeUpToChar(String current, String ch) {}
因此,将其放在一起(基本上仍处于问题域中,因为我们没有实现任何操作,只是将问题投射到结构中):
public int lengthOfLongestSubstring(字符串s){
字符串答案=”;
字符串current=“”;
对于(int i=0;i
现在实现“操作”变得更容易(也更有趣),因为它们是孤立的,并不复杂。这是留给你的。实现后,问题就解决了
验证正确性后的下一个逻辑步骤是考虑优化-如果需要的话,
尽管图片是有用的,并且大多是正确的,但是代码是次优的。 问题中的代码,以及当前两个答案中的代码,使用字符串连接构建了大量子字符串。这对性能有害
下面是一个不构建任何子字符串的O(n)解决方案:public static int lengthOfLongestSubstring(String s) {
Map<Character, Integer> lastPos = new HashMap<>();
int start = 0, maxLen = 0, i = 0;
for (; i < s.length(); i++) {
Integer pos = lastPos.put(s.charAt(i), i);
if (pos != null && pos >= start) {
if (i > start + maxLen)
maxLen = i - start;
start = pos + 1;
}
}
return (i > start + maxLen ? i - start : maxLen);
}
1) 要返回多个最长子字符串中的最后一个,请将i>
更改为i>=
上述解决方案无法处理带有补充平面中Unicode字符的字符串,例如表情符号
我相信所有的反对票都是因为StackOverflow不是免费的调试服务。你应该自己调试自己的代码,我们看不到任何证据。你调试过吗?您可能想告诉我们每个测试用例的正确/预期结果,以及您的程序观察到的输出。你需要重新思考你的逻辑,因为当你遇到一个重复的字符时,你不能只清楚你在跟踪数据。例如,输入
“aBcdBefgh”
会使您在看到第二个B
时清除,将“Befgh”
作为最长的子字符串,而最长的子字符串实际上是
public static int lengthOfLongestSubstring(String s) {
Map<Character, Integer> lastPos = new HashMap<>();
int start = 0, maxLen = 0, i = 0;
for (; i < s.length(); i++) {
Integer pos = lastPos.put(s.charAt(i), i);
if (pos != null && pos >= start) {
if (i > start + maxLen)
maxLen = i - start;
start = pos + 1;
}
}
return (i > start + maxLen ? i - start : maxLen);
}
public static String longestSubstring(String s) {
Map<Character, Integer> lastPos = new HashMap<>();
int start = 0, maxStart = 0, maxLen = 0, i = 0;
for (; i < s.length(); i++) {
Integer pos = lastPos.put(s.charAt(i), i);
if (pos != null && pos >= start) {
if (i > start + maxLen) {
maxStart = start;
maxLen = i - start;
}
start = pos + 1;
}
}
return (i > start + maxLen ? s.substring(start) : s.substring(maxStart, maxStart + maxLen));
}