代码随想录算法训练营第一天|数组理论基础、704二分查找、27移除元素

发布时间:2024年01月10日

数组理论基础

一维数组

  1. 数组中的元素在内存空间中是连续的
  2. 数组名与数组中第一个元素的地址相同(一维数组)
  3. 数组的下标从0开始
  4. 删除数组的元素其实是用后面的元素覆盖掉要删除的元素
  5. 数组的长度不能改变

二维数组

  1. 二维数组是按照行存储的,也是连续的
  2. 将二维数组看作是一维数组的一维数组
  3. 二维数组就是指针组成的数组,可以用二级指针表示
int arr[2][3] = {{1,2,3},{4,5,6}}
// 首先将二维数组arr看作元素是arr[0],arr[1]的一维数组
arr // 二维数组arr的起始地址
arr[i] // 第i行一维数组的数组名,代表该一维数组的首元素地址,即第一个元素arr[i][0]的地址  =*(arr+i)
arr[i]+j // 代表arr[i][j]的地址,即&(arr[i][j])
*(arr[i]+j) // 代表arr[i][j]
arr[i][j]  // 代表arr[i][j]
arr+i // 代表二维数组中第i行数组的地址
*(arr+i)  // 即arr[i],第i行第0列的地址
*(arr+i)+j // 即&(arr[i][j])
*(*(arr+i)+j) // 即arr[i][j]

如果难以理解,可以看看在一维数组中的情况:

int arr[3]={1,2,3}
arr[1] // 代表了a[1]的值,即2
arr+1 // 代表了a[1]的地址,即&a[1]
*(arr+1) // 代表了a[1]的值,即2

704 二分查找

题目链接:二分查找

思路

暴力解法

如果这道题目的名字不是二分查找,那么拿到题目一个最直接的思路就是for循环暴力求解。

class Solution {
public:
   int search(vector<int>& nums, int target) {
   	for(int i=0; i<nums.size(); i++){
       	if(nums[i] == target){
           	return i;
       	}
   	}
   	return -1;
   }
};

二分解法

再一看,输入的数组是有序的,同时数组中还没有重复元素,再结合题目二分查找,便也可轻易地想到实用二分法来查找元素。自己在纸上画画,有一个二分法的伪代码。
二分法的具体实现要关注两个点:

  1. 区间问题
    到底是左闭右开区间[left,right),还是左闭右闭区间[left, right],我选择实用左闭右闭区间,因为这样看起来比较好理解,同时while条件中可以left可以等于right。
  2. 溢出问题
    这是一个小问题,计算mid时:mid = (left+right)/2,这样可能出现的一个问题是:left+right太大导致溢出。所以可以采取另一个计算方法:mid = left + (right - left) / 2,可以有效避免溢出问题。
class Solution {
public:
    int search(vector<int>& nums, int target) {
        int left = 0;
        int right = nums.size() - 1;
        while (left <= right){
            int mid = left + (right - left) / 2;
            if (nums[mid] == target){
                return mid;
            }
            else if (nums[mid] < target){
                left = mid + 1;
            }
            else if (nums[mid] > target){
                right = mid - 1;
            }
        }
        return -1;
    }
};

27 移除元素

题目链接:移除元素

思路

暴力解法

在看完题目说明后。首先是得删除掉数组中的目标元素(在数组中删除元素本质是后继元素的覆盖),然后返回的是剩余元素的长度。使用for循环,如果当前元素等于目标元素,则: 将后续的所有元素向前移动一位(这里又要使用一个for循环),同时数组长度减一,for循环的i也减一(因为数组已经移动,当前位置的元素是之前的下一个位置的元素,还没有经过if判断)。

class Solution {
public:
    int removeElement(vector<int>& nums, int val) {
        int n = nums.size();
        for(int i=0; i<n; i++){
            if(nums[i] == val){
                for(int j=i+1; j<n; j++){
                    nums[j-1] = nums[j];
                }
                n--;
                i--;
            }
        }
        return n;
 }  
};

双指针法

这道题不看解析想不到要用双指针法,对于什么是双指针法,现在浅显的认识也就是要有两个东西来进行处理,之前的for循环都是使用一个东西来遍历。
双指针法就是得要有两个东西来对数组进行处理,直观解释一下过程。
在这里插入图片描述
变量fast,也就是快指针,用来遍历要处理的数组;变量slow,也就是慢指针,用来对新数组的下标进行计数。

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

参考链接

  1. https://book.itheima.net/course/223/1263669610003230722/1263675595644137474
  2. https://zhuanlan.zhihu.com/p/148737542
  3. https://programmercarl.com/0027.%E7%A7%BB%E9%99%A4%E5%85%83%E7%B4%A0.html
文章来源:https://blog.csdn.net/qq_41596730/article/details/135494545
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。