
思路:窗口内为无重复字符子串,使用哈希表来保存最新碰到的字符下标,只要出现重复就缩小left指针,缩小到无重复字符也就是map.get(c)+1
- class Solution {
- public int lengthOfLongestSubstring(String s) {
- HashMap
map = new HashMap(); - int l = 0;
- int r = 0;
- int len = s.length();
- int res = 0;
- while(r
- char c = s.charAt(r);
- if(map.get(c) != null){
- l = Math.max(l,map.get(c) + 1);
- }
- map.put(c,r);
- res = Math.max(r-l+1,res);
- r++;
- }
- return res;
- }
- }
(2)至多包含两个不同字符的最长子串

思路:窗口为两个以内的不同字符,使用哈希表来保存最新碰到的字符下标,和上一题不同的是这里需要关注哈希表的size,如果超过2代表窗口内有两个以上不同的字符了,需要更新left指针位置为记录的窗口内最小的位置,并移除
- public static int lengthOfLongestSubstringTwoDistinct(String s) {
-
- if (s.length() < 3) {
- return s.length();
- }
- int left = 0, right = 0;
- HashMap
hashmap = new HashMap<>(); - int maxLen = 2;
-
- while (right < s.length()) {
-
- if (hashmap.size() < 3)
- hashmap.put(s.charAt(right), right++);
-
- // 如果大小达到了3个
- if (hashmap.size() == 3) {
- // 最左侧要删除的位置
- int del_idx = Collections.min(hashmap.values());
- hashmap.remove(s.charAt(del_idx));
- // 窗口left的新位置
- left = del_idx + 1;
- }
-
- maxLen = Math.max(maxLen, right - left);
- }
- return maxLen;
- }
(3)至多包含k个不同字符的最长子串
题目:给定一个字符串 s,找出 至多 包含 k 个不同字符的最长子串T
思路:只需要将上一题的3改成k,完美移植
- public static int lengthOfLongestSubstringKDistinct(String s, int k) {
- if (s.length() < k + 1) {
- return s.length();
- }
-
- int left = 0, right = 0;
- HashMap
hashmap = new HashMap<>(); - int maxLen = k;
-
- while (right < s.length()) {
-
- if (hashmap.size() < k + 1)
- hashmap.put(s.charAt(right), right++);
-
- // 如果大小达到了k个
- if (hashmap.size() == k + 1) {
- //
- int del_idx = Collections.min(hashmap.values());
- hashmap.remove(s.charAt(del_idx));
- // 窗口left的新位置
- left = del_idx + 1;
- }
-
- maxLen = Math.max(maxLen, right - left);
- }
- return maxLen;
- }
2. 长度最小的子数组

思路:当小于target时就不断扩大窗口,当大于等于target的时候就从l开始不断剔除元素
- class Solution {
- public int minSubArrayLen(int target, int[] nums) {
- int l = 0;
- int r = 0;
- int sum = 0;
- int min = Integer.MAX_VALUE;
- while(r
- sum += nums[r];
- while(sum>=target){
- min = Math.min(min,r-l+1);
- sum -= nums[l++];
- }
- r++;
- }
- return min!=Integer.MAX_VALUE ? min : 0;
- }
- }
3.盛水最多的容器


思路:这题和上面不同的地方在于,不是双指针从头开始慢慢增大窗口,而是从首尾开始缩小窗口
长板不动,因为长板往内移动是一定会变小容量的
短板内移,可能变大也可能变小还可能不变,遍历一遍取最大
- class Solution {
- public int maxArea(int[] height) {
- int left = 0;
- int right = height.length-1;
- int low = Math.min(height[left],height[right]);
- int ability = 0;
- while(right > left){
- if(height[left]
- ability = Math.max(ability,(right-left)*height[left]);
- left++;
- }else{
- ability = Math.max(ability,(right-left)*height[right]);
- right--;
- }
- }
- return ability;
- }
- }
4.寻找子串异位词
1)字符串的排列

思路:窗口为子串大小,从s1的位置为初始窗口位置开始遍历,看看s2窗口内是不是与s1相等的
- class Solution {
- public boolean checkInclusion(String s1, String s2) {
- if(s1.length()>s2.length()){
- return false;
- }
- char[] c1 = new char[26];
- char[] c2 = new char[26];
- int left = 0;
- int right = s1.length();
- for(int i = 0;i
- c1[s1.charAt(i)-'a']++;
- c2[s2.charAt(i)-'a']++;
- }
- if(Arrays.equals(c2,c1)){
- return true;
- }
- for(;right
- c2[s2.charAt(right)-'a']++;
- c2[s2.charAt(left)-'a']--;
- left++;
- if(Arrays.equals(c2,c1)){
- return true;
- }
- }
- return false;
-
- }
- }
2)找到字符串中所有字母异位词

思路:和上一题差不多,窗口为子串大小,从子串大小位置为初始窗口位置开始遍历
- class Solution {
- public List
findAnagrams(String s, String p) { - if(s.length()
- return new ArrayList<>();
- }
- char[] c1 = new char[26];
- char[] c2 = new char[26];
- int left = 0;
- int right = p.length();
- for(int i = 0;i
- c1[p.charAt(i)-'a']++;
- c2[s.charAt(i)-'a']++;
- }
- List
list = new ArrayList<>(); - if(Arrays.equals(c2,c1)){
- list.add(0);
- }
- while(right
- c2[s.charAt(right)-'a']++;
- c2[s.charAt(left)-'a']--;
- left++;
- if(Arrays.equals(c2,c1)){
- list.add(left);
- }
- right++;
- }
- return list;
- }
- }
-
相关阅读:
小程序中的权限设计
基于 golang 从零到一实现时间轮算法 (三)
java毕业设计员工绩效考核系统分析与设计Mybatis+系统+数据库+调试部署
ScheduledThreadPoolExecutor 类
C语言:两个数的交换函数
Linux内核完全注释(基于Linux0.11)_笔记_Linux0.11执行流程
Happy 1024
通知可以根据切入点表达式来进行增强,也可以根据自己的注解值来进行增强
如何在WPF网格中隐藏行
4. git 添加版本标签
-
原文地址:https://blog.csdn.net/Candy___i/article/details/133236749