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

发布时间 2023-09-07 00:48:50作者: zz子木zz

数组

704.二分查找

mydemo

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

            if(nums[mid] == target)
                return mid;

            if(nums[mid] > target)
            {
                right = mid - 1;
                mid = (left + right) / 2;
            }
        }

        return -1;
    }
};

为什么是

left = mid + 1; right = mid - 1 

而不是

left = mid; right= mid;

解答

其实在发生大小判断进入更新left或right的分支后,mid就已经被排除在外了,所以不用考虑mid所在位置,+1或者-1进行移动即可。

而且移动有一个好处,就是可以让left何right重叠甚至是反向(right在left前面),这是跳出循环的重要条件

而且不进行移动的话,考虑一种极限情况:

[7,8], target = 8

left = 0, right = 1,mid = 0;

你会发现无论怎么样mid都无法到达target。

要是target过大或过小不在数组里,这个算法怎么输出-1呢?

关键:

while(left <= right)

target过大,left会不断朝着right移动,到达临界点(left = right),然后继续变大,跳出循环

target过小则反之

为什么是

while(left <= right)

而不是

while(left < right)

考虑一种极限情况,即数组一开始就只有一个元素 {5},

令 target = 5

那么:

mid = 0 ,left = 0, right = 0

left 等于 right,无法进入循环进行二分查找,从而输出-1,这是显然是错误的

27.移除元素

1 暴力解法

my demo:

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)
            {
                //cout << "i=" << i << endl;
                if(nums[i] == val)
                {
                    if(i==len)
                        len--; //不加的话,当i=len-1时,nums[j] = nums[j+1];有可能会越界
                    else
                    {
                        for(int j = i; j < len-1; j++)
                        {    
                            nums[j] = nums[j+1];   
                        }
                        len--;
                        i--;	//不加这一行,在 0,1,2,2,3,val=2这种要删除的元素重复出现的时候会出错
                    }
                }
            }
        }
        return len;
    }
};

2 快慢指针法

my demo

class Solution {
public:
    int removeElement(vector<int>& nums, int val) {
       int len = nums.size();
       int slow = 0;
       for(int fast = 0; fast < len; fast++)
       {
           if(nums[fast] != val)
           {
                nums[slow] = nums[fast];
                slow++;
           }
       }
        return slow;
    };
};

优化版:

nums[slow] = nums[fast];
slow++;

改为

nums[slow++] = nums[fast];