思路: 连续 最大 长度 要想起滑动窗口
可以去看下这个up讲滑动窗口的视频,我就是看了他讲的,讲的很不错:滑动窗口【基础算法精讲 03】_哔哩哔哩_bilibili
3. 无重复字符的最长子串 - 力扣(LeetCode)
public int lengthOfLongestSubstring(String s) {
int n = s.length();
//左指针
int left = 0;
//最长子串的长度
int maxLen = 0;
//定义map存放[left,right]区间中各个字符出现的个数
HashMap<Character, Integer> map = new HashMap<>();
for (int right = 0; right < n; right++) {
//右指针指向的字符
char rightChar = s.charAt(right);
//存到map中,该字符出现的次数加1
map.put(rightChar, map.getOrDefault(rightChar, 0) + 1);
//map.get(rightChar) > 1 表示右字符在前面接上的字符串中已经出现过,
//此时需要移动左指针
while (map.get(rightChar) > 1){
//左指针指向的字符
char leftChar = s.charAt(left);
//将左指针指向的字符在map中的个数减1
map.put(leftChar, map.get(leftChar) - 1);
//同时左指针左移一个单位
left++;
}
//上述while之后,得到的[left,right]区间中的字符串是不重复的
maxLen = Math.max(maxLen, right - left + 1);
}
return maxLen;
}
209. 长度最小的子数组 - 力扣(LeetCode)
public int minSubArrayLen20241016(int target, int[] nums) {
int n = nums.length;
int minLen = Integer.MAX_VALUE;
int sum = 0;
int left = 0;
for (int right = 0; right < n; right ++){
//加入当前right值到sum中
sum += nums[right];
//若此时sum大于target,则向右移动左指针尝试找到长度最小的总和大于等于target的子数组
while (sum >= target){
minLen = Math.min(minLen, right - left + 1);
sum -= nums[left];
left ++;
}
}
return minLen == Integer.MAX_VALUE ? 0 : minLen;
}
713. 乘积小于 K 的子数组 - 力扣(LeetCode)
public int numSubarrayProductLessThanK(int[] nums, int k) {
if (k <= 1) return 0;
int n = nums.length;
//左指针
int left = 0;
//乘积初始化时要为1而不是0
int sum = 1;
//符合要求的数组个数
int cnt = 0;
for (int right = 0; right < n; right++) {
sum *= nums[right];
//当乘积大于等于k时,左指针右移,直到符合要求(乘积小于k)
while (sum >= k){
//当不符合要求时,左指针右移
sum /= nums[left];
left++;
}
//当右节点为right,此时符合要求的数组个数如下式
cnt += right - left + 1;
}
return cnt;
}
题目(华为可信科目二):一队士兵排成一排,身穿绿色跟黑色衣服,如果可以随便将一个士兵移除队伍,那么求最长的连续绿色衣服的士兵队伍长度,示例:绿色表示1,黑色表示0
输入:10111
输出: 4
表示移出第二个位置的黑色士兵,最大连续长度为4.
public static int longestOnes(int[] nums){
int n = nums.length;
int cnt0 = 0; //表示滑动窗口里的0的个数
int max1 = 0; //表示最大连续1的个数
int left = 0; //左指针
//最长可翻转1 也就是变成了求滑动窗口内0的数量小于等于1时最大滑动窗口大小
for (int right = 0; right < n; right++) {
int rNum = nums[right];
if (rNum == 0) cnt0 ++;
//当cnt0 滑动窗口左移
while (cnt0 > 1){
int lNum = nums[left];
if (lNum == 0) cnt0 --;
left ++;
}
max1 = Math.max(max1, right - left + 1);
}
return cnt0 == 1 ? max1 - 1 : max1;
}
1004. 最大连续1的个数 III - 力扣(LeetCode)
思路:转换为求滑动窗口内0的个数小于等于k时,滑动窗口的最大长度
public int longestOnes(int[] nums, int k) {
//思路 转换成当cnt0 <= k时,滑动窗口长度最大值
int n = nums.length;
int cnt0 = 0; //表示当前滑动窗口内0的个数
int maxlen = 0; //表示当前最长的滑动窗口
int left = 0;
for (int right = 0; right < n; right ++){
int rNum = nums[right];
if (rNum == 0) cnt0 ++;
//若前面操作使得cnt0 > k,则需要让left右移,直到cnt0 <= k
while (cnt0 > k){
int lNum = nums[left];
if (lNum == 0) cnt0 --;
left ++;
}
//经上面操作后 cnt0 <= k
//判断是否更新maxlen。 right - left + 1为当前滑动窗口大小与max1比较,取最大值
maxlen = Math.max(maxlen, right - left + 1);
}
return maxlen;
}
134. 加油站 - 力扣(LeetCode)
思路:目的 找到以left开始 长度为n的滑动窗口即是正确的流程,用rest来表示剩余油量
public int canCompleteCircuit(int[] gas, int[] cost) {
int n = gas.length;
int rest = 0; //表示剩余汽油量
int left = 0; //左指针
//目的 找到以left开始 长度为n的滑动窗口即是正确的流程
for (int right = 0; right - left < n; right ++){
rest += gas[right % n] - cost[right % n]; //因为right可能回调 从 4调到1
//若当前滑动窗口 剩余油量小于0说明 不能以该left为起点 让left右移
while (rest < 0 && left < n){
rest -= gas[left] - cost[left];
left ++;
}
}
return rest >= 0 ? left : - 1;
}
题目描述: 给你一个字符串,只包含大写字母,求同一字母连续出现的最大次数。
例如”AAAABBCDHHH”,同一字母连续出现的最大次数为4,因为一开始A连续出现了4次。
ADDDDBDDDCAAAAAAA 7
这是本人一面手撕代码原题
public static int maxLX(String s){
int n = s.length();
int max = 0;
int left = 0;
char win = s.charAt(0); //初始 将滑动窗口内的字符设置为最左边的字符
for (int right = 0; right < n; right++) {
char rChar = s.charAt(right);
while (rChar != win){ //若右字符与滑动窗口内字符不一致
char lChar = s.charAt(left);
if (lChar == win) left ++; //若当前左指针指向的字符和win相同 则让左指针右移
else { //否则更新滑动窗口字符以及左指针位置
win = rChar;
left = right;
}
}
max = Math.max(right - left + 1, max);
}
return max;
}
题目(华为可信科目二):一串字符串由"1-10"“A-Z"组成,各字符之间由”"隔开,找到最大连续的子串。(10后面的字符是A)
输入:1,2,3,4,5,7,8 输出1 2 3 4 5
这题,我做了挺久但苦于没有输入输出用例,所以想着如果遇到了就换题