/**
* 无重复字符的最长子串
* 字符存储到set集合,如果有重复的直接之前的从set集合移除,加进来新的字符
*/
import java.util.HashSet;
import java.util.Set;
/**
* 思路:滑动窗口
* 以(a)bcabcbb 开始的最长字符串为 (abc)abcbb;
* 以a(b)cabcbb 开始的最长字符串为 a(bca)bcbb;
* 以ab(c)abcbb 开始的最长字符串为 ab(cab)cbb;
* 以abc(a)bcbb 开始的最长字符串为 abc(abc)bb;
* 以abca(b)cbb 开始的最长字符串为 abca(bc)bb;
* 以abcab(c)bb 开始的最长字符串为 abcab(cb)b;
* 以abcabc(b)b 开始的最长字符串为 abcabc(b)b;
* 以abcabcb(b) 开始的最长字符串为 abcabcb(b).
* 此时观察,我们需要边加入字符边移除字符。将字符逐个存入set集合,如果后面的元素有重复出现的字符,则set集合元素出集合直到无此重复元素,再将此元素入set集合
*/
public class Num48_无重复字符的最长子串 {
public int lengthOfLongestSubstring(String s) {
int max=0;
int right=0;
Set<Character> set = new HashSet<>();
for (int left = 0; left < s.length(); left++) {
//左指针向后遍历,移除left的前一个元素
if(left!=0){
set.remove(s.charAt(left-1));
}
//左指针定住,右指针向后走,元素不但放入set集合,直到遇到与set中元素重复或走到空记录长度
while (right<s.length()&&(!set.contains(s.charAt(right)))){
set.add(s.charAt(right));
right++;
}
max=Math.max(max,right-left);
}
return max;
}
}
/**
* 滑动窗口(本题是连续正数序列12345...,实际任意递增序列都能适用)
*/
public class Num57_II_和为s的连续正数序列 {
public static int[][] findContinuousSequence(int target) {
int left=1;//滑动窗口左边界
int right=1;//滑动窗口右边界
int sum=0;
List<int[]> ret = new ArrayList<>();
while (left<=target/2){//5最大只能是2+3不能是3+4,取到target的一半即可,因为顺序,3及后面的大数不可能组成5,左边界无需取到>target/2的数
if(sum<target){
sum+=right;
right++;
}else if(sum>target){
sum-=left;
left++;
}else {
int[] temp=new int[right-left];//不能取到right,因为sum等于+=right完了等于目标值后right还会++一次
for (int i = left; i < right; i++) {
temp[i-left]=i;
}
ret.add(temp);
//遍历完继续左边界右移,去掉左边移除都元素的值
sum-=left;
left++;
}
}
return ret.toArray(new int[ret.size()][]);//链表转化为数组
}
public static void main(String[] args) {
findContinuousSequence(5);
}
}