代码随想录算法训练营第一天| 704. 二分查找、27. 移除元素

数组理论知识:从0开始,地址连续

只能覆盖不能删除

704. 二分查找

初步想法:遍历搜索数组,查找target;两端逼近搜索(二分)

阅读后想法:

1. 使用二分法,考虑采用左闭右闭的方式 [left, right],在区间范围内代表有意义的数(所寻找的target包含在其中),因此当 arr[mid]!=target的情况下,需要排除mid这个点,进行left=mid+1或者right=mid-1;

2. 当left==right的情况下,[left, right]是有意义的,还会进行点搜索;

3. 进行初始化的时候,right需有意义是考虑的点,因此right = arr.size()-1.

class Solution {
public:
    int search(vector& nums, int target) {
        int right = nums.size()-1;
        int left = 0;
        while(left<=right) {
            int mid = (left+right)/2;
            if(nums[mid]==target) {
                return mid;
            }else if(nums[mid]>target) {
                right = mid-1;
            }else {
                left = mid+1;
            }
        }
        return -1;
    }
};

拓展题:35、34

27. 移除元素

初步想法:数组只能进行覆盖,发现元素整体(后方元素s)往前移动;双指针(类似快慢指针),一个指针搜索,一个指针记录索引位置,边寻找边插入

阅读后想法:使用双指针

a. 暴力解法(练习暴力)

1. size记录数组大小,当删除一个元素后size缩小;

2. i为遍历索引下标,当往前移时,i需要保持不变(新的arr[i]),i--;

class Solution {
public:
    int removeElement(vector& nums, int val) {
        int size = nums.size();
        // 进行遍历
        for(int i=0; i

b. 双指针(快慢指针应用)

class Solution {
public:
    int removeElement(vector& nums, int val) {
        // 快慢指针
        int slow = 0; // 记录索引
        int fast = 0; // 访问下标索引
        int size = nums.size()-1;
        while(fast<=size) {
            if(nums[fast]==val) {
                // 需要被覆盖,不被写入
                fast++;
            }else {
                nums[slow++] = nums[fast++];
            }
        }
        return slow;
    }
};

拓展题:

35. 搜索插入位置

 a. 暴力解法

想法:遍历的方式,寻找大于或等于的情况

思路:只有四种情况

1. 元素小于数组所有元素

2. 元素等于数组中某个元素

3. 元素插入到数组中某个下标

4. 元素大于数组中所有元素

class Solution {
public:
    int searchInsert(vector& nums, int target) {
        for(int i=0; i=target) {
                return i;
            }
        }
        return nums.size();
    }
};

b. 二分法

循环不变量:在这个范围内[left, right]寻找target

class Solution {
public:
    int searchInsert(vector& nums, int target) {
        int left = 0;
        int right = nums.size()-1;
        while(left<=right) {
            int mid = (left+right)/2;
            if(nums[mid]target) {
                right = mid-1;
            }else {
                return mid;
            }
        }
        return right+1;
    }
};

34. 在排序数组中查找元素的第一个和最后一个位置

想法:需要寻找第一个=target的下标,和第一个>=target的下标

范围:[left, right]

思路:

1. 第一个位置:左边寻找,缩小right(靠左)

当找到=target的位置,尽可能继续搜索左部分(改right),寻找第一个

2. 最后一个位置:右边寻找,扩大left(靠右)

当找到target的位置,尽可能继续搜索右部分(改left),寻找最后一个

class Solution {
public:
    int findLastIndex(vector& nums, int target) {
        int left = 0;
        int right = nums.size()-1;
        int rightBoard = -2;
        while(left<=right) {
            int mid = (left+right)/2;
            if(nums[mid]>target) {
                right = mid-1;
            }else if(nums[mid]<=target) {
                left = mid+1;
                rightBoard = left;
            }
        }
        return rightBoard;
    }

    int findOneIndex(vector& nums, int target) {
        int left = 0;
        int right = nums.size()-1;
        int leftBoard = -2;
        while(left<=right) {
            int mid = (left+right)/2;
            if(nums[mid]>=target) {
                right = mid-1;
                leftBoard = right;
            }else if(nums[mid] searchRange(vector& nums, int target) {
        int rightBoard = findLastIndex(nums, target);
        int leftBoard = findOneIndex(nums, target);
        if(rightBoard==-2 || leftBoard==-2) {
            return {-1, -1};
        }
        if(rightBoard-leftBoard>1) {
            return {leftBoard+1, rightBoard-1};
        }
        return {-1, -1};
        
    }
};

你可能感兴趣的:(数据结构,算法,leetcode,c++)