数据结构入门:时间复杂度与排序和查找

一、时间复杂度

1.1定义

时间复杂度是算法执行次数(y)和数据总量(n)的关系,反映算法 "效率趋势"(不是具体执行时间)。

例:

y = a------------>y=1------------>O(1) 算法的执行次数与数据总量无关

y = an+b------------>y=n------------>O(n)

y = logan------------>y=logn------------>O(logn)

y = an²+bn+c------------>y=n²------------>O(n²)

效率排序:O(1)<O(logn)<O(n)<O(nlogn)<O(n2)

1.2真题练手

例题1:

复制代码
int sum=0;
for(int i=1;i<n;i*=2)
    for(int j=0;j<i;j++)
        sum++;

分析

外层循环:i从 1 开始,每次 ×2,直到i≥n,执行次数是 log2​n(比如 n=8 时,i=1、2、4,共 3 次);

内层循环:每次执行i次(i=1 时执行 1 次,i=2 时执行 2 次,...,i=2^k 时执行 2^k 次);

总执行次数:1+2+4+...+2log2​n−1=2log2​n−1=n−1;

时间复杂度:O(n)。

例题2:

复制代码
int i=0;
while(i*i <=n)
    i++;

分析

循环结束条件是i² >n,即i>√n,执行次数约为 ;

时间复杂度:O(√n

例题3:

复制代码
count=0;
for(k=1;k<=n;k*=2)
    for(j=1;j<=n;j++)
        count++;

分析

外层循环:k从 1 开始,每次 ×2,直到k>n,执行次数是 log2​n(比如 n=8 时,k=1、2、4、8,共 4 次);

内层循环:每次固定执行n次;

总执行次数:log2​n×n=nlog2​n;

时间复杂度:O(nlogn)(对应选项 C)。

二、查找算法:从 "暴力" 到 "高效"

计算机 80% 的操作是 "查找",两种常见方式对比:

2.1无序数组查找(暴力遍历)

比如数组[5,7,4,2,0,3,1,6]找 "4":

只能从头到尾遍历,最坏情况执行 n 次;

时间复杂度:O(n)。

2.2折半查找(二分查找,仅适用于有序数组)

比如有序数组[0,1,2,3,4,5,6,7]找 "4":

步骤:先查中间位mid=3(对应值 3),比 4 小,再查右半部分的中间位mid=5(对应值 5),比 4 大,最后查中间位 4(找到目标);

执行次数:log2​n(n=8 时执行 3 次);

时间复杂度:O(logn)。

三、排序算法:不同算法的效率差异

要想用折半查找,得先把数组排序 ------ 看几个经典排序的逻辑和复杂度。

3.1冒泡排序(O(n2))

核心逻辑 :前后元素对比,大的往后 "冒泡"。比如数组[4,2,0,3,1,5,6,7]

第 1 轮:对比 (4,2)→交换,(4,0)→交换,...,最大的 "7" 移到末尾;

第 2 轮:对比剩下的元素,第二大的 "6" 移到倒数第二位;

最坏情况执行次数:1+2+...+(n−1)=n(n−1)/2;

时间复杂度:O(n2)。

3.2简单选择排序(O(n2))

核心逻辑 :每轮找最小值,和待排序部分的第一个元素交换。比如数组[0,1,2,3,5,4,7,6]

第 1 轮:找最小的 "0",和第一个元素交换(已在正确位置);

第 2 轮:找剩下的最小 "1",和第二个元素交换;

无论数组是否有序,都要遍历找最小值,执行次数约n2/2;

时间复杂度:O(n2)。

3.3新增:插入排序(O(n2))

核心逻辑: 把数组分成 "已排序部分" 和 "未排序部分",每次从未排序部分取第一个元素 ,插入到已排序部分的合适位置(类似打扑克时整理手牌)。

举个例子,数组[4,2,0,3,1,5,6,7]

第 1 轮:已排序部分是[4],取未排序的2,插入后变成[2,4]

第 2 轮:已排序部分是[2,4],取未排序的0,插入后变成[0,2,4]

第 3 轮:取未排序的3,插入到24之间,变成[0,2,3,4]

...... 直到所有元素插入完成。

最好情况:数组已经有序,每次插入只需要比较 1 次,总执行次数是n,时间复杂度O(n);

最坏情况:数组逆序,第i个元素需要比较i次(比如第 2 个元素比较 2 次,第 3 个比较 3 次...),总执行次数是1+2+...+(n−1)=n(n−1)/2,时间复杂度O(n2);

平均情况:时间复杂度也是O(n2)。

3.4 希尔排序(介于O(nlogn)和O(n2))

核心逻辑 :按 "间隔" 分组排序,逐步缩小间隔,最后用直接插入排序收尾。比如数组[5,7,4,2,0,3,1,6](长度 8):

第 1 轮:间隔 = 4,分成 4 组(5,0)(7,3)(4,1)(2,6),组内排序后得到[0,3,1,2,5,7,4,6]

第 2 轮:间隔 = 2,分成 2 组(0,1,5,4)(3,2,7,6),组内排序后得到[0,2,1,3,4,6,5,7]

第 3 轮:间隔 = 1,直接插入排序得到有序数组;

时间复杂度:和间隔选择有关,通常介于O(nlogn)和O(n2)之间。

相关推荐
SmoothSailingT25 分钟前
408每日一题——数据结构
数据结构·考研·408
im_AMBER3 小时前
Leetcode 99 删除排序链表中的重复元素 | 合并两个链表
数据结构·笔记·学习·算法·leetcode·链表
s砚山s4 小时前
代码随想录刷题——二叉树篇(十三)
数据结构·算法
ulias2124 小时前
AVL树的实现
开发语言·数据结构·c++·windows
黎雁·泠崖4 小时前
二叉树知识体系全梳理:从基础到进阶一站式通关
c语言·数据结构·leetcode
蜕变菜鸟4 小时前
JS的Object.keys()和sort()排序的用法
数据结构·算法
镜中人★4 小时前
408数据结构考纲知识点(更新中)
数据结构
杜子不疼.5 小时前
【LeetCode30_滑动窗口 + 哈希表】:三招搞定“串联所有单词的子串”
数据结构·算法·哈希算法
妹妹够啦5 小时前
1. 两数之和
数据结构·算法·leetcode
vyuvyucd5 小时前
Java数组与Arrays类实战指南
数据结构·算法