代码随想录刷题笔记-数组篇

代码随想录刷题笔记-数组篇

27 移除元素(easy)

力扣地址

https://leetcode.cn/problems/remove-element/description/

题目描述

给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素。元素的顺序可能发生改变。然后返回 nums 中与 val 不同的元素的数量。

假设 nums 中不等于 val 的元素数量为 k,要通过此题,您需要执行以下操作:

更改 nums 数组,使 nums 的前 k 个元素包含不等于 val 的元素。nums 的其余元素和 nums 的大小并不重要。
返回 k。
用户评测:

评测机将使用以下代码测试您的解决方案:

int[] nums = [...]; // 输入数组
int val = ...; // 要移除的值
int[] expectedNums = [...]; // 长度正确的预期答案。
                            // 它以不等于 val 的值排序。

int k = removeElement(nums, val); // 调用你的实现

assert k == expectedNums.length;
sort(nums, 0, k); // 排序 nums 的前 k 个元素
for (int i = 0; i < actualLength; i++) {
    assert nums[i] == expectedNums[i];
}
如果所有的断言都通过,你的解决方案将会 通过。

题目实例

输入:nums = [3,2,2,3], val = 3
输出:2, nums = [2,2,_,_]
解释:你的函数函数应该返回 k = 2, 并且 nums 中的前两个元素均为 2。
你在返回的 k 个元素之外留下了什么并不重要(因此它们并不计入评测)。

解题思路

快慢指针,两个指针都从下标0开始。
快的指针负责遍历原始数组,每次+1。
慢的指针负责统计真实长度,当满足条件(快指针指向的小标 != 目标值)时,先把不满足的值赋给当前慢指针的下标,然后+1。
当快指针遍历结束时,此时的慢指针的长度就是期待的值。

举个栗子:
例如 3 2 2 3,目标值是3
快指针 为0,如果表示下标则指向3 ,慢指针不动,值还是0
快指针 为1,如果表示下标则指向2 ,满足不等于目标值,先给慢指针的当前值(0)对应的num[0] 赋值2,然后慢指针向后移动,慢指针变成1
快指针 为2,如果表示下标则指向2 ,满足不等于目标值,先给慢指针的当前值(1)对应的num[1] 赋值2,然后慢指针向后移动,慢指针变成2
快指针 为3,如果表示下标则指向3,慢指针不动,值还是2
数组遍历结束,返回慢指针的值2,也就是只有两个元素符合条件。

补充说明: 之所以用 “快指针 为0,如果表示下标则指向3” 是因为这个不完全是数组的下标,只是可以这样理解,因为实际场景的话,新数组的长度是2,下标2都越界了。

代码实现

    public int removeElement(int[] nums, int val) {
        // 慢指针
        int slowIndex = 0;
        for (int i = 0; i < nums.length; i++) {
            if (nums[i] != val) {
               // 也可以写成 slowIndex++
                nums[slowIndex] = nums[i];
                slowIndex++;
            }
        }
        return slowIndex;
    }

tips: 实际开发中,不要用i这样的表示,要有业务意义。

26. 删除有序数组中的重复项(easy)

力扣地址

https://leetcode.cn/problems/remove-duplicates-from-sorted-array/description/

题目描述

给你一个 非严格递增排列 的数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。然后返回 nums 中唯一元素的个数。

考虑 nums 的唯一元素的数量为 k ,你需要做以下事情确保你的题解可以被通过:

更改数组 nums ,使 nums 的前 k 个元素包含唯一元素,并按照它们最初在 nums 中出现的顺序排列。nums 的其余元素与 nums 的大小不重要。
返回 k 。
判题标准:

系统会用下面的代码来测试你的题解:

int[] nums = [...]; // 输入数组
int[] expectedNums = [...]; // 长度正确的期望答案

int k = removeDuplicates(nums); // 调用

assert k == expectedNums.length;
for (int i = 0; i < k; i++) {
    assert nums[i] == expectedNums[i];
}
如果所有断言都通过,那么您的题解将被 通过。

题目示例

示例 1:

输入:nums = [1,1,2]
输出:2, nums = [1,2,_]
解释:函数应该返回新的长度 2 ,并且原数组 nums 的前两个元素被修改为 1, 2 。不需要考虑数组中超出新长度后面的元素。

解题思路

有序,所以一样的一定在一起。
快慢指针
初始状态:慢指针为0,快指针为1
进行状态:当快慢指针指向的值不一致时,慢指针先加1,然后再赋值这个加一以后的位置的值。上一个题目是从慢指针开始一个一个填充不等于目标值的,这个是最开始的那一位就是需要的,然后才要筛选每一个不一样的。
结束状态:快指针遍历结束,返回慢指针 + 1,数组是从0开始的,长度要+1。

栗子:
1,1,2
初始状态:
快指针1,指向的值是1
慢指针0,指向的值是1
进行状态:
快指针+1,变成2,指向的值是2
慢指针是0,指向1,值不一样,慢指针先+1,变成1,然后1这个位置的值赋值2
结束状态:
返回长度,慢指针1,+1是2

代码实现

    public int removeDuplicates(int[] nums) {
        // 建议做个保护,实际你不知道别人会不会调你的方法,万一有问题,防止甩锅
        if (nums == null || nums.length == 0) {
            return 0;
        }
        int slowIndex = 0;
        for (int fastIndex = 1; fastIndex < nums.length; fastIndex++) {
            if (nums[fastIndex] != nums[slowIndex]) {
                slowIndex++;
                nums[slowIndex] = nums[fastIndex];
            }
        }
        return slowIndex + 1;

    }

283. 移动零(easy)

力扣地址

https://leetcode.cn/problems/move-zeroes/description/

题目描述

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

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

题目实例

示例 1:

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

解题思路

这个和27是一样的,可以理解成目标值是0,然后把不等于0的全部塞完以后,这个时候的慢指针从结束位置一直填充0。

代码实现

    public void moveZeroes(int[] nums) {
        int index = 0;
        for (int i = 0;  i < nums.length; i++) {
            if (nums[i] != 0) {
                nums[index++] = nums[i];
            }
        }
        // 上面和27完全一样,下面就一点点变种
        for (int i = index; i < nums.length; i++) {
            nums[i] = 0;
        }
    }

tips:实际开发中,不要把对象塞在一个void方法里,否则你压根不知道会改点什么东西,和对象有关的要放在初始化里,如果涉及状态改变,将这个对象建模成领域实体,再把状态改变的方法定义在领域实体中。

844 比较含退格的字符串(easy)

力扣地址

https://leetcode.cn/problems/backspace-string-compare/description/

题目描述

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

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

题目实例

示例 1:

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

解题思路

栈的解法比较基础,就不展开了,主要是看到卡哥的思路,直呼牛逼,就直接贴出来了
在这里插入图片描述
动图:
在这里插入图片描述
初始化:
定义s串中的#的数量 sSkipNum = 0
定义t串中的#的数量 tSkipNum = 0
定义指针 sIndex,从后往前遍历, sIndex = s.length() - 1
定义指针 tIndex,从后往前遍历, tIndex = t.length() - 1
进行状态:
两个指针的过程是一致的

while(指针 >= 0) {
      if ( 当前指针指向的字符 = #) {
             #的数量++;
     } else {
          //  进行回退操作,回退以后,这个#的数量就需要-1
          if  ( #的数量  > 0) {
               #的数量--;
          } else {
              // 如果不需要进行回退操作,那么就进行下一个字符的处理
              break;
         }
    }
    指针--;
}

两个指针遍历以后,如果指向的字符不一样,那么说明还是不一样,就判断false,否则就继续下一个

            if (t.charAt(tIndex) != s.charAt(sIndex)) {
                return false;
            }
            tIndex--;
            sIndex--;

结束状态:
当有一个指针结束,那么判断是不是两个指针都指向了-1,指向-1说明都遍历结束了,回退操作以后两个串是一样的

代码实现

    public boolean backspaceCompare(String s, String t) {
        // 初始状态
        int sSkipNum = 0;
        int tSkipNum = 0;
        int sIndex = s.length() - 1;
        int tIndex = t.length() - 1;

        // 中间状态
        while (true) {
            while (sIndex >= 0) {
                if (s.charAt(sIndex) == '#') {
                    sSkipNum++;
                } else {
                    if (sSkipNum > 0) {
                        sSkipNum--;
                    } else {
                        break;
                    }
                }
                sIndex--;
            }
            while (tIndex >= 0) {
                if (t.charAt(tIndex) == '#') {
                    tSkipNum++;
                } else {
                    if (tSkipNum > 0) {
                        tSkipNum--;
                    } else {
                        break;
                    }
                }
                tIndex--;
            }
            // 结束状态:有一个已经遍历结束了,交给最后的审判,笑死,也算中间状态,看怎么理解
            if (tIndex < 0 || sIndex < 0) {
                break;
            }
            // 中间状态:#回退的已经结束了,后面就是判断剩下的是不是一致
            if (t.charAt(tIndex) != s.charAt(sIndex)) {
                return false;
            }
            tIndex--;
            sIndex--;
        }

        // 结束状态: 看看是不是两个都遍历完了
        if (sIndex == tIndex && sIndex == -1) {
            return true;
        }
        return false;
    }

977. 有序数组的平方(easy)

力扣地址

https://leetcode.cn/problems/squares-of-a-sorted-array/description/

题目描述

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

题目实例

示例 1:

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

解题思路

实际开发中:最简单的当然用stream的map转成平方,然后统计list,再用工具类排序即可。
刷题学习建议还是双指针
初始状态:
前指针,指向0,从头遍历
后指针,指向nums.length -1,从后向前遍历
新数组的下标,默认指向最后,nums.length - 1
进行状态:
如果前指针指向的数的平方大,那么就放在最后,然后新数组的下标–,反之就是后指针的数放在后面

代码实现

    public int[] sortedSquares(int[] nums) {
        int i = 0;
        int j = nums.length - 1;
        int index = nums.length - 1;
        int[] res = new int[nums.length];
        while (i <= j) {
            if (nums[i] * nums[i] > nums[j] * nums[j]) {
                res[index--] = nums[i] * nums[i];
                i++;
            } else {
                res[index--] = nums[j] * nums[j];
                j--;
            }
        }
        return res;
    }

209 长度最小的子数组(mid)

力扣地址

https://leetcode.cn/problems/minimum-size-subarray-sum/description/

题目描述

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

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

题目实例

示例 1:

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

解题思路

不定长的滑窗。
滑窗模板
不定长

int res = 最大值或者最小值,求最大值就选最小值,反之就最大值
// 这样方便计算长度
int start = -1;
int end = 0;
// 中间状态,可能是求和,求积或者什么
int midStatusNum = ?

while (end < num.length) {
   midStatusNum = 操作num[end]
   while (一个条件) {
      // 也可能是最大值,因为初始化的时候给了-1,所以这个时候就直接减
      res = Math.min(res, end - start); 
      start++;
      midStatus - num[start]
   }
   end++;
}

// 如果还是初始化的值,那说明这个过程就取不到
res == 最大值或者最小值 ? 0 : res;

定长的话,判断窗口的时候就不能用while了,就用if,这样长度才能被限制住

int res = 最大值或者最小值,求最大值就选最小值,反之就最大值
// 这样方便计算长度
int start = -1;
int end = 0;
// 中间状态,可能是求和,求积或者什么
int midStatusNum = ?

while (end < num.length) {
   midStatusNum = 操作num[end]
   if (一个条件) {
      // 也可能是最大值,因为初始化的时候给了-1,所以这个时候就直接减
      res = Math.min(res, end - start); 
      start++;
      midStatus - num[start]
   }
   end++;
}

// 如果还是初始化的值,那说明这个过程就取不到
res == 最大值或者最小值 ? 0 : res;

代码实现

套不定长的模板

    public int minSubArrayLen(int target, int[] nums) {
        int res = Integer.MAX_VALUE;

        int start = -1;
        int end = 0;
        int sum = 0;
        
        while (end < nums.length) {
            sum += nums[end];
            while (sum >= target) {
                res = Math.min(res, end - start);
                start++;
                sum -= nums[start];
            }
            end++;
        }

        return res == Integer.MAX_VALUE ? 0 : res;
    }

54 螺旋矩阵 (待补充,面经碰到的少,最后再说)

相关推荐

  1. 代码随想笔记

    2024-06-12 05:08:02       32 阅读
  2. 代码随想笔记Day36

    2024-06-12 05:08:02       43 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-06-12 05:08:02       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-06-12 05:08:02       100 阅读
  3. 在Django里面运行非项目文件

    2024-06-12 05:08:02       82 阅读
  4. Python语言-面向对象

    2024-06-12 05:08:02       91 阅读

热门阅读

  1. docker使用auth登录

    2024-06-12 05:08:02       30 阅读
  2. 二进制兼容

    2024-06-12 05:08:02       30 阅读
  3. day6 C++

    2024-06-12 05:08:02       30 阅读
  4. 2024全国高考作文题解读(讯飞星火3.0版本)

    2024-06-12 05:08:02       24 阅读
  5. 常用的网络安全测试工具介绍

    2024-06-12 05:08:02       36 阅读
  6. 个人愚见的自主可控

    2024-06-12 05:08:02       34 阅读
  7. Python学习笔记5:入门知识(五)

    2024-06-12 05:08:02       34 阅读