[Day1] array, 704 binary search, 27 remove elements

The questions of the exercises come from Likou, and the order is carried out according to the code random recording.

array

An array is a collection of data of the same type stored in a contiguous memory space .

  • Array subscripts start from 0
  • The addresses of the array memory space are continuous (one-dimensional and two-dimensional are both continuous)
  • The elements of the array cannot be deleted, only overwritten
  • Arrays are random access storage structures

If you use C++, you should pay attention to the difference between vector and array. The underlying implementation of vector is array. Strictly speaking, vector is a container, not an array.
Vector is a sequential container, which uses continuous memory space to store elements, but the size of its memory space can be changed.
Array is a sequential container, which also uses continuous memory space to store elements, but its memory space is a fixed size, which cannot be changed after application.

704 Binary Search

The premise of binary search is that the array is an ordered array and there are no duplicate elements in the array.

Because once there are repeated elements, the subscript of the element returned by the binary search method may not be unique. These are the prerequisites for using the binary search method. When you see that the title description meets the above conditions, you can think about it. Use dichotomy.

When writing dichotomy, there are generally two definitions of intervals, left-closed and right-closed [left, right], or left-closed and right-opened [left, right).

Topic Link: 704 Binary Search

Topic: Given an ordered (ascending) integer array nums with n elements and a target value target, write a function to search the target in nums, and return the subscript if the target value exists, otherwise return -1.

Version one is left closed and right closed [left, right]

[left, right] Both left and right sides can be obtained, nums[m] cannot be equal to target, so nums[m]>target, then right=m-1

// 版本一 左闭右闭即[left, right]
class Solution {
    
    
public:
    int search(vector<int>& nums, int target) {
    
     //vector好比是一个数组
        int left=0;
        int right=nums.size()-1;    //左闭右闭,下标从0开始,最后一个数就是个数减1
        while (left<=right)
        {
    
    
            int middle=left+((right-left)/2);  //防止溢出,等价于 (left+right)/2
            if(nums[middle]>target){
    
    
                right=middle-1;//target在左区间, middle是几个数值的中间数 数组这里是以下标看来值,因此下标-1
            }else if(nums[middle]<target){
    
    
                left=middle+1;//target在右区间
            }else{
    
                  //nums[middle]==target
                return middle;
            }
        }
        // 未找到目标值
        return -1;
    }
};

About the following code

 int middle = left + ((right - left) / 2);  //而不用mid = (left+right)/2

Reason: mid = (left + right) / 2 is prone to overflow! Because left+right can easily exceed the int range! And mid = left + (right - left) / 2 is not easy to overflow, so it is recommended to use mid = left + (right - left) / 2 when writing binary points in the future
Source: binary search

Version 2 left closed right open [left, right)

[left, right) The value on the left can be obtained but the value on the right cannot be obtained, nums[m] may be equal to target, so nums[m]>target, then right=m

// 版本二  左闭右开即[left, right)
class Solution {
    
    
public:
    int search(vector<int>& nums, int target) {
    
    
        int left=0;
        int right=nums.size();    //左闭右开,
        while (left<right)
        {
    
    
            int middle=left+((right-left)>>1);  //防止溢出,(right-left)>>1相当于(right - left)/2
            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;
    }
};

(right - left) >> 1 in the following code is equivalent to (right - left)/2

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

Reason: I am still worried that left+right may exceed the maximum value of the basic type
Source: left + ((right -left) >> 1

27 Remove elements

The elements of the array are continuous in the memory address, and an element in the array cannot be deleted individually, but can only be overwritten.

Topic link: 27 remove elements

Question:
Given an array nums and a value val, you need to remove all elements whose value is equal to val in place, and return the new length of the removed array.

Don't use extra array space, you have to use only O(1) extra space and modify the input array in-place.

The order of elements can be changed. You don't need to consider elements in the array beyond the new length.

Brute force solution

The violent solution is a two-layer for loop, one for loop traverses the array elements, and the second for loop updates the array.
Time complexity: O(n^2)
Space complexity: O(1)

//暴力解法  两层for 循环
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;
    }
};

double pointer method

Double pointer method (fast and slow pointer method): complete the work of two for loops under one for loop through a fast pointer and a slow pointer.

Define fast and slow pointers

  • Fast pointer: Find the elements required by the new array, the new array is the array that does not contain the target element (the array after deleting the target value)
  • Slow pointer: point to the location where the subscript of the new array is updated

The fast pointer is used to create a new array. When the fast pointer is not equal to the target value (the number to be deleted), that is the element we need for the new array we created. We need to update the array and assign the value obtained by the fast pointer to The position of the subscript corresponding to the new array is to give the fast pointer to the position of the slow pointer, and the slow pointer is to update the position of the new array. After the fast pointer assigns the value to the slow pointer, the slow pointer also needs to move back one position to continue updating. When the fast pointer touches the value of the element to be deleted, the content in the following for loop will not be carried out, the fast pointer continues to move backward, and the slow pointer is still at the original position (this step is to remove the element)

// 时间复杂度: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;  //慢指针对应的下标就是新数组中的大小
    }
};

Guess you like

Origin blog.csdn.net/weixin_45768644/article/details/128637757