当前位置: 首页 > 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.dtcms.com/a/294809.html

相关文章:

  • ZeroMQ源码深度解析:高性能网络库的架构设计与性能优化
  • 高效编程革命:DeepSeek V3多语言支持与性能优化实战
  • 【前端】当前主流的 CSS 预处理器语言Sass / SCSS、Less、Stylus
  • C++:list(1)list的使用
  • HomeAssistant本地开发笔记
  • 「iOS」——KVO
  • MCP客户端架构与实施
  • SQL基础⑦ | 子查询
  • Linux——System V 共享内存 IPC
  • 【第十二章 W55MH32 NetBIOS示例标题】
  • ChatGPT桌面版深度解析
  • clientHeight(用于获取元素的可视高度)
  • 大致自定义文件I/O库函数的实现详解(了解即可)
  • 计算机网络学习----域名解析
  • uni-app平板端自定义样式合集
  • 【67】MFC入门到精通——MFC 销售管理系统 项目实现详细教程
  • 【自动化运维神器Ansible】深入解析Ansible Host-Pattern:精准控制目标主机的艺术
  • PowerShell自动化核对AD与HR系统账户信息实战指南
  • Hexo - 免费搭建个人博客02 - 创建个人博客
  • 智能办公如何创建e9流程
  • 力扣刷题(第九十六天)
  • Windows 用 Python3 快速搭建 HTTP 服务器
  • Google Chrome V8< 14.0.221 类型混淆漏洞
  • 基于Kafka实现动态监听topic功能
  • 元图CAD:高效分割图纸的智能解决方案
  • CSP-J系列【2024】P11230 [CSP-J 2024] 接龙题解
  • 数据持久化--PlayerPrefs
  • GRE实验
  • ROS是什么?
  • 力扣面试150(39/150)