因为学计算机语言是属于半路出家,在接触数据结构之前,我只了解数据的类型,从没有了解过不同数据类型的存储方式。数组、链表等等因为不同的存储方式,展现出不同的优缺点,以适应不同的用途。
代码随想录是属于把饭喂到嘴里的好!里面资料对于我这种小白来说,真的是很保姆了。之前刷过一小段时间的力扣算法,但没有坚持下来,学到链表就已经放弃。这次学习给自己一个目标:
按照卡哥的进度,完成整个数据结构的主要题目,并在平台中打卡记录
这个目标是因为卡哥的教程里还包含了很多扩展和延申的题目,但是因为我时间有限,所以先打算主要过一遍,如果有机会二刷再细致来吧
二分查找
触发条件:
二分查找的主要条件是有序,只有排列有了顺序才能通过二分法减少查找次数
注意事项:
查找区间**[a,b]还是[a, b)**
我个人还是比较熟悉**[a, b)这种方法右等左加**
具体代码:
class Solution:def search(self, nums: List[int], target: int) -> int:left, right = 0, len(nums) # 定义target在左闭右开的区间里,即:[left, right)while left < right: # 因为left == right的时候,在[left, right)是无效的空间,所以使用 <middle = left + (right - left) // 2if nums[middle] > target:right = middle # target 在左区间,在[left, middle)中elif nums[middle] < target:left = middle + 1 # target 在右区间,在[middle + 1, right)中else:return middle # 数组中找到目标值,直接返回下标return -1 # 未找到目标值
移除元素
触发条件:
空间复杂度为O(1)(即原地移除,不能构建新的数组),移除val值后的数组大小
注意事项:
有两种方法可以解决下列问题:
①暴力法: 2个for (一个原数组、一个新数组)、O(n^2)的时间复杂度
// 时间复杂度:O(n^2)
// 空间复杂度:O(1)
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;}
};
②双指针法:快指针找元素、慢指针定位置,O(n)的时间复杂度
// 时间复杂度: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;}
};
虽然我更熟悉python,但是感觉这里C++的代码更有感觉,更好理解
以下是我的python代码:
class Solution:def removeElement(self, nums: List[int], val: int) -> int:slowindex = 0fastindex = 0num_long = len(nums)while fastindex < num_long:if val != nums[fastindex]:nums[slowindex] = nums[fastindex]slowindex += 1fastindex += 1 return slowindex