子串:原序列中必须连续的一段
子序列:原序列中可以不连续的一段
注意:无论是子串和子序列,元素的顺序都是原序列中的顺序 注意:无论是子串和子序列,元素的顺序都是原序列中的顺序
- 示例1:输入: s = “abcabcbb” 输出: 3 解释: 因为无重复字符的最长子串是 “abc”,所以其长度为 3。
- 示例2:输入: s = “bbbbb” 输出: 1 解释: 因为无重复字符的最长子串是 “b”,所以其长度为 1。
- 示例3:输入: s = “pwwkew” 输出: 3 解释: 因为无重复字符的最长子串是 “wke”,所以其长度为 3。 请注意,你的答案必须是子串的长度,”pwke” 是一个子序列,不是子串。
- 示例4:输入: s = “” 输出: 0
提示:0 <= s.length <= 5 * 10^4 s由英文字母、数字、符号和空格组成
public class Test3 {
public static void main(String[] args) {
String str = "asdf234234fdgbv";
System.out.println(lengthOfLongestSubstring(str));
System.out.println(lengthOfLongestSubstring2(str));
System.out.println(lengthOfLongestSubstring3(str));
}
/**
* 实现方式1:遍历每一个字符串,检查从当前字符串后的字符开始是否跟前面的字符串相同,若相同则不属于子串
* 否在属于子串,缺点:使用的是list来保存子串,然后检查是否再list里面时间复杂度要用O(N),所以很慢
* 执行用时:1412 ms, 在所有 Java 提交中击败了5.01%的用户 内存消耗:39.4 MB, 在所有 Java 提交中击败了5.08%的用户
* @param str
* @return
*/
public static int lengthOfLongestSubstring(String str) {
// 用最傻的方法先实现,遍历每个字母开始的最长字串
int maxLen = 0;
// 定义一个数组来存贮从某一个字符开始的最长子串
String maxStr = "";
if (str.length() <= 0) {
maxLen = 0;
} else {
List<String> strs = new ArrayList<String>();
for (int i = 0; i < str.length(); i++) {
// 先获取第一个字符的最长字串
// 获取当前要判断的字符
char now = str.charAt(i);
strs.add(now + "");
for (int j = i + 1; j < str.length(); j++) {
// 判断跟前面的是否重复
char n = str.charAt(j);
// 判断n是否在之前的序列里
boolean flag = strs.contains(n + "");
if (!flag) {
System.out.println(n + "属于以" + now + "开头的最长字串");
strs.add(n + "");
} else {
System.out.println(n + "不属于以" + now + "开头的最长字串");
break;
}
}
System.out.println("以" + now + "开通要的最长子序列为" + strs.toString());
if (strs.size() > maxLen) {
maxLen = strs.size();
maxStr = strs.toString();
}
strs.clear();
}
System.out.println(str + "的最长字串为" + maxStr + "长度为" + maxLen);
}
return maxLen;
}
/**
* 实现方式2:遍历每一个字符串,检查从当前字符串后的字符开始是否跟前面的字符串相同,若相同则不属于子串
* 否在属于子串,改为用map来存放是否在子串中,所以比第一种好一点,但是还是很慢
* 执行用时:执行用时:247 ms, 在所有 Java 提交中击败了5.74%的用户内存消耗:39 MB, 在所有 Java 提交中击败了17.15%的用户
* @param str
* @return
*/
public static int lengthOfLongestSubstring2(String str) {
// 用最傻的方法先实现,遍历每个字母开始的最长字串
int maxLen = 0;
// 定义一个数组来存贮从某一个字符开始的最长子串
Map<String,Boolean> map = new HashMap<String,Boolean>();
for (int i = 0; i < str.length(); i++) {
// 先获取第一个字符的最长字串
// 获取当前要判断的字符
char now = str.charAt(i);
//这里直接借助map来判断是否存在
map.put(now+"", true);
int len=1;
for (int j = i + 1; j < str.length(); j++) {
// 判断跟前面的是否重复
char n = str.charAt(j);
// 判断n是否在之前的序列里
if(map.get(n+"")!=null) {
System.out.println(n + "不属于以" + now + "开头的最长字串");
break;
} else {
System.out.println(n + "属于以" + now + "开头的最长字串");
map.put(n+"", true);
len++;
}
}
if (len > maxLen) {
maxLen =len;
}
System.out.println("以" + now + "开头的字符串maxlen="+maxLen);
map.clear();
}
return maxLen;
}
/**
* 实现方式3:遍历每一个字符串,检查从当前字符串后的字符开始是否跟前面的字符串相同,若相同则不属于子串
* 否在属于子串,改为用map来存放是否在子串中,并且如果判断当前字符不属于前一个子串,则字节从前一个冲突的子串的下一位开始判断,这样
* 就不用重复判断长度不可能大于当前子串的内容了,比如串“abcdefcg”,我们先判断以a开头的子串,当判断到“abcdefc”的时候,c跟前面的c
* 冲突,此时就没有必要判断b和第三个c开头的子串了,直接从d开始即可,节省时间。但还还是不够理想,才7.28%。
* 执行用时:164 ms, 在所有 Java 提交中击败了7.28%的用户内存消耗:39 MB, 在所有 Java 提交中击败了16.36%的用户
* @param str
* @return
*/
public static int lengthOfLongestSubstring3(String str) {
// 用最傻的方法先实现,遍历每个字母开始的最长字串
int maxLen = 0;
// 定义一个数组来存贮从某一个字符开始的最长子串
Map<String,Integer> map = new HashMap<String,Integer>();
int now_j=0;
for (int i = 0; i < str.length();) {
// 先获取第一个字符的最长字串
//获取i~now_j之间的字符串
String ss = str.substring(i, now_j+1);
int len=ss.length();
for (int j = 0; j <ss.length(); j++) {
map.put(ss.charAt(j)+"", i+j);
}
//冲突的下标
Integer n_index=now_j+1;
for (int j = now_j+1; j < str.length(); j++) {
// 判断跟前面的是否重复
char n = str.charAt(j);
// 判断n是否在之前的序列里
n_index = map.get(n+"");
now_j=j;
if(n_index!=null) {
//这里表示当前的j和n_index,那下一次循环就可以直接把n_index~j之间的内容
break;
} else {
n_index=j;
map.put(n+"", j);
len++;
}
}
if (len > maxLen) {
maxLen =len;
}
map.clear();
i=n_index+1;
}
return maxLen;
}
}
上面是我自己的解题方法,超过的人太少了,丢人!
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/median-of-two-sorted-arrays