刷题的第一天,希望自己能够不断坚持下去,迎来蜕变。
刷题语言:C++ / Python
数组理论基础
704. 二分查找
27. 移除元素
数组:存放连续内存空间上的相同类型数据的集合
Tip:(1) 数组下标都是从0开始 (2) 数组内存空间的地址是连续的
因为数组的在内存空间的地址是连续的,所以我们在删除或者增添元素的时候,就难免要移动其他元素的地址
数组的元素不能删,只能覆盖
在C++中,二维数组在地址空间上也是连续的
我熟悉了根据左闭右开,左闭右闭两种区间规则写出来的二分法
前提:
(1)数组为有序数组
(2)强调数组无重复元素 (一旦有重复元素,使用二分返回的元素下标可能不是唯一的)
区间的定义:不变量。
循环不变量
:在while寻找每一次边界的处理都要坚持根据区间的定义来操作
(1) [ l e f t , r i g h t ] [left, right] [left,right]左闭右闭
C++:
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) / 2;
if (nums[mid] > target) // [left, mid - 1]
{
right = mid - 1;
}
else if (nums[mid] < target) // [mid + 1, right]
{
left = mid + 1;
}
else
{
return mid;
}
}
return -1;
}
};
Python:
class Solution(object):
def search(self, nums, target):
left = 0
right = len(nums) - 1
while (left <= right):
mid = (left + right) // 2
if (nums[mid] > target):
right = mid - 1
elif (nums[mid] < target):
left = mid + 1
else:
return mid
return -1
(2) [ l e f t , r i g h t ) [left, right) [left,right) 左闭右开
C++:
class Solution {
public:
int search(vector<int>& nums, int target) {
int left = 0;
int right = nums.size();
while (left < right) // 因为left == right的时候,在[left, right)是无效的空间,所以使用 <
{
int mid = (left + right) / 2;
if (nums[mid] > target) // [left, mid)
{
right = mid;
}
else if (nums[mid] < target) // [mid + 1, right)
{
left = mid + 1;
}
else
{
return mid;
}
}
return -1;
}
};
Python:
class Solution(object):
def search(self, nums, target):
left = 0
right = len(nums)
while (left < right):
mid = (left + right) // 2
if (nums[mid] > target):
right = mid
elif (nums[mid] < target):
left = mid + 1
else:
return mid
return -1
掌握了暴力解法和双指针(快慢指针)的解法
(1)暴力解法
第一个for循环遍历数组元素
第二个for循环更新数组,发现元素,集体向前移动
时间复杂度: O ( n 2 ) O(n^2) O(n2)
C++:
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;
}
};
Python:
class Solution(object):
def removeElement(self, nums, val):
i = 0
size = len(nums)
while i < size:
if nums[i] == val:
for j in range(i+1, size):
nums[j-1] = nums[j]
i-=1
size-=1
i += 1
return size
(2)双指针法
快慢指针:通过一个快指针和慢指针在一个for循环下完成两个for循环的工作
快指针:新数组元素
慢指针:更新新数组下标的位置
伪代码
slow = 0;
for (fast = 0; fast < nums.size; fast++)
{
if (nums[fast] != val) # fast 寻找新数组元素
nums[slow++] = nums[fast];# slow更新新数组下标的位置
}
时间复杂度: O ( n ) O(n) O(n)
空间复杂度: O ( 1 ) O(1) O(1)
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];
}
}
return slow;
}
};
Python:
class Solution(object):
def removeElement(self, nums, val):
slow = 0 # 慢指针
fast = 0 # 快指针
size = len(nums)
while fast < size:# 不加等于是因为,a = size 时,nums[a] 会越界
# slow 用来收集不等于 val 的值,如果 fast 对应值不等于 val,则把它与 slow 替换
if nums[fast] != val:
nums[slow] = nums[fast]
slow += 1
fast += 1
return slow
鼓励坚持一天的自己