一些算法日常题

这篇博客介绍了如何使用双指针和滑动窗口算法解决LeetCode上的几道经典问题,包括有序数组的平方、轮转数组以及寻找最短子数组。解法一和解法二分别展示了不同的实现策略,强调了在不同场景下如何灵活运用这两种技巧。此外,还提及了滑动窗口在寻找最长和最短子数组问题中的应用,以及在存在重复元素II和字符串排列问题中的解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.双指针 

977. 有序数组的平方 - 力扣(LeetCode)

类型:双指针、数组

解法一: 

思路:

class Solution {
    public int[] sortedSquares(int[] nums) {
        int neg = -1;
        int len = nums.length;
        for (int i = 0; i < len; i++) {
            if(nums[i]<0){
                neg = i;
            }else{
                break;
            }
        }
        int[] array = new int[len];
        int index = 0;
        int i = neg;    int j = neg+1;
        while(i>=0||j<len){
            if(i<0){//原数组里面全部都为正数,或者已经把原数组里面的负数都遍历完了
                array[index] = (int)Math.pow(nums[j],2);
                j++;
            }else if(j==len){//原数组里面全部都为负数,或者已经把原数组里面的正数都遍历完了
                array[index] = (int)Math.pow(nums[i],2);
                i--;
            }else{//原数组中既有负数又有正数
                array[index] = Math.max((int)Math.pow(nums[j],2),(int)Math.pow(nums[i],2)) ==(int)Math.pow(nums[j],2)
                        ?(int)Math.pow(nums[i--],2):(int)Math.pow(nums[j++],2);
            }
            index++;
        }
        return array;
    }
}
public class TestDemo {
    public static void main(String[] args) {
        Solution solution = new Solution();
        int[] array = new int[]{-5,-3,-2,-1,0,3,5,10};
        System.out.println(Arrays.toString(solution.sortedSquares(array)));
    }
}

 

解法二:

思路

class Solution {
    public int[] sortedSquares(int[] nums) {
        int[] ans = new int[nums.length];
        int pos = nums.length-1;
        for (int i = 0, j = nums.length-1; i <=j ;) {
            if((int)Math.pow(nums[i],2)>(int)Math.pow(nums[j],2)){
                ans[pos--] = (int)Math.pow(nums[i++],2);
            }else{
                ans[pos--] = (int)Math.pow(nums[j--],2);
            }
        }
        return ans;
    }
}
public class TestDemo {
    public static void main(String[] args) {
        Solution solution = new Solution();
        int[] array = new int[]{-5,-3,-2,-1,0,3,5,10};
        System.out.println(Arrays.toString(solution.sortedSquares(array)));
    }
}

 189. 轮转数组 - 力扣(LeetCode)

类型:数组、双指针

解法一:

思路:

class Solution {
    public void rotate(int[] nums, int k) {
        int n = nums.length;
        int[] ans = new int[n];
        for(int i = 0;i<n;i++){
            ans[(i+k)%n] = nums[i];
        }
        System.arraycopy(ans,0,nums,0,n);
    }
}
public class TestDemo {
    public static void main(String[] args) {
        Solution solution = new Solution();
        int[] array = new int[]{1,2,3,4,5,6,7};
        solution.rotate(array,8);
        System.out.println(Arrays.toString(array));
    }
}

 

 解法二:

思路:

class Solution {
    public void rotate(int[] nums, int k) {
        int n = nums.length;
        k%=n;
        if(k==0)return;
        turn(nums,0,n-1);
        turn(nums,0,k-1);
        turn(nums,k,n-1);
    }
    public void turn(int[] array,int left,int right){
        while(left<=right){
            int temp = array[left];
            array[left++] = array[right];
            array[right--] = temp;
        }
    }
}
public class TestDemo {
    public static void main(String[] args) {
        Solution solution = new Solution();
        int[] array = new int[]{1,2,3,4,5,6,7};
        solution.rotate(array,3);
        System.out.println(Arrays.toString(array));
    }
}

 2.滑动窗口 

滑动窗口解题思路:

(1)题型:寻找最长...

核心:左右双指针(L,R)在起始位置,R向右逐位滑动循环。

每次滑动过程中如果窗内元素满足条件,R向右扩大窗口,并更新最优结果;如果窗内元素不满足条件,L向右缩小窗口。

代码模板:

初始化left、right、result、bestResult
while(右指针没有达到结束条件){
    窗口扩大,加入right对应元素,更新当前result
    while(result不满足要求){
        窗口缩小,移除left对应元素,left右移
    }
    更新最优结果bestResult
    right++;
}
返回beatResult;

 (2)题型:寻找最短...

核心:左右双指针(L,R)在起始位置,R向右逐位滑动循环。

每次滑动过程中如果窗内元素满足条件,L向右缩小窗口,并更新最优结果;如果窗内元素不满足条件,R向右扩大窗口。

 代码模板

初始化left、right、result、beatResult
while(右指针没有达到结束条件){
    窗口扩大,加入right对应元素,更新当前result
    while(result满足要求){
        更新最优结果bestResult
        窗口缩小,移除left对应元素,left右移
    }
    right++;
}
返回bestResult;


209. 长度最小的子数组 - 力扣(LeetCode)

类型:滑动窗口

思路:

class Solution {
    public int minSubArrayLen(int target, int[] nums) {
        int i = 0;
        int j = 0;
        int minLength = 0;
        int curSum = 0;
        while(j<nums.length){
            curSum +=nums[j];
            while(curSum>=target){
                if(j-i+1<minLength||minLength==0){
                    minLength = j-i+1;
                }
                curSum-=nums[i++];
            }
            j++; 
        }
        return minLength;
    }
}

存在重复元素 II - 存在重复元素 II - 力扣(LeetCode)

类型滑动窗口、哈希表

 解法一:

思路:

1.创建一个Set集合,用来存储数组中的数据,同时创建两个指针i、j

2.判断j-i的差值length与K的大小关系,若length>k,则将集合中下标为i处的元素删除,同时i右移。若不大于,则让j右移,右移之前先判断集合中是否存在j处下标的元素,若存在则返回true,不存在则将j处下表的元素加入集合中。

3.当j大于等于数组的长度时,返回false。

class Solution {
    public boolean containsNearbyDuplicate(int[] nums, int k) {
        int i = 0,j = 0,abslen = 0;
        Set<Integer> set = new HashSet<>();
        while(j<nums.length){
            abslen = j-i;
            if(abslen>k){
                set.remove(nums[i]);
                i++;
            }
            if(!set.add(nums[j])){
                return true;
            }
            j++;
        }
        return false;
    }
}

解法二:

思路:

1.创建一个哈希表,利用哈希表中的key-value键值对分别存放数组中的元素和数组下标,比如现在有一个数组为【1,2,3,1】则存储到哈希表中就应该是这样

 2.遍历数组,判断哈希表中是否包含与i处位置的元素,包含且i减去该元素所对应的下标小于等于k时就返回true,即map.containsKey(nums[i]&&i-map.get(nums[i])).当不满住条件时将下标i处的数据记录到哈希表中

class Solution {
    public boolean containsNearbyDuplicate(int[] nums, int k) {
        Map<Integer,Integer> map = new HashMap<>();
        for(int i = 0;i<nums.length;i++){
            int num = nums[i];
            if(map.containsKey(num)&&i-map.get(num)<=k){
                return true;
            }
            map.put(num,i);
        }
        return false;
    }
}

567. 字符串的排列 - 力扣(LeetCode)

思路:

class Solutions {
    public boolean checkInclusion(String s1, String s2) {
        int n = s1.length(),m = s2.length();
        if(n>m)return false;
        int[] arr1 = new int[26];
        int[] arr2 = new int[26];
        for (int i = 0; i < n; i++) {
            ++arr1[s1.charAt(i)-'a'];
            ++arr2[s2.charAt(i)-'a'];
        }
        if(Arrays.equals(arr1,arr2))return true;
        for (int i = n; i < m; i++) {
            ++arr2[s2.charAt(i)-'a'];
            --arr2[s2.charAt(i-n)-'a'];
            if(Arrays.equals(arr1,arr2))return true;
        }
        return false;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

咸鱼吐泡泡

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值