leetcode刷题(八)

将x减到0的最小操作数
在这里插入图片描述

思路
  • 将x减到0的最小操作数
  • target=sum(nums)-x
  • windowSum<=target 扩大窗口 right++
  • windowSum>target 缩小窗口 left++
  • windowSum==target 更新结果值
public int minOperations(int[] nums, int x) {
    int left=0,right=0;
    int sum=0;
    for(int i:nums){
        sum+=i;
    }
    int windowTarget=sum-x,res=Integer.MIN_VALUE,windowSum=0;
    while (right<nums.length){
        windowSum+=nums[right];
        right++;
        while (windowSum>windowTarget){
            windowSum-=nums[left];
            left++;
        }
        if(windowSum==windowTarget){
            res=Math.max(res,right-left);
        }
    }
    return res==Integer.MIN_VALUE?-1:nums.length-res;
}

乘积小于k的子数组
在这里插入图片描述

思路
  • 乘积小于k的子数组
  • 窗口乘积windowMul
  • windowMul<k 扩大窗口 right++
  • windowMul>=k缩小窗口 left++
  • count+=right-left 更新结果值
public int numSubarrayProductLessThanK(int[] nums, int k) {
    int left=0,right=0,count=0;
    int windowMul=1;
    while (right<nums.length){
        windowMul*=nums[right];
        right++;
        while (left<right && windowMul>=k){
            windowMul/=nums[left];
            left++;
        }
        count+=right-left;
    }
    return count;
}

最大连续1的个数 III

思路
  • 最大连续1的个数 III
  • 窗口内0有windowZeroCount个
  • windowZeroCount<=k 扩大窗口 right++
  • windowZeroCount>k缩小窗口 left++
  • max_len=Math.max(max_len,right-left) 更新结果值
    在这里插入图片描述
public int longestOnes(int[] nums, int k) {
    int left=0,right=0,windowZeroCount=0;
    int max_len=0;
    while (right<nums.length){
        if(nums[right]==0)
            windowZeroCount++;
        right++;
        while (windowZeroCount>k){
            if(nums[left]==0){
                windowZeroCount--;
            }
            left++;
        }
        max_len=Math.max(max_len,right-left);
    }
    return max_len;
}

替换后的最长重复字符
在这里插入图片描述

思路
  • 替换后的最长重复字符
  • 对于A-Z的每个字符c,把非字符c的大写字符替换成c,窗口内只能替换k次
  • 套用最大连续1的个数 III
  • windowCharCount<=k 扩大窗口 right++
  • windowCharCount>k缩小窗口 left++
  • max_len=Math.max(max_len,right-left) 更新结果值
  • 最后得到最大的max_len值为算法输出
public int getRes(String s,int k,char c){
    int left=0,right=0,windowCharCount=0;
    int max_len=0;
    while (right<s.length()){
        if(s.charAt(right)==c){
            windowCharCount++;
        }
        right++;
        while (right-left-windowCharCount>k){
            if(s.charAt(left)==c){
                windowCharCount--;
            }
            left++;
        }
        max_len=Math.max(max_len,right-left);
    }
    return max_len;
}
public int characterReplacement(String s, int k) {
    int res=0;
    for(char c='A';c<='Z';c++){
        res=Math.max(res,getRes(s,k,c));
    }
    return res;
}

存在重复元素 II
在这里插入图片描述

思路
  • 存在重复元素 II
  • 哈希窗口window存储数组nums元素
  • 窗口内存在nums[right] 返回true
  • right-left<=k window.add(nums[right]) 扩大窗口 right++
  • right-left>k window.remove(nums[left]) 缩小窗口 left++
public boolean containsNearbyDuplicate(int[] nums, int k) {
    HashSet<Integer>window=new HashSet<>();
    int left=0,right=0;
    while (right<nums.length){
        if(window.contains(nums[right]))
            return true;
        window.add(nums[right]);
        right++;
        while (right-left>k){
            window.remove(nums[left]);
            left++;
        }
    }
    return false;
}

存在重复元素 III
在这里插入图片描述

思路
  • 存在重复元素 III
  • TreeSet(window)存储数组nums元素
  • 取出window中最接近nums[right]中的最大元素(ceiling)和最小元素(floor)
  • 如果两者存在,则判断它们各自与nums[right]的差值的绝对值是否不大于valueDiff,是则返回true
  • right-left<=indexDiff window.add(nums[right]) 扩大窗口 right++
  • right-left>indexDiff window.remove(nums[left]) 缩小窗口 left++
public boolean containsNearbyAlmostDuplicate(int[] nums, int indexDiff, int valueDiff) {
    int left=0,right=0;
    TreeSet<Integer>window=new TreeSet<>();
    while (right<nums.length){
        Integer ceiling=window.ceiling(nums[right]);
        if(ceiling!=null && ceiling-nums[right]<=valueDiff)
            return true;
        Integer floor=window.floor(nums[right]);
        if(floor!=null && nums[right]-floor<=valueDiff)
            return true;
        window.add(nums[right]);
        right++;
        while (right-left>indexDiff){
            window.remove(nums[left]);
            left++;
        }
    }
    return false;
}

至少有k个重复字符的最长子串
在这里插入图片描述

思路
  • 至少有k个重复字符的最长子串
  • 对于 a-z 26个字符的任意组合,可以出现的子串中各字符的组合种类有26种
  • 对于窗口内的子串需要满足的条件是:
    1. 字符种类为classes
    2. 每种字符最少出现k次
  • 当窗口字符种类数windowClassCount不大于classes时,扩大窗口,right++
  • 当窗口字符种类数windowClassCount大于classes时,缩小窗口,left++
  • 使用变量windowValidCount记录窗口内有多少个字符出现次数至少为k次
  • 如果窗口内的子串满足条件1、2(windowValidCount==classes),则更新最大长度max_len=Math.max(max_len,right-left)
public int getMaxLen(String s,int k,int classes){
    int left=0,right=0,max_len=0;
    int windowClassCount=0,windowValidCount=0;
    int[]window=new int[26];
    while (right<s.length()){
        char c=s.charAt(right);
        if(window[c-'a']==0)
            windowClassCount++;
        window[c-'a']++;
        if(window[c-'a']==k)
            windowValidCount++;
        right++;
        while (windowClassCount>classes){
            char d=s.charAt(left);
            if(window[d-'a']==k)
                windowValidCount--;
            window[d-'a']--;
            if(window[d-'a']==0)
                windowClassCount--;
            left++;
        }
        if(windowValidCount==classes)
            max_len=Math.max(max_len,right-left);
    }
    return max_len;
}
public int longestSubstring(String s, int k) {
    int res=0;
    for(int i=1;i<=26;i++){
        res=Math.max(res,getMaxLen(s,k,i));
    }
    return res;
}
  • 26
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值