双指针:
设置两个不同的指针 ,或者头,或者尾。在一个递增的序列中,
根据结果分类,说明指针的下一步应该怎么移动。
例:
给你 n 个非负整数 a1,a2,…,an,每个数代表坐标中的一个点 (i, ai) 。在坐标内画 n 条垂直线,垂直线 i 的两个端点分别为 (i, ai) 和 (i, 0) 。找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。
说明:你不能倾斜容器。
示例 1:
输入:[1,8,6,2,5,4,8,3,7]
输出:49
解释:图中垂直线代表输入数组 [1,8,6,2,5,4,8,3,7]。在此情况下,容器能够容纳水(表示为蓝色部分)的最大值为 49。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/container-with-most-water
解:
public class leetcode_11 {
public static void main(String[] args) {
int[] height = {4, 3, 2, 1, 4, 5};
int max = 0;
//普通遍历 容易超出时间限制
// for (int i = 0; i < height.length; i++) {
// for (int j = i + 1; j < height.length; j++) {
//
// max = Math.max(max, Math.min(height[i], height[j]) * (j - i));
//
// }
// }
int left = 0;
int right = height.length - 1;
//双指针
//两指针从两边出发 哪个短哪个往里面移动 比较这所有的结果
while (left < right) {
max = Math.max(max, Math.min(height[left], height[right]) * (right - left));
if (height[left] <= height[right]) {
left++;
} else {
right--;
}
}
System.out.println(max);
}
}
滑动窗口
双指针的一种情况、
滑动窗口算法是在给定特定窗口大小的数组或字符串上执行要求的操作。
简而言之,滑动窗口算法在一个特定大小的字符串或数组上进行操作,而不在整个字符串和数组上操作,这样就降低了问题的复杂度,从而也达到降低了循环的嵌套深度。其实这里就可以看出来滑动窗口主要应用在数组和字符串上。
滑动:说明这个窗口是移动的,也就是移动是按照一定方向来的。
窗口:窗口大小并不是固定的,可以不断扩容直到满足一定的条件;也可以不断缩小,直到找到一个满足条件的最小窗口;当然也可以是固定大小。
为了便于理解,这里采用的是字符串来讲解。但是对于数组其实也是一样的。滑动窗口算法的思路是这样:
我们在字符串 S 中使用双指针中的左右指针技巧,初始化 left = right = 0,把索引闭区间 [left, right] 称为一个「窗口」。
我们先不断地增加 right 指针扩大窗口 [left, right],直到窗口中的字符串符合要求(包含了 T 中的所有字符)。
此时,我们停止增加 right,转而不断增加 left 指针缩小窗口 [left, right],直到窗口中的字符串不再符合要求(不包含 T 中的所有字符了)。同时,每次增加 left,我们都要更新一轮结果。
重复第 2 和第 3 步,直到 right 到达字符串 S 的尽头。
例题:
给定一个字符串 s ,请你找出其中不含有重复字符的 最长子串 的长度。
示例 1:
输入: s = “abcabcbb”
输出: 3
解释: 因为无重复字符的最长子串是 “abc”,所以其长度为 3。
示例 2:
输入: s = “bbbbb”
输出: 1
解释: 因为无重复字符的最长子串是 “b”,所以其长度为 1。
示例 3:
输入: s = “pwwkew”
输出: 3
解释: 因为无重复字符的最长子串是 “wke”,所以其长度为 3。
请注意,你的答案必须是 子串 的长度,“pwke” 是一个子序列,不是子串。
示例 4:
输入: s = “”
输出: 0
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/longest-substring-without-repeating-characters
解:
public class leetcode_3 {
public static void main(String[] args) {
String s = "abcbcbc";
int len = 0;
int n = s.length();
int left = 0;
int right = 0;
//存set集合
HashSet window = new HashSet();
while (right < n) {
char a = s.charAt(right);
//containsKey 包含则为true
while (window.contains(a)) {
window.remove(s.charAt(left));
left++;
}
len = Math.max(len, right - left + 1);
window.add(a);
right++;
}
System.out.println(len);
}
}