Day1|704.二分查找|27.移除数组|977.有序数组的平方

数组基础

数组是存放在连续内存空间上的相同类型数据的集合。 

  • 数组下标都是从0开始的。
  • 数组内存空间的地址是连续的

所以增删数组元素时,要移动其他元素的地址 。且数组元素不是删,只能覆盖。

二维数组的地址也是连续的,数组元素地址相差的字节取决于它是什么类型的数组。

注意,严格来说vector是容器而不是数组。 

704.二分查找

链接:https://leetcode.cn/problems/binary-search/description/ 

题目:给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。

解法一:左闭右闭

while(left---right)   里left和right使用<=,middle比较过一次,就不用包含在区间里,那么在比较middle和target时左区间或右区间就要更新为(middle+1,right)或(left,middle-1)。

class Solution {
public:
    int search(vector<int>& nums, int target) {
        int left=0,right=nums.size()-1;
        while(left<=right)
        {
            int middle=(left+right)/2;
            if(nums[middle]>target)right=middle-1;//更新右区间
            else if(nums[middle]<target)left=middle+1;//更新左区间
            else return middle;//找到
        }
        return -1;//没找到
    }
};

注意:定义middle时防止数据溢出  写法更正为:int middle=(left+(right-left))/2

解法二:左闭右开

和上面解法区别,left和right使用<比较。

在一开始right定义为数组长度时,左区间的右边界就已经不包括right了,所以更新时直接等于middle。

class Solution {
public:
    int search(vector<int>& nums, int target) {
        int left=0,right=nums.size();//注意右开right的定义
        while(left<right)
        {
            int middle=(left+right)/2;
            if(nums[middle]>target)right=middle;//更新右开区间
            else if(nums[middle]<target)left=middle+1;//更新左闭区间
            else return middle;
        }
        return -1;
    }
};

注意,定义middle时防止数据溢出  写法更正为:

int middle = left + ((right - left) >> 1);

27.移除数组

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

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

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

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

暴力解法

比较简单,就是找到要移除的数,并把后面的数一个个向前覆盖。

class Solution {
public:
    int removeElement(vector<int>& nums, int val) {
        int len=nums.size();
          for(int i=0;i<len;i++)
          {
            if(nums[i]==val)
            {
                for(int j=i+1;j<len;j++)
                nums[j-1]=nums[j];
            i--;
            len--;//好理解,就是覆盖
            }
          }
          return len;
    }
};
  • 时间复杂度:O(n^2)
  • 空间复杂度: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];
            slowindex++;
            }
        }
        return slowindex;
        
    }
};
  • 时间复杂度:O(n)
  • 空间复杂度:O(1)

 977.有序数组的平方

题目:977. 有序数组的平方 - 力扣(LeetCode)

给你一个按 非递减顺序 排序的整数数组 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]

双指针法

图示理解:

思路,原有数组定义两个指针i和j,i指向数组起始位置,j指向数组末位。

定义一个新数组来存储平方且排序后的原数组元素,并由指针k指向末尾

比较i和j指向元素的平方,较大者赋值给新数组(从末位开始),并更新i,j,k的指向。

class Solution {
public:
    vector<int> sortedSquares(vector<int>& nums) {
        int a=nums.size()-1;
          vector<int>result(a+1,0);
          for(int i=0,j=a;i<=j;)
          {
            if(nums[i]*nums[i]>nums[j]*nums[j])
            { result[a]=nums[i]*nums[i];
            a--;
            i++;
            }
            else 
            { result[a]=nums[j]*nums[j];
            a--;
            j--;
            }
          }
          return result;
    }
};

暴力解法:每个数平方后,用sort函数排序。

总结:由于之前做过数组的题,所以对二分法和双指针法的运用较为熟悉。

  • 18
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值