Datawhale组队学习丨9月Leetcode算法入门与数组丨打卡笔记
这篇博客以及接下来几篇将会是一个 入门型 的文章,主要是自己学习的一个记录。
内容会参考这篇笔记(很详细):LeetCode 算法笔记(Leetcode-Notes)
程序 = 算法 + 数据结构
程序设计的所要追求的是:
更加合适的数据结构 + 花费时间更少、占用空间更小的算法。
LeetCode 算法笔记(Leetcode-Notes) 笔记中写道:如果把程序比喻成做菜,那么各种食材和调味料就是数据结构,而不同的做菜方法或者说不同的烹饪方式就是算法。那么色香味俱全就是做菜的追求,程序也是这样,通过合适的算法以及合适的数据结构,产生一个高质量的代码去解决问题。
数据结构(Data Structure):带有结构特性的数据元素的集合。简言之,就是 数据的组织结构,用来组织、存储数据。用来提高计算机硬件的利用效率。
通过学习数据结构,我们可以了解和掌握计算中中的数据是以什么样的方式进行组织和存储的。
数据结构的分类方式
1. 逻辑结构
2. 物理结构
链式存储结构:将数据元素存放在任意的存储单元里,存储单元可以连续,也可以不连续。
链结点:每个元素所占用的若干单元组合。存放当前元素数据信息和下一元素所在链接点的指针。
算法:解决问题的方法或者流程。
它不依赖于任何一种语言,可以用 自然语言、编程语言(Python、C、C++、Java 等) 描述,也可以用 伪代码、流程图 来表示。
1. 算法的基本特性
2. 算法追求的目标
算法复杂度(Algorithm complexity):在问题的输入规模为 n n n 条件下,程序的时间使用情况和空间使用情况。
比较算法优劣的两种方法
问题的输入规模 n n n :算法问题输入的数据量大小。
1.时间复杂度简介
时间复杂度(Time Complexity):在问题的输入规模为 n n n 的条件下,算法运行所需要花费的时间,可以记作为 T ( n ) T(n) T(n) 。
度量标准:基本操作次数。
什么是基本操作?
算法执行中的每一条语句。每一次基本操作都可以在常数时间内完成。
2.渐进符号
渐进符号(Asymptotic Symbol):专门用来刻画函数的增长速度的。简单来说,渐进符号只保留了 最高阶幂,忽略了一个函数中增长较慢的部分,比如 低阶幂、系数、常量。因为当问题规模变的很大时,这几部分并不能左右增长趋势,所以可以忽略掉。
渐近记号 Θ \Theta Θ、 O O O、 o o o、 Ω \Omega Ω、 ω \omega ω关系
记号 | 含义 | 通俗理解 |
---|---|---|
Θ \Theta Θ | 紧确界 | 相当于"=" |
O O O(大欧) | 上界 | 相当于"<=" |
o o o(小欧) | 非紧的上界 | 相当于"<" |
Ω \Omega Ω(大欧米伽) | 下界 | 相当于">=" |
ω \omega ω(小欧米伽) | 非紧的下界 | 相当于">" |
3.时间复杂度计算
确定基本操作:首先,需要明确算法中的基本操作是什么,这些基本操作通常是算法中执行一次所需要的时间最长的操作。
计算每个基本操作的执行次数:对于算法中的每个基本操作,需要计算它们分别会执行多少次。这通常涉及到对算法中的循环、递归等结构进行分析。
求和并简化:将每个基本操作的执行次数加总,并进行简化。通常可以根据常见的时间复杂度规则(如忽略常数项、保留最高次项等)来简化计算。
得出时间复杂度表达式:根据求和并简化后的结果,得出算法的时间复杂度表达式。常见的时间复杂度包括 O ( 1 ) O(1) O(1)、 O ( n ) O(n) O(n)、 O ( n 2 ) O(n^2) O(n2)、 O ( n ! ) O(n!) O(n!)、 O ( log n ) O(\log n) O(logn)、 O ( n log n ) O(n \log n) O(nlogn)等。
需要注意的是,时间复杂度只是对算法的时间性能进行粗略估计,它描述的是算法的增长率,而非具体的执行时间。在实际应用中,还需要考虑输入规模、硬件环境等因素来综合评估算法的效率。
忽略常数项:在计算时间复杂度时,通常会忽略常数项。因为常数项对于大规模数据来说影响较小,而且不同的机器、不同的编译器等因素都会影响常数项。
保留最高次项:在计算时间复杂度时,通常只保留最高次项,因为最高次项对于大规模数据来说影响最大。
乘法法则:如果一个算法中有多个嵌套的循环,那么它们的时间复杂度应该用乘法法则计算。
加法法则:如果一个算法中有多个不同的操作,那么它们的时间复杂度应该用加法法则计算。
最坏情况分析:在计算时间复杂度时,通常会假设算法在最坏情况下的时间复杂度,因为最坏情况下的时间复杂度可以保证算法在任何情况下都不会超时。
平均情况分析:有些算法的时间复杂度与输入数据的分布情况有关,这时需要进行平均情况分析。
总之,计算时间复杂度需要遵循科学严谨的原则,同时也需要结合具体的算法和应用场景来进行综合评估。
def algorithm(n):
a = 1
b = 2
res = a * b + n
return res
def algorithm(n):
cnt = 1
while cnt < n:
cnt *= 2
return cnt
def algorithm(n):
sum = 0
for i in range(n):
sum += 1
return sum
def algorithm(n):
cnt = 1
res = 0
while cnt < n:
cnt *= 2
for i in range(n):
res += 1
return res
def algorithm(n):
res = 0
for i in range(n):
for j in range(n):
res += 1
return res
最佳时间复杂度(Best Case Time Complexity):指在最理想的情况下,算法执行所需的最少时间。最佳时间复杂度表示算法在最有利的输入情况下的性能表现。
最坏时间复杂度(Worst Case Time Complexity):指在最不利的情况下,算法执行所需的最长时间。最坏时间复杂度表示算法在最差的输入情况下的性能表现。
平均时间复杂度(Average Case Time Complexity):指算法执行所需时间的平均值,考虑了所有可能的输入情况下的性能表现。平均时间复杂度需要对输入的概率分布进行分析,通常需要使用概率论或统计学的方法来计算。
空间复杂度是衡量算法在执行过程中所需的额外空间或内存资源的度量。它描述的是算法所需的额外空间随着输入规模增加而增长的趋势。
通常,空间复杂度可以分为以下几种情况:
常数空间复杂度( O ( 1 ) O(1) O(1)):算法所需的额外空间是固定的,与输入规模无关。例如,只使用有限个变量的算法。
线性空间复杂度( O ( n ) O(n) O(n)):算法所需的额外空间随着输入规模线性增长。例如,需要存储输入数据的数组或列表。
平方空间复杂度( O ( n 2 ) O(n^2) O(n2)):算法所需的额外空间随着输入规模的平方增长。例如,需要存储二维矩阵的算法。
指数空间复杂度( O ( 2 n ) O(2^n) O(2n)):算法所需的额外空间随着输入规模的指数增长。例如,需要存储所有可能子集的算法。
需要注意的是,空间复杂度并不仅仅取决于算法中的变量和数据结构的使用情况,还受到函数调用、递归等因素的影响。在实际应用中,除了考虑时间复杂度外,也需要关注算法的空间复杂度,以避免因为内存不足导致程序异常或效率低下。
class Solution:
def sum(self, num1: int, num2: int) -> int:
return num1 + num2
class Solution:
def getConcatenation(self, nums: List[int]) -> List[int]:
return nums + nums
class Solution:
def numJewelsInStones(self, jewels: str, stones: str) -> int:
jewels_dic = dict()
for i in jewels:
jewels_dic[i] = 1
count = 0
for j in stones:
if j in jewels_dic:
count += 1
return count
class Solution:
def runningSum(self, nums: List[int]) -> List[int]:
n = len(nums)
runningSum = [0] * n
runningSum[0] = nums[0]
for i in range(1, n):
runningSum[i] = runningSum[i-1] + nums[i]
return runningSum
class Solution:
def toLowerCase(self, s: str) -> str:
ans = ''
for i in s:
if ord('A') <= ord(i) <= ord('Z'):
ans += chr(ord(i)+32)
else:
ans += i
return ans
class Solution:
def maximumWealth(self, accounts: List[List[int]]) -> int:
n = len(accounts)
m = 0
for i in range (n):
sum = 0
for j in range (len(accounts[i])):
sum += accounts[i][j]
if sum > m:
m = sum
return m
参考文献
—— END ——
如果以上内容有任何错误或者不准确的地方,欢迎在下面 👇 留言。或者你有更好的想法,欢迎一起交流学习~~~
更多精彩内容请前往 AXYZdong的博客