day01-数组

数组理论基础  

文章链接:代码随想录

 704. 二分查找 
        使用二分查找前提是数组为有序数组,同时题目还强调数组中无重复元素

right代表的是搜索范围的右边界,而不是数组的实际最后一个元素的索引

左闭右闭        [left, right]
class Solution {
    public int search(int[] nums, int target) {
        int left = 0;                        //定义左区间标识
        int right = nums.length - 1;         //定义右区间标识
        // 当left==right,区间[left, right]依然有效,所以用 <=
        while (left <= right) {
            int mid= left + ((right - left) >> 1);// 防止溢出 等同于(left + right)/2
            if(nums[mid] > target){         //中间值大于目标值
                right = mid - 1;            //右边界变为mid - 1 左闭右闭
            }else if(nums[mid] < target){   //中间值小于目标值
                left = mid + 1;
            }else{
                return mid;
            }
        }
        return -1;
    }
}

左闭右开  [left, right)

主要还是区间的把握

区间是你自己定义的,如果说有四个数字
定义左闭右开区间:left(0) < right(4) 可以取到下标为0,1,2,3的元素
定义左闭右闭区间:left(0) <= right(3),可以取到下标为0,1,2,3的元素

所以

class Solution {
    public int search(int[] nums, int target) {
        int left = 0;                        //定义左区间标识
        int right = nums.length;             //定义右区间标识
        // 当left==right,区间[left, right)依然有效,所以用 <=
        while (left < right) {
            int mid= left + ((right - left) >> 1);// 防止溢出 等同于(left + right)/2
            if(nums[mid] > target){         //中间值大于目标值
                right = mid;                //右边界变为mid  左闭右闭
            }else if(nums[mid] < target){   //中间值小于目标值
                left = mid + 1;
            }else{
                return mid;
            }
        }
        return -1;
    }
}

 35. 搜索插入位置

暴力遍历

class Solution {
    public int searchInsert(int[] nums, int target) {
        /* 分四种情况 */
        for(int i = 0; i < nums.length; i++){
            //目标值在所有数组元素之前
            //目标值等于数组元素中某一个元素
            //目标值插入数组的位置
            if(nums[i] >= target){
                return i;
            }
            
        }
        //目标值在所有元素之后
        return nums.length;
    }
}

二分法

class Solution {
    public int searchInsert(int[] nums, int target) {
        int n = nums.length;

        // 定义target在左闭右闭的区间,[low, high]
        int low = 0;
        int high = n - 1;

        while (low <= high) { // 当low==high,区间[low, high]依然有效
            int mid = low + (high - low) / 2; // 防止溢出
            if (nums[mid] > target) {
                high = mid - 1; // target 在左区间,所以[low, mid - 1]
            } else if (nums[mid] < target) {
                low = mid + 1; // target 在右区间,所以[mid + 1, high]
            } else {
                // 1. 目标值等于数组中某一个元素  return mid;
                return mid;
            }
        }
        // 2.目标值在数组所有元素之前 3.目标值插入数组中 4.目标值在数组所有元素之后 return right + 1;
        return high + 1;
    }
}
//第二种二分法:左闭右开
public int searchInsert(int[] nums, int target) {
    int left = 0;
    int right = nums.length;
    while (left < right) { //左闭右开 [left, right)
        int middle = left + ((right - left) >> 1);
        if (nums[middle] > target) {
            right = middle; // target 在左区间,在[left, middle)中
        } else if (nums[middle] < target) {
            left = middle + 1; // target 在右区间,在 [middle+1, right)中
        } else { // nums[middle] == target
            return middle; // 数组中找到目标值的情况,直接返回下标
        }
    }
    // 目标值在数组所有元素之前 [0,0)
    // 目标值插入数组中的位置 [left, right) ,return right 即可
    // 目标值在数组所有元素之后的情况 [left, right),因为是右开区间,所以 return right
    return right;
}

 27. 移除元素

暴力法

// 时间复杂度: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;

    }
};

 双指针-快慢指针  并没有改变元素的相对位置

// 时间复杂度: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;
    }
};

双指针-相向指针

class Solution {
    public int removeElement(int[] nums, int val) {
        int left = 0;
        int right = nums.length - 1;
        while(left <= right){
            //找左边等于val的元素
            while(left <= right && nums[left] != val){
                //使用++leftIndex 可以确保我们先移动指针,然后再进行下一次判断。如果使用leftIndex++,则会导致先判断当前位置的元素,然后再移动指针
                ++left;
            }
            //找右边不等于val的元素
            while(left <= right && nums[right] == val){
                --right;
            }
            //将右边不等于val的元素覆盖左边等于val的元素
            if(left < right){
                //是先将右边不等于目标值的元素赋值给左边等于目标值的元素,然后同时移动左右指针,以继续寻找下一个需要移动的元素。
                nums[left++] = nums[right--];
            }
        }
        return left;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值