2023.3.30代码随想录二刷——移除元素系列、长度最小的子数组系列

本文介绍了几个基于数组的算法问题,包括如何原地移动数组中的零到末尾,比较含退格的字符串是否相等,有序数组的平方以及找到和大于等于目标值的最小子数组的长度。这些问题都采用了双指针或滑动窗口的策略来解决。

3.30代码随想录二刷——移除元素系列、长度最小的子数组系列

移除元素

283.移动零

给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。

请注意 ,必须在不复制数组的情况下原地对数组进行操作。

示例 1:

输入: nums = [0,1,0,3,12]
输出: [1,3,12,0,0]

示例 2:

输入: nums = [0]
输出: [0]
思路

用双指针i,j,i遍历原数组,遇到非零元素。

j遍历有效数组,将i非零的元素补进来

剩下的补0

题解
class Solution {
    public void moveZeroes(int[] nums) {
        if (nums.length == 0) {
            return;
        }
        //第一次遍历,j指针记录非0的个数,只要是非0的统统都赋给nums[j]
        int j = 0;
        for (int i = 0; i < nums.length; i++) {
            if (nums[i] != 0){
                nums[j] = nums[i];
                j++;
            }            
        }
        //非0元素统计完了,剩下的都赋0即可
        for (int i = j; i < nums.length; i++) {
            nums[i] = 0;
        }
    }
}

844.比较含退格的字符串

给定 st 两个字符串,当它们分别被输入到空白的文本编辑器后,如果两者相等,返回 true# 代表退格字符。

**注意:**如果对空文本输入退格字符,文本继续为空。

示例 1:

输入:s = "ab#c", t = "ad#c"
输出:true
解释:s 和 t 都会变成 "ac"。

示例 2:

输入:s = "ab##", t = "c#d#"
输出:true
解释:s 和 t 都会变成 ""。

示例 3:

输入:s = "a#c", t = "b"
输出:false
解释:s 会变成 "c",但 t 仍然是 "b"。
思路

用双指针i,j来遍历两字符串,同时sSkipNum、tSkipNum记录两个字符串的"#",遇到时++,没遇到时,如果其值>0 则进行–,当该值<0,则跳出对于s,t的模拟消除过程。最后比对两字符串各元素

题解
class Solution {
    public boolean backspaceCompare(String s, String t) {
        //844比较含退格的字符串
        //由后向前遍历,记录#的数量,模拟消除的操作,如果#用完了,就开始比较S[i]和t[j]
        int i = s.length() - 1;
        int j = t.length() - 1;
        int sSkipNum = 0;//记录S中#的数量
        int tSkipNum = 0;//记录t中#的数量
        while (true){
            //先统计,并模拟消除
            while (i >= 0){
                if (s.charAt(i) == '#'){
                    sSkipNum++;
                }else {
                    if (sSkipNum > 0){
                        sSkipNum--;
                    }else {
                        break;
                    }
                }
                i--;
            }
            while (j >= 0){
                if (t.charAt(j) == '#'){
                    tSkipNum++;
                }else {
                    if (tSkipNum > 0){
                        tSkipNum--;
                    }else {
                        break;
                    }
                }
                j--;
            }
            //再比对,比较s[i] 和  t[j]
            if(i < 0 || j < 0){
                break;//S或者T遍历到头
            }
            if(s.charAt(i) != t.charAt(j)){
                return false;

            }
            i--;
            j--;
        }
        //说明S,T同时遍历完毕
        if (i == -1 && j == -1){
            return true;
        }
        return false;
    }
}

977.有序数组的平方

给你一个按 非递减顺序 排序的整数数组 nums,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。

示例 1:

输入:nums = [-4,-1,0,3,10]
输出:[0,1,9,16,100]
解释:平方后,数组变为 [16,1,0,9,100]
排序后,数组变为 [0,1,9,16,100]

示例 2:

输入:nums = [-7,-3,2,3,11]
输出:[4,9,9,49,121]
思路

方法一:直接平方, 排序

方法二:利用 最大值总会在两端,双指针ij,对两边界比较,取最大值,填入新数组终止位置。

题解
public class SortedSquares {
    public int[] sortedSquares(int[] nums) {
        //977.有序数组的平方
        //第一种方法:平方后直接排序
//        for (int i = 0; i < nums.length; i++) {
//            nums[i] = nums[i] * nums[i];
//        }
//
//        Arrays.sort(nums);
        //第二种方法:双指针
        //再新建一个数组res
        int[] res = new int[nums.length];
        int k = nums.length - 1;
        //平方后,数组的最大值一定会是在两端,不会在中间,所以用ij双指针遍历比较nums,用k表res终止位置依次填入最大值
        for (int i = 0,j = nums.length - 1; i <= j ; ) {
            if (nums[i] * nums[i] > nums[j] * nums[j]) {
                res[k] = nums[i] * nums[i];
                k--;
                i++;
            }else {
                res[k] = nums[j] * nums[j];
                k--;
                j--;
            }

        }
        return res;

    }
}

长度最小的子数组

209.长度最小的子数组

给定一个含有 n 个正整数的数组和一个正整数 target

找出该数组中满足其和 ≥ target 的长度最小的 连续子数组 [numsl, numsl+1, ..., numsr-1, numsr] ,并返回其长度**。**如果不存在符合条件的子数组,返回 0

示例 1:

输入:target = 7, nums = [2,3,1,2,4,3]
输出:2
解释:子数组 [4,3] 是该条件下的长度最小的子数组。

示例 2:

输入:target = 4, nums = [1,4,4]
输出:1

示例 3:

输入:target = 11, nums = [1,1,1,1,1,1,1,1]
输出:0
思路

用滑动窗口,其实也是双指针,就是将元素和>=target的限定为一个窗口里,然后一直求最小的窗口

题解
public class MinSubArrayLen {
    public int minSubArrayLen(int target, int[] nums) {
        int minLen = Integer.MAX_VALUE;//用于统计满足条件的子数组的最小长度
        int sum = 0;//用于求和
        int i = 0;//作为滑动窗口开始位置
        for (int j = 0; j < nums.length; j++) {
            sum += nums[j];

            while (sum >= target){//当元素之和大于target,记录下此时的长度,移动窗口接着求
                minLen = Math.min(minLen,j - i + 1);
                sum -= nums[i];
                i++;//滑动窗口开始位置往前
            }
        }
        //如果minLen没有被赋值,则返回0
        return minLen == Integer.MAX_VALUE ? 0:minLen;

    }
}

904.水果成篮

你正在探访一家农场,农场从左到右种植了一排果树。这些树用一个整数数组 fruits 表示,其中 fruits[i] 是第 i 棵树上的水果 种类

你想要尽可能多地收集水果。然而,农场的主人设定了一些严格的规矩,你必须按照要求采摘水果:

  • 你只有 两个 篮子,并且每个篮子只能装 单一类型 的水果。每个篮子能够装的水果总量没有限制。
  • 你可以选择任意一棵树开始采摘,你必须从 每棵 树(包括开始采摘的树)上 恰好摘一个水果 。采摘的水果应当符合篮子中的水果类型。每采摘一次,你将会向右移动到下一棵树,并继续采摘。
  • 一旦你走到某棵树前,但水果不符合篮子的水果类型,那么就必须停止采摘。

给你一个整数数组 fruits ,返回你可以收集的水果的 最大 数目。

示例 1:

输入:fruits = [1,2,1]
输出:3
解释:可以采摘全部 3 棵树。

示例 2:

输入:fruits = [0,1,2,2]
输出:3
解释:可以采摘 [1,2,2] 这三棵树。
如果从第一棵树开始采摘,则只能采摘 [0,1] 这两棵树。
思路
题解

待续。。。下一篇接上

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值