解题:
public List<List<Integer>> threeSum(int[] nums) {
// 排序
Arrays.sort(nums);
ArrayList<List<Integer>> ans = new ArrayList<>();
// 双指针
for (int i = 0; i < nums.length; i++) {
// 满足条件提前结束
if (nums[i]>0) break;
if (i!=0&&nums[i]==nums[i-1]){
continue;
}
int L = i+1;
int R = nums.length-1;
while (L<R){
int sum = nums[i]+nums[L]+nums[R];
if (sum == 0 ){
ans.add(Arrays.asList(new Integer[]{
nums[i],nums[L],nums[R]}));
while (L<R && nums[L]==nums[++L]){
} //去重
while (L<R && nums[R]==nums[--R]){
} //去重
}else if(sum<0){
while (L<R && nums[L]==nums[++L]){
}
}else {
while (L<R && nums[R]==nums[--R]){
}
}
}
}
return ans;
}
参考:
- 常用的双指针技巧
public String minWindow(String s, String t){
//目标计数
HashMap<Character, Integer> target = new HashMap<>();
//目标统计
……
//滑动框内计数
HashMap<Character, Integer> window = new HashMap<>();
// 左右指针,左闭右开
int L = 0, R = 0;
while (R < s.length()){
// 移入的元素
Character cr = s.charAt(R);
// 增大窗口
R++;
// 窗口内数据更新
……
// 只要窗口满足条件,就收缩
while(窗口满足条件){
//更新结果
……
// 移出左边的元素
Character cl = s.charAt(L);
//缩小窗口,L++;
L++;
// 窗口内数据更新
……
}
}
return 结果
}
完整代码
public String minWindow(String s, String t){
//目标计数
HashMap<Character, Integer> target = new HashMap<>();
//目标统计
for(Character c:t.toCharArray()){
target.put(c,target.getOrDefault(c,0)+1);
}
//滑动框内计数
HashMap<Character, Integer> window = new HashMap<>();
// 左右指针,左闭右开
int L = 0, R = 0;
// 达成目标个数累计(如果==target.size()表示window框包含所有目标中内容)
int cnt=0;
// 记录最小覆盖子串起始索引、长度
int start = 0,res_len = Integer.MAX_VALUE;
while (R < s.length()){
// 移入的元素
Character cr = s.charAt(R);
// 增大窗口
R++;
// 判断移入的元素是否是target中元素
if(target.containsKey(cr)){
//增加window对应元素数量,注意window中可能没有cr Key,所以用getOrDefault
window.put(cr,window.getOrDefault(cr,0)+1);
// 加入元素可能使窗口接近目标,增加cnt计数
if (window.get(cr).equals(target.get(cr))) cnt++;
}
// 只要窗口满足条件,就收缩
while(cnt == target.size()){
//更新结果
if (R-L <res_len){
start = L;
res_len = R-L;
}
// 移出左边的元素
Character cl = s.charAt(L);
//缩小窗口,L++;
L++;
// 判断移出的元素是否和t中相同
if(target.containsKey(cl)){
// 移出元素可能使窗口不满足条件
if (window.get(cl).equals(target.get(cl))) cnt--;
//减小window对应元素数量
window.put(cl,window.get(cl)-1);
}
}
}
return res_len==Integer.MAX_VALUE?"":s.substring(start,start+res_len);
}
参考:labuladong的算法小抄
public boolean checkInclusion(String s1, String s2) {
HashMap<Character, Integer> target = new HashMap<>();
for (Character c : s1.toCharArray()){
target.put(c,target.getOrDefault(c,0)+1);
}
HashMap<Character, Integer> window = new HashMap<>();
int L=0,R=0;
int cnt = 0;
while (R <s2.length()){
Character cr = s2.charAt(R);
R++;
// 进⾏窗⼝内数据的⼀系列更新
if (target.containsKey(cr)){
window.put(cr,window.getOrDefault(cr,0)+1);
if (window.get(cr).equals(target.get(cr))) cnt++;
}
// 判断左侧窗⼝是否要收缩
while (R - L >=s1.length()){
// 在这⾥判断是否找到了合法的⼦串
if (cnt == target.size()) return true;
Character cl = s2.charAt(L);
L++;
// 进⾏窗⼝内数据的⼀系列更新
if (target.containsKey(cl)){
if (window.get(cl).equals(target.get(cl))) cnt--;
window.put(cl,window.get(cl)-1);
}
}
}
// 未找到符合条件的⼦串
return false;
}
public List<Integer> findAnagrams(String s, String p){
HashMap<Character, Integer> target = new HashMap<>();
for(Character c:p.toCharArray()){
target.put(c,target.getOrDefault(c,0)+1);
}
HashMap<Character, Integer> window = new HashMap<>();
ArrayList<Integer> res = new ArrayList<>();
int L=0,R=0;
int cnt=0;
while (R <s.length()){
Character cr = s.charAt(R);
R++;
if (target.containsKey(cr)){
window.put(cr,window.getOrDefault(cr,0)+1);
if (window.get(cr).equals(target.get(cr))) cnt++;
}
// 判断左侧窗⼝是否要收缩
while (R-L >= p.length() ){
Character cl = s.charAt(L);
if (cnt == target.size()){
res.add(L);
}
L++;
if (target.containsKey(cl)){
if (window.get(cl).equals(target.get(cl))) cnt--;
window.put(cl,window.get(cl)-1);
}
}
}
return res;
}
// 滑动窗口 11ms
public int lengthOfLongestSubstring(String s){
HashMap<Character, Integer> map = new HashMap<>();
int L = 0,R = 0 ;
int res = Integer.MIN_VALUE;
while (R < s.length()){
Character cr = s.charAt(R);
R++;
map.put(cr,map.getOrDefault(cr,0)+1);
// 当 map.get(cr) 值⼤于 1 时,说明窗⼝中存在重复字符,不符合条件,就该L++缩⼩窗⼝
while (map.get(cr)>1){
Character cl = s.charAt(L);
L++;
map.put(cl,map.get(cl)-1);
}
// 更新无重复的 最长字串
if (R - L >res ) res = R-L;
}
return res==Integer.MIN_VALUE?0:res;
}