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

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

class Solution {
public:

    int search(vector& nums, int target) {
        
        int l=0;
        int r=nums.size()-1;
            while(l<=r){
                int mid=(l+r)>>1;
                if(target==nums[mid])  return mid;
                if(target>nums[mid]){
                    
                    l=mid+1;
                }
                else{
                    r=mid-1;
                }
                
            }
            return -1;

    }
};

之前就已经熟悉二分法了,有两次wa,第一次是因为一开始的右边界取了一个数为数组的长度值int r=nums.size(),终止条件是l<=r,导致数组可能越界(针对于数组为[-1],target为5的情况),r能取到的时候要注意取值;第二次wa是终止条件写成了l

看完题解发现:

这道题目的前提是数组为有序数组,同时题目还强调数组中无重复元素,因为一旦有重复元素,使用二分查找法返回的元素下标可能不是唯一的,这些都是使用二分法的前提条件,当大家看到题目描述满足如上条件的时候,可要想一想是不是可以用二分法了。重点是区间定义。

时间复杂度是o(logn)的,而空间复杂度是o(1)的。

如果l和r是左闭,右开

// 版本二
class Solution {
public:
    int search(vector& nums, int target) {
        int left = 0;
        int right = nums.size(); // 定义target在左闭右开的区间里,即:[left, right)
        while (left < right) { // 因为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; // 数组中找到目标值,直接返回下标
            }
        }
        // 未找到目标值
        return -1;
    }
};

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

class Solution {
public:
    int removeElement(vector& nums, int val) {
        int l=0;
        if(nums.size()==0) return 0;
        int r=nums.size()-1;
        
        while(l<=r){
            while(l<=r&&nums[l]!=val){
                l++;
                
            }
            while(l<=r&&nums[r]==val ){
                r--;
            }
            // if(l==r){
            //     return l+1;
            // }
            if(l>r) return l; 
            swap(nums[l],nums[r]);

        }
        return l+1;
    
    }
};

这道题之前看过,所以也是挺快ac,有一次wa是因为没考虑数组为空的情况,要注意特判。是双指针法。

暴力解法是对每一个元素,判断是或不是,是的话删除移动元素。

class Solution {
public:
    int removeElement(vector& nums, int val) {
        if(nums.size()==0) return 0;
        int res=0;
        for(int i=0;i

我第一次wa的原因是直接将后面的元素移到了前面,但是仍然可能遍历到后面,被统计,但其实该元素已经移到前面了,所以要swap。

暴力解法空间复杂度也是O(1),时间复杂度是O(n的平方)

我的是改变了相对位置的写法,以下是copy的没更改相对位置的写法。

// 时间复杂度:O(n)
// 空间复杂度:O(1)
class Solution {
public:
    int removeElement(vector& nums, int val) {
        int slowIndex = 0;
        for (int fastIndex = 0; fastIndex < nums.size(); fastIndex++) {
            if (val != nums[fastIndex]) {
                nums[slowIndex++] = nums[fastIndex];
            }
        }
        return slowIndex;
    }
};

今日收获:一个半小时的代码编写;要注意边界条件。

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