一、无重复字符的最长子串
主体思路是采用滑动窗口法,也就是如果窗内不包含扫描到的某元素,那就把该元素加进窗内,并且长度加一,继续下一个元素的扫描判断,但如果窗内包含该元素,那就将窗内该元素删掉,(但只是删掉,index没变,所以下一轮扫描还是该元素)然后在下一轮while里面再加进来(相当于更新了一下重复元素的位置)
class Solution {
public int lengthOfLongestSubstring(String s) {
ArrayList<Character> window = new ArrayList<>();
int lens = s.length();
int max = 0,index = 0;
while(index < lens){
if(!window.contains(s.charAt(index))){
window.add(s.charAt(index));
index++;
max = Math.max(max,window.size());
}else{
window.remove(0);
}
}
return max;
}
}
一些小想法:如果要输出最长字串,可以在max赋值前判断这时的窗长window.size是不是max,如果是,新定义一个list用来存储窗里的数据,最后,输出这个list。
二、找到字符串中所有字母异位词
主题思路也是用一个滑动窗口,窗长为p的长度,然后依次向s的末尾滑动
public static List<Integer> findAnagrams(String s, String p) {
List<Integer> list = new ArrayList<>();
int index = 0,cnt = s.length();
while(index <= cnt-p.length()){
String sub = s.substring(index,index+p.length());
if(isAnagram(p,sub)){
list.add(index);
}
index++;
}
return list;
}
public static boolean isAnagram(String s, String t) {
int [] res = new int[26];
for(int i =0; i<s.length(); i++){
res[s.charAt(i)-'a']++;
}
for(int i =0; i<t.length(); i++){
res[t.charAt(i)-'a']--;
}
for(int i =0; i<res.length; i++){
if(res[i]!=0){
return false;
}
}
return true;
}
三、和为K的子数组
一开始的思路使用滑动窗口,判断条件是sum和目标k的大小 ,但是我发现滑动窗口仅限于整数,一旦涉及负数例如[-1,-1,1]这样的形式就会结果出现问题,在评论区看到要用前缀和的方法。
前缀和顾名思义也就是新建立一个数组,该数组的索引i代表前i个数字的和,也就是sum[i] = sum[i-1] + num[i-1] 。
回到本题,要求和为k的子数组,也就是满足sum[j] = sum[i] + k,那么为了方便思路(取大的然后往数组左边方向减),将该式写成sum[i] = sum[j] - k ;该式的含义是,当索引到i,这时前i个数据和为sum[i],而它与前j个数据和为sum[j]刚好差k的大小,也就意味着i和j之间的数据就是我们需要的子数组。但是题目要求要返回子数组的个数,所以再采用一个map集合,键存储sum[i],值存储它出现的次数。我一开始写的核心处理部分如下:
if(map.containsKey(sum - k)){
cnt = map.get(sum - k)+1;
map.put(sum - k, cnt);
}
map.put(sum, map.getOrDefault(sum, 0) + 1);
但是在处理类似于[1,2,1,2,1] 就会出现问题。发现问题在于:比如第一轮sum-k=0,然后满足if条件,于是cnt = value(0) +1;然后把cnt传给value(0)。(括号里面代表键值)下一轮sum-k=1,然后满足if条件,于是cnt = value(1) +1;然后把cnt传给value(1)。所以我们可以看到两轮都满足条件,但是第一轮cnt给的是value(0),第二轮cnt取的是的是value(1)加一,所以上一轮的结果没有给到下一轮,就出现了逻辑误区,代码重新更改为:
class Solution {
public int subarraySum(int[] nums, int k) {
Map<Integer, Integer> map = new HashMap<>();
map.put(0, 1);
int sum = 0,cnt = 0;
for(int j = 0; j < nums.length; j++ ) {
sum += nums[j];
if(map.containsKey(sum - k)){
cnt += map.get(sum - k);
}
map.put(sum, map.getOrDefault(sum, 0) + 1);
}
return cnt;
}
}
以上来自于力扣及评论区