文章目录
前言
算法是程序员的内功,掌握算法不仅能帮助你在面试中过关斩将,赢取 Dream Offer,更能充分锻炼你的逻辑思维与底层能力,我是一名忠实的 Leetcode 用户,积累的一些个人经验,尽可能地帮助大家少走弯路。🚀 1.算法性能分析
🌈 1.1 时间复杂度
🚩 什么是时间复杂度?
🚀 2.数组
🌈 2.1 数组理论
🌈 2.2 二分法
🚩 题目
🚩 解题思路
🚩 答案
class Solution {
public:
int search(vector<int>& nums, int target) {
int left = 0;
int right = nums.size() - 1; // 定义target在左闭右闭的区间里,[left, right]
while (left <= right) { // 当left==right,区间[left, right]依然有效,所以用 <=
int middle = left + ((right - left) / 2);// 防止溢出 等同于(left + right)/2
if (nums[middle] > target) {
right = middle - 1; // target 在左区间,所以[left, middle - 1]
} else if (nums[middle] < target) {
left = middle + 1; // target 在右区间,所以[middle + 1, right]
} else { // nums[middle] == target
return middle; // 数组中找到目标值,直接返回下标
}
}
// 未找到目标值
return -1;
}
};
🌈 2.3 双指针法
🚩 题目
🚩 解题思路
🚩 答案
/**
* 相向双指针方法,基于元素顺序可以改变的题目描述改变了元素相对位置,确保了移动最少元素
* 时间复杂度:O(n)
* 空间复杂度:O(1)
*/
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
int leftIndex = 0;
int rightIndex = nums.size() - 1;
while (leftIndex <= rightIndex) {
// 找左边等于val的元素
while (leftIndex <= rightIndex && nums[leftIndex] != val){
++leftIndex;
}
// 找右边不等于val的元素
while (leftIndex <= rightIndex && nums[rightIndex] == val) {
-- rightIndex;
}
// 将右边不等于val的元素覆盖左边等于val的元素
if (leftIndex < rightIndex) {
nums[leftIndex++] = nums[rightIndex--];
}
}
return leftIndex; // leftIndex一定指向了最终数组末尾的下一个元素
}
};
🚀 3.链表
🌈 3.1 链表理论
🚩 单链表
🚩 双链表
🚩 循环链表
🚩 链表的存储方式
这个链表起始节点为2, 终止节点为7, 各个节点分布在内存个不同地址空间上,通过指针串联在一起。
🌈 3.2 删除链表节点
🚩 题目
🚩 解题思路
🚩 答案
class Solution {
public ListNode removeNthFromEnd(ListNode head, int n) {
ListNode dummy = new ListNode(-1);
dummy.next = head;
ListNode slow = dummy;
ListNode fast = dummy;
while (n-- > 0) {
fast = fast.next;
}
// 记住 待删除节点slow 的上一节点
ListNode prev = null;
while (fast != null) {
prev = slow;
slow = slow.next;
fast = fast.next;
}
// 上一节点的next指针绕过 待删除节点slow 直接指向slow的下一节点
prev.next = slow.next;
// 释放 待删除节点slow 的next指针, 这句删掉也能AC
slow.next = null;
return dummy.next;
}
}
🚀 4.哈希表
🌈 4.1 哈希理论
🌈 4.2 两数之合
🚩 题目
🚩 答案
class Solution {
public int[] twoSum(int[] nums, int target) {
int[] res = new int[2];
for(int i=0;i<nums.length;i++){
for(int j=i+1;j<nums.length;j++){
if(nums[i]+nums[j]==target){
res[0]=i;
res[1]=j;
break;
}
}
}
return res;
}
}
🚀 5.栈和队列
🚀 6.二叉树
🌈 6.1 满二叉树
这棵二叉树为满二叉树,也可以说深度为k,有2^k-1个节点的二叉树。
🌈 6.2 完全二叉树
相信不少同学最后一个二叉树是不是完全二叉树都中招了。
之前我们刚刚讲过优先级队列其实是一个堆,堆就是一棵完全二叉树,同时保证父子节点的顺序关系。
🚀 7.回溯法
🚩 什么是回溯法
🚩 回溯法解决的问题
🚩 回溯搜索的遍历过程
回溯法一般是在集合中递归搜索,集合的大小构成了树的宽度,递归的深度构成的树的深度。
🚀 7.贪心算法
🚩 什么是贪心算法
🚩 贪心一般解题步骤
🚀 8.动态规划
🚩 什么是动态规划
恭喜你,已经把代码随想录通关了,说一说自己刷完一遍的收获吧。
不过一刷代码随想录,理解的一定是不到位的,建议二刷之后,对各个经典类型的题目就有自己的想法了。
详细的刷题笔记参考以下CSDN博客,100道精选题
LeetCode精选算法100题,从入门到入赘
https://jeames.blog.csdn.net/article/details/124899610