LeetCode【刷题日记】:数组篇(1)含原理讲解

发布时间:2026/5/24 22:26:42

LeetCode【刷题日记】:数组篇(1)含原理讲解 个人主页北极的代码欢迎来访作者简介java后端学习者❄️个人专栏苍穹外卖日记SSM框架深入JavaWeb✨命运的结局尽可永在不屈的挑战却不可须臾或缺前言经过前面对java语言的学习大体的了解了java语言的基础内容和技术栈而算法这篇主要是培养我们的编程思维让我们能在实际问题中运用编程思维解决问题同时算法也是找工作找实习面试中重要的一环尤其是LeetCode已经快成为算法的标准题库了我们多刷肯定是有帮助的。1.二分查找题目原型LeetCode 704给定一个 n 个元素有序的升序整型数组 nums 和一个目标值 target 写一个函数搜索 nums 中的 target如果目标值存在返回下标否则返回 -1。我的观点这道题看着简单实则也有很多容易让人犯迷糊的地方 让我们来详细的讲解一下这题。首先什么是二分查找简单的说就像是一个猜数字游戏1-100我们每次猜的数字都是范围的一半这样就能根据结果排除一半的范围大了或者小了从而更新我们查找的范围提高了查找的效率。题解一左闭右闭class Solution { public int search(int[] nums, int target) { int left0; int rightnums.length-1; while(leftright){ int midleft((right-left)1); if(targetnums[mid]){ return mid; } else if(targetnums[mid]){ rightmid-1; }else{ leftmid1; } } return-1; } }分析一下我们先定义两个值用来表示要查询的范围最核心的就是while语句中的条件了这里我们写的是 闭区间【】意味着两边都能取到那这个条件影响我们后面的什么呢最直接的影响就是我们后面更新区间的时候能不能取等号的问题或者是加一减一的问题当两边都取闭区间时我们拿target目标值和中间值进行比较如果目标值小于中间值那么我们就取中间值的左半部分区间更新原来区间的right的值由于都是闭区间我们要把值更新成mid-1因为是闭区间我们能取到mid但是前提是目标值已经小于mid了同理如果是目标值大于mid我们就更新原来区间的left更新成mid1原理一样。题解二左闭右开class Solution { public int search(int[] nums, int target) { int left 0, right nums.length; while (left right) { int mid left ((right - left) 1); if (nums[mid] target) { return mid; } else if (nums[mid] target) { left mid 1; } else { // nums[mid] target right mid; } } // 未找到目标值 return -1; } }分析一下前面的部分都相同关于while里的条件是不一样的是不带等号的因为是左闭右开带等号这个区间是不合法的但是这里的条件变化了肯定会影响到后面的区间更新我们来具体讲解当target目标值小于mid时我们取原来区间的左半部分把right更新成mid为什么不是mid-1因为右边本来就是开区间取不到当target值大于mid时我们取原来区间的右半部分把left更新为mid1为什么是这样是因为我们左边是闭区间可以取到mid。写法区间类型循环条件区间合法性写法1闭区间[left, right]left rightleft right合法1个元素写法2左闭右开[left, right)left rightleft right不合法空区间不带等号是因为左闭右开left right是空区间right mid而不是mid-1因为右边开区间取不到midleft mid1而不是mid因为左边闭区间要排除mid取到mid会导致问题要么漏元素要么死循环一句话总结二分查找的两种写法本质是一样的区别在于区间定义决定了边界如何更新——闭区间可以取到边界开区间取不到所以要相应调整更新逻辑。2.移除元素题目背景LeetCode 27给你一个数组 nums 和一个值 val你需要 原地 移除所有数值等于 val 的元素并返回移除后数组的新长度。不要使用额外的数组空间你必须仅使用 O(1) 额外空间并原地修改输入数组。元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。示例 1: 给定 nums [3,2,2,3], val 3, 函数应该返回新的长度 2, 并且 nums 中的前两个元素均为 2。 你不需要考虑数组中超出新长度后面的元素。示例 2: 给定 nums [0,1,2,2,3,0,4,2], val 2, 函数应该返回新的长度 5, 并且 nums 中的前五个元素为 0, 1, 3, 0, 4。你不需要考虑数组中超出新长度后面的元素。我的观点这题题目简单思想挺重要引入了双指针的概念思想题解一暴力拆解class Solution { public int removeElement(int[] nums, int val) { // 暴力法 int n nums.length; for (int i 0; i n; i) { if (nums[i] val) { for (int j i 1; j n; j) { nums[j - 1] nums[j]; } i--; n--; } } return n; } }分析一下逻辑非常简单简单的两个for循环时间复杂度O(n^2)题解二双指针法什么是双指针简单的说就是两个人协同干活减少循环次数底层就是把两次for循环变成一次for循环模式指针移动方式经典应用左右指针一左一右向中间靠拢两数之和、回文判断快慢指针一快一慢同向而行删除重复、链表找环滑动窗口窗口左右边界同向移动子数组问题class Solution { public int removeElement(int[] nums, int val) { // 快慢指针 int slowIndex 0; for (int fastIndex 0; fastIndex nums.length; fastIndex) { if (nums[fastIndex] ! val) { nums[slowIndex] nums[fastIndex]; slowIndex; } } return slowIndex; } }分析一下这里的快慢指针是同一起点的还有双向的但原理都是一样的我们把这个步骤形容成整理书架书架的垃圾是需要删除覆盖的元素具体的实现步骤书[0, 1, 2, 2, 3, 0, 4, 2] 要扔2第1本fast0书是0要留[0, 1, 2, 2, 3, 0, 4, 2]↑slow0侦察兵0是好书搬运工放到slow位置0→ [0, ...]slow前进到1 ✓第2本fast1书是1要留[0, 1, 2, 2, 3, 0, 4, 2]↑slow1侦察兵1是好书搬运工放到slow位置1→ [0, 1, ...]slow前进到2 ✓第3本fast2书是2要扔[0, 1, 2, 2, 3, 0, 4, 2]↑slow2侦察兵2是垃圾搬运工不动slow还是2空位留着[0, 1, 2, 2, ...] ← 垃圾还在第4本fast3书是2要扔[0, 1, 2, 2, 3, 0, 4, 2]↑slow2侦察兵又是垃圾搬运工不动slow还是2第5本fast4书是3要留[0, 1, 2, 2, 3, 0, 4, 2]↑slow2侦察兵3是好书搬运工放到slow位置2→ [0, 1, 3, 2, 3, 0, 4, 2]把原来的垃圾2覆盖了slow前进到3 ✓第6本fast5书是0要留[0, 1, 3, 2, 3, 0, 4, 2]↑slow3侦察兵0是好书搬运工放到slow位置3→ [0, 1, 3, 0, 3, 0, 4, 2]把原来的垃圾2覆盖了slow前进到4 ✓第7本fast6书是4要留[0, 1, 3, 0, 3, 0, 4, 2]↑slow4侦察兵4是好书搬运工放到slow位置4→ [0, 1, 3, 0, 4, 0, 4, 2]把原来的3覆盖了slow前进到5 ✓第8本fast7书是2要扔[0, 1, 3, 0, 4, 0, 4, 2]↑slow5侦察兵垃圾搬运工不动检查完毕结语如果对你有帮助请点赞关注收藏你的支持就是我最大的鼓励

相关新闻