代码随想录算法学习心得1 |704.二分查找、数组理论基础、27.元素移除...

一、数组理论基础


数组是基本的数据结构,数组是存放在连续内存空间上的相同类型数据的集合。

即两个特点:存储在一篇连续的内存空间、数据类型相同。

正是因为数组的在内存空间的地址是连续的,在删除或者增添元素的时候,就移动其他元素的地址,也就是说数组的元素是不能删的,只能覆盖。

对于二维数组来说,不同的编程语言对于内存的管理不同,在C++中,二维数组也是存储在一片连续的内存空间的。

对于二维整型数组arr[2][3]来说,其地址如下:

arr[2][3]={{0,1,2},
           {3,4,5}};

代码随想录算法学习心得1 |704.二分查找、数组理论基础、27.元素移除..._第1张图片 

 

代码随想录算法学习心得1 |704.二分查找、数组理论基础、27.元素移除..._第2张图片


二、二分查找

题目链接:https://leetcode.cn/problems/binary-search/

描述:给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target  ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。

方法1:抛开使用二分查找的方法,以ac为目的的话,第一想法是通过遍历数组来解决。

代码如下:

#include 
#include 
using namespace std;

//C++的类来实现,遍历vector容器
class Solution
{
public:
	int search(vector& nums, int target)
	{
		int i = 0;
		for (vector::iterator it = nums.begin(); it != nums.end(); it++,i++)
		{
			if (*it == target)
				return i;
		}
		return -1;
	}
};

int main()
{
	vector nums{ 1,2,3,4,56 };
	Solution s;
	int ret=s.search(nums, -2);
	return ret;
}

可以得到结果如下:

代码随想录算法学习心得1 |704.二分查找、数组理论基础、27.元素移除..._第3张图片


方法2:二分查找(左闭右闭)

前提:数组是有序且无重复元素的。

左闭右闭:[left,right],left=0,right=容器大小-1;

关键点:要遵循循环不变量原则,区间的定义即不变量是贯穿于整个while循环过程的。

while(left<=right)

代码如下:

#include 
#include 
using namespace std;
//左闭右闭原则
class Solution
{
public:
	int search(vector& nums, int target)
	{
		int left = 0;
		int right = nums.size() - 1;
		while (left <= right)
		{
			int middle = left + (right - left) / 2;
			if (nums[middle] > target)
				right = middle - 1;
			else if (nums[middle] < target)
				left = middle + 1;
			else
				return middle;
		}
		return -1;
	}
};

int main()
{
	vector v{ 10,28,29,30 };
	Solution s;
	int ret=s.search(v, 11);
	return ret;
}

 结果如下:

代码随想录算法学习心得1 |704.二分查找、数组理论基础、27.元素移除..._第4张图片


方法3:二分查找(左闭右开)

while(left

代码如下:

#include 
#include 
using namespace std;
//左闭右开原则
class Solution
{
public:
	int search(vector& nums, int target)
	{
		int left = 0;
		int right = nums.size();
		while (left < right)
		{
			int middle = left + (right - left) >> 1;
			if (nums[middle] > target)
				right = middle;
			else if (nums[middle] < target)
				left = middle + 1;
			else
				return middle;
		}
		return -1;
	}
};

int main()
{
	vector v{ 10,28,29,30 };
	Solution s;
	int ret=s.search(v, 29);
	return ret;
}

结果如下:

代码随想录算法学习心得1 |704.二分查找、数组理论基础、27.元素移除..._第5张图片

 


三、移除元素

题目链接:力扣

描述:

给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。

不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并原地修改输入数组。

元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。


方法1:用两个for循环来实现。

代码如下:

#include 
#include 
using namespace std;
//暴力循环
class Solution {
public:
    int removeElement(vector& nums, int val)
    {
        int size = nums.size();//记录大小
        for (int i = 0; i < size; i++)
        {
            if (nums[i] == val)
            {
                for (int j = i; j < nums.size() - 1; j++)
                {
                    nums[j] = nums[j + 1];
                }
                i--;//如果不写这一行,可能导致删除不干净。
                size--;
            }
        }
        return size;
    }
};
int main()
{
    vectorv{ 1,3,3,6,7,3,3 };
    Solution s;
    int ret = s.removeElement(v, 3);
    int arr[2][3] = {{0,1,2},
                      {3,4,5}};
    return ret;
}

 结果如下:

代码随想录算法学习心得1 |704.二分查找、数组理论基础、27.元素移除..._第6张图片

 


方法2:双指针法

  • 快指针:寻找新数组的元素,新数组就是不含有目标元素的数组
  • 慢指针:指向新数组下标的位置

双指针法(快慢指针法)在数组和链表的操作中是非常常见的,很多考察数组、链表、字符串等操作的面试题,都使用双指针法。 

代码如下:

#include 
#include 
using namespace std;

//使用双指针来实现
class Solution {
public:
    int removeElement(vector& nums, int val) {
        int slow = 0;//新数组的下标
        for (int fast = 0; fast < nums.size(); fast++)
        {//新数组的更新过程
            if (nums[fast] != val)
            {//若不等于,则加入新数组
                nums[slow++] = nums[fast];
            }
        }
        return slow;
    }
};
int main()
{
    vectorv{ 1,3,5,3,7,3 };
    Solution s;
    int ret=s.removeElement(v, 3);
    return ret;
}

代码随想录算法学习心得1 |704.二分查找、数组理论基础、27.元素移除..._第7张图片 

 

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