参考资料:
电子网站:datawhalechina.github.io/leetcode-no…
——————————
程序 = 数据结构 + 算法
classDiagram
数据结构 --|> 逻辑结构
数据结构 --|> 物理结构
逻辑结构 --|> 集合
逻辑结构 --|> 线性
逻辑结构 --|> 树形
逻辑结构 --|> 图形
物理结构 --|> 顺序存储
物理结构 --|> 链式存储
数据结构: 数据以何种方式进行组织、存储
class 逻辑结构{
数据元素之间的相互关系
}
class 集合{
数据无序且唯一
}
class 线性{
数组、链表、栈、队列、哈希表
}
class 树形{
二叉树、多叉树、字典树
}
class 图形{
无向图、有向图、连通图
}
class 物理结构{
数据的逻辑结构 在计算机中的存储方式
}
class 顺序存储{
+占用最少的存储空间
-需要占用一片地址连续的存储单元,并且存储分配需要事先进行
-移动、删除等操作较慢
}
class 链式存储{
+ 存储空间不必事先分配,可临时申请。不会造成空间的浪费
+ 插入、移动、删除等操作效率比顺序存储高
- 需要额外的存储后继指针的空间。
}
算法的基本特性: 输入、输出、有穷性、确定性、可行性。
算法追求的目标:所需运行时间更小,占用内存空间更小。
- 正确、可读、健壮
——————
算法复杂度: 在问题的输入规模为 n 的条件下, 程序的时间使用情况 和 空间使用情况。
时间复杂度 T(n)
1、不包含循环、递归语句。 O(1)
2、线性 O(n) 单层循环
3、平方 双层循环 且 每层循环次数为 n
4、阶乘 O(n!) 全排列、旅行商问题暴力解法
5、对数 O(log n) 二分查找、分治
6、线性对数 O(n log n) 快速排序、归并排序、堆排序
时间复杂度的最佳、最坏、平均
空间复杂度 S(n)
来源 1: 算法范围内定义的变量 占用的存储空间。
来源 2: 递归栈帧空间
————————
目标: 通过解决 LeetCode 题库中的问题来练习编程技能,提升算法能力。
Leetbook、计划等
推荐刷题顺序和目录如下:
1. 初级算法、2. 数组类算法、3. 数组和字符串、4. 链表类算法、5. 哈希表、6. 队列 & 栈、7. 递归、8. 二分查找、9. 二叉树、10. 中级算法、11. 高级算法、12. 算法面试题汇总。
flowchart LR
看到题思考五分钟 -->|有思路| 写代码
看到题思考五分钟 -->|无思路| 看题解
看题解 -->|有思路| 根据题解思路实现代码
看题解 -->|无思路| 认真阅读题解的代码.并理解代码的逻辑
🚩—— Day1
√ 2235. 两整数相加
😂 这题也值得出嘛
class Solution: # O(1) O(1)
def sum(self, num1: int, num2: int) -> int:
return num1 + num2
class Solution {// O(1) O(1)
public:
int sum(int num1, int num2) {
return num1 + num2;
}
};
√ 1929. 数组串联
⭐ 数组串联的时间复杂度为 O(n)
class Solution: # O(n) O(1)
def getConcatenation(self, nums: List[int]) -> List[int]:
return nums * 2
class Solution: # O(n) O(1)
def getConcatenation(self, nums: List[int]) -> List[int]:
return nums + nums
class Solution: # O(n) O(1)
def getConcatenation(self, nums: List[int]) -> List[int]:
nums.extend(nums)
return nums
class Solution {// O(n) O(1)
public:
vector<int> getConcatenation(vector<int>& nums) {
int n = nums.size();
for (int i = 0; i < n; ++i){// 这里要注意 提前计算 n。因为后续 nums 的长度变大
nums.emplace_back(nums[i]);
}
return nums;
}
};
√ 771. 宝石与石头
优化: 哈希化 后, 空间换时间, 可将时间复杂度 从 O(mn) 降到 O(m + n)
⭐ 哈希化 可将查找时间复杂度降至 线性 O(n)
class Solution: # O(m + n) O(m) m 为 jewels 的长度
def numJewelsInStones(self, jewels: str, stones: str) -> int:
jewelsSet = set(jewels)
ret = 0
for c in stones:
if c in jewelsSet: # 哈希表为 O(1) 字符串为 O(n)
ret += 1
return ret
class Solution {// 哈希化 空间换时间 O(m + n) O(m) m 为 jewels 的长度
public:
int numJewelsInStones(string jewels, string stones) {
unordered_set<char> jewelsSet(jewels.begin(), jewels.end());
int ret = 0;
for (char c : stones){
if (jewelsSet.contains(c)){
++ret;
}
}
return ret;
}
};
🚩—— Day2
√ 1480. 一维数组的动态和
⭐ 原地叠加修改成前缀和数组
# 需要问清楚 是否允许修改原来的数组。不然创建一个新数组存储值即可
class Solution: # O(n) O(1)
def runningSum(self, nums: List[int]) -> List[int]:
for i in range(1, len(nums)):
nums[i] += nums[i - 1]
return nums
class Solution {// O(n) O(1)
public:
vector<int> runningSum(vector<int>& nums) {
for (int i = 1; i < nums.size(); ++i){
nums[i] += nums[i - 1];
}
return nums;
}
};
√ 709. 转换成小写字母
class Solution:
def toLowerCase(self, s: str) -> str:
return s.lower()
class Solution {// API O(n) O(1)
public:
string toLowerCase(string s) {
for (char & ch : s){
ch = tolower(ch);
}
return s;
}
};
⭐ 大写字母 ord() + 32 (按位或替代)后得到 小写字母
class Solution: # O(n) O(1)
def toLowerCase(self, s: str) -> str:
# 大写字母 [65, 90] + 32 后变成 小写
# 小写字母 [97, 122]
lis = list(s)
for i, c in enumerate(lis):
if 65 <= ord(c) <= 90: # 注意范围, 非字母部分 无需转换
lis[i] = chr(ord(c) | 32) # 按位或 后,恰好实现了 加 32 操作
return ''.join(lis)
#print(ord('A'), ord('Z'))
#print(ord('a'), ord('z'))
class Solution {// O(n) O(1)
public:
string toLowerCase(string s) {
for (char & ch : s){
if ( 65 <= ch && ch <= 90){// C++ 可以直接比较
ch |= 32;
}
}
return s;
}
};
√ 1672. 最富有客户的资产总量
class Solution: # O(mn) O(1)
def maximumWealth(self, accounts: List[List[int]]) -> int:
ret = 0
for acc in accounts:
ret = max(ret, sum(acc))
return ret
class Solution {// O(mn) O(1)
public:
int maximumWealth(vector<vector<int>>& accounts) {
int ret = 0;
for (auto & acc : accounts){
ret = max(ret, accumulate(acc.begin(), acc.end(), 0));
}
return ret;
}
};