当前位置: 首页 > news >正文

算法:数组part01:704. 二分查找 +977.有序数组的平方

算法:数组part01:704. 二分查找 +27. 移除元素+977.有序数组的平方

704. 二分查找

题目链接:https://leetcode.cn/problems/binary-search/
文章讲解:https://programmercarl.com/0704.%E4%BA%8C%E5%88%86%E6%9F%A5%E6%89%BE.html

思想:

  • 题目要达到O(logn)的时间复杂度,显然遍历数组是做不到了,考虑二分查找

  • 使用二分查找的前提是:数组有序且不重复

  • 二分查找根据给定区间的闭合情况,分为左闭右闭区间算法和左闭右开区间算法

解题

左闭右闭
class Solution {public int search(int[] nums, int target) {//左闭右闭算法int left=0;int right=nums.length-1;while(left<=right){int mid=(left+right)/2;if(target==nums[mid]){//找到return mid;}else if(target<nums[mid]){//左侧right=mid-1;}else{//右侧left=mid+1;}}return -1;}
}
左闭右开
class Solution {public int search(int[] nums, int target) {//左闭右闭算法int left=0;int right=nums.length;while(left<right){int mid=(left+right)/2;if(target==nums[mid]){//找到return mid;}else if(target<nums[mid]){//左侧right=mid;}else{//右侧left=mid;}}return -1;}
}

总结

左闭右闭区间算法和左闭右开区间算法的区别:

  • 左闭右闭在where(left<=right)中加上等号,而左闭右开不加等号-------原因是左右边界能取到相同值比如[1,1]
  • 左闭右闭取左边或右边的时,让right=mid-1,left=mid+1;左闭右开让right=mid,left=mid,这样可以确保一个开区间
  • 左闭右闭初始right=nums.length-1,左闭右开初始right=nums.length

27. 移除元素

题目链接:https://leetcode.cn/problems/remove-element/
文章讲解:https://programmercarl.com/0027.%E7%A7%BB%E9%99%A4%E5%85%83%E7%B4%A0.html

思想

  • 要移除所有指定val并让让所有剩余元素挨个排在列表的前面,可以直接用暴力解法O(n2):即遍历数组找到需要移除的元素之后,将它后面的所有元素全部向前移一格;
  • 优化的解法是用双指针,快指针用于遍历数组,若其指向的这个元素不是val,就给慢指针的位置赋值为这个元素,慢指针从数组下标0开始;

解题

暴力解法
class Solution {public int removeElement(int[] nums, int val) {//暴力解法://遍历数组:找到val,然后将其后面的所有元素前移一格int size=nums.length;for(int i=0;i<size;i++){if(nums[i]==val){for(int j=i+1;j<size;j++){nums[j-1]=nums[j];}i--;size--;}}return size;}
}//这个是参考答案,要更好理解,上面的是我写的// 时间复杂度:O(n^2)
// 空间复杂度:O(1)
class Solution {
public:int removeElement(vector<int>& nums, int val) {int size = nums.size();for (int i = 0; i < size; i++) {if (nums[i] == val) { // 发现需要移除的元素,就将数组集体向前移动一位for (int j = i + 1; j < size; j++) {nums[j - 1] = nums[j];}i--; // 因为下标i以后的数值都向前移动了一位,所以i也向前移动一位size--; // 此时数组的大小-1}}return size;}
};
双指针

解法

class Solution {public int removeElement(int[] nums, int val) {int k=0;for(int i=0;i<nums.length;i++){if(nums[i]!=val){nums[k]=nums[i];k++;}}return k;}
}//这个是参考答案,要更好理解,上面的是我写的
// 时间复杂度:O(n)
// 空间复杂度:O(1)
class Solution {
public:int removeElement(vector<int>& nums, int val) {int slowIndex = 0;for (int fastIndex = 0; fastIndex < nums.size(); fastIndex++) {if (val != nums[fastIndex]) {nums[slowIndex++] = nums[fastIndex];}}return slowIndex;}
};

总结

双指针法用于在一个for循环中完成两个嵌套for的操作,用一个快指针去遍历,一个慢指针去指向剔除后的新数组。

977.有序数组的平方

题目链接:https://leetcode.cn/problems/squares-of-a-sorted-array/
文章讲解:https://programmercarl.com/0977.%E6%9C%89%E5%BA%8F%E6%95%B0%E7%BB%84%E7%9A%84%E5%B9%B3%E6%96%B9.html

思想

  • 在O(n)的时间复杂度下解这道题,同样利用双指针的思想;
  • 最重要的是需要理解:这个场景下的最大值只有可能出现在最左和最右。
  • 因此,可以利用left和right对比,将大者放入新数组的尾部;while(left<=right)就一直遍历,这样问题便迎刃而解了;

解题

class Solution {public int[] sortedSquares(int[] nums) {//平方后的最大元素只有可能在数组的两端int left=0;int right=nums.length-1;//定义一个新数组存放排序结果int[] result=new int[nums.length];int index=nums.length-1;while(left<=right){if(nums[left]*nums[left]<nums[right]*nums[right]){result[index--]=nums[right]*nums[right];right--;}else{result[index--]=nums[left]*nums[left];left++;}}return result;}
}//这个是参考答案,要更好理解,上面的是我写的
class Solution {public int[] sortedSquares(int[] nums) {int right = nums.length - 1;int left = 0;int[] result = new int[nums.length];int index = result.length - 1;while (left <= right) {if (nums[left] * nums[left] > nums[right] * nums[right]) {// 正数的相对位置是不变的, 需要调整的是负数平方后的相对位置result[index--] = nums[left] * nums[left];++left;} else {result[index--] = nums[right] * nums[right];--right;}}return result;}
}

总结

抓住核心:最大值只有可能在最左侧和最右侧,新建一个数组把left和right的大者放到新数组尾部,左右指针遍历即可得到结果。仍利用双指针思想,但算是双指针的另外一种稍复杂场景。

http://www.lryc.cn/news/597203.html

相关文章:

  • Java开发岗面试记录合集
  • LLM 中的 温度怎么控制随机性的?
  • AI驱动攻防升级,API安全走到关键档口
  • CentOS 7 Linux 用 yum 安装 Docker,含 Docker 镜像无法拉取问题(即 docker pull 失败)的解决方案
  • 路由器与交换机的区别
  • 数据结构之队列(C语言)
  • 【优选算法-多源 BFS】多源 BFS:解决多个起点的广度优先搜索
  • 【大模型文生图、文生音频实战Demo】基于Spring AI Alibaba和阿里百炼大模型实现文生图、文生视频
  • Android MediaCodec 的使用和源码实现分析
  • 2.1 为什么定义tensor数据结构?
  • 【有趣的跳跃一维数组问题】2022-7-27
  • 彻底掌握双列集合——Map接口以及实现类和常用API及其底层原理
  • 题解:P9468 [EGOI 2023] Candy / 糖果
  • 亚马逊云科技 上海AI研究院 突然解散 | AI早报
  • Taint Bug (污点漏洞):
  • GitHub 趋势日报 (2025年07月22日)
  • Docker 基础概念
  • 解决Node 17+版本与Metro、Webpack等兼容性问题(500)
  • 数据结构自学Day13 -- 快速排序--“分而治之”
  • ITIL 4:云计算与微服务对组织架构的影响
  • kotlin基础【1】
  • android studio(NewsApiDemo)100%kotlin
  • 【前端】当前主流的 CSS 预处理器语言Sass / SCSS、Less、Stylus
  • kotlin基础【2】
  • BaaS平台(Supabase)
  • 数据结构自学Day13 -- 快速排序--“前后指针法”
  • 《计算机网络》实验报告六 电子邮件
  • 数据结构(2)顺序表算法题
  • 【数据结构】二叉树的链式结构--用C语言实现
  • 数据结构系列之AVL树