1 算法基础

90 阅读3分钟

算法基础

算法概念

image-20240112105246405

时间复杂度

image-20240112105603398

image-20240112110315467

  • 时间复杂度:用来评估算法运行效率的一个式子

image-20240112110922768

image-20240112111424611

时间复杂度强调的是一个大概的时间(取最高阶)

image-20240112112450390

时间复杂度 - 小结

  • 时间复杂度是用来估计算法运行时间的一个式子(单位)。

  • 一般来说,时间复杂度高的算法比复杂度低的算法慢。

  • 常见的时间复杂度(按效率排序)

    • O(1)<O(logn)<O(n)<O(nlogn)<O(n2)<O(n2logn)<O(n3)O(1)<O(logn)<O(n)<O(nlogn)<O(n^2)<O(n^2logn)<O(n^3)
  • 复杂问题的时间复杂度

    • O(n!)O(2n)O(nn)...O(n!) O(2^n) O(n^n)...

如何简单快速地判断算法复杂度

  • 快速判断算法复杂度(适用于绝大多数简单情况):

    • 确定问题规模
    • 循环减半过程 ---> lognlogn
    • k层关于n的循环 ---> nkn^k
  • 复杂情况:根据算法执行过程判断

空间复杂度

  • 空间复杂度:用来评估算法内存占用大小的式子

  • 空间复杂度的表示方式与时间复杂度完全一样

    • 算法使用了几个变量:O(1)O(1)
    • 算法使用了长度为n的一维列表:O(n)O(n)
    • 多算法使用了m行n列的二维列表:O(mn)O(mn)
  • “空间换时间”【时间的优先级比较高】

复习:递归

image-20240112132912765

在上面的代码中,func1func2func3func4 都是递归函数,因为它们都调用了自身。然而,正确的递归函数需要有一个终止条件来防止无限递归。我们来分析一下每个函数:

  1. func1:没有终止条件。这个函数会无限地递减 x 并打印它,直到程序崩溃或者遇到栈溢出错误。
  2. func2:同样没有终止条件。这个函数在 x 大于0时会无限地递增 x 并打印它,直到程序崩溃或者遇到栈溢出错误。
  3. func3:有终止条件。当 x 不再大于0时,递归将停止。这个函数会打印从 x 开始递减到1的所有正整数。
  4. func4:也有终止条件。与 func3 类似,当 x 不再大于0时,递归将停止。不同的是,这个函数会在返回之前打印 x,所以它实际上会以升序打印从1到 x 的所有正整数。

因此,正确的递归函数是 func3func4,因为它们有适当的终止条件。

 #include <iostream>
 ​
 void func3(int x) {
     if (x > 0) {
         std::cout << x << std::endl;
         func3(x - 1);
     }
 }
 ​
 void func4(int x) {
     if (x > 0) {
         func4(x - 1);
         std::cout << x << std::endl;
     }
 }
 ​
 int main() {
     std::cout << "func3:" << std::endl;
     func3(5);  // 示例调用func3,将打印5到1的数字
 ​
     std::cout << "func4:" << std::endl;
     func4(5);  // 示例调用func4,将打印1到5的数字
 ​
     return 0;
 }

汉诺塔问题

image-20240116221658742

tower-of-Hanoi

image-20240116223253525

image-20240116231240600

 #include<iostream>
 using namespace std;
 ​
 //汉诺塔问题
 //起始杆A 中转杆B 目标杆C
 void hanoi(int n, char a, char b, char c)
 {
     if (n > 0)
     {
         hanoi(n - 1, a, c, b);
         
         printf("moving from %c to %c\n", a, c);
 ​
         hanoi(n - 1, b, a, c);
     }
 }
 ​
 int main()
 {
     int n = 3;
     char a = 'A';
     char b = 'B';
     char c = 'C';
 ​
     hanoi(n, a, b, c);
 ​
     system("pause");
 ​
     return 0;
 ​
 }
 moving from A to C
 moving from A to B
 moving from C to B
 moving from A to C
 moving from B to A
 moving from B to C
 moving from A to C
 请按任意键继续. . .
  • 汉诺塔移动次数的递推式:h(x)=2h(x1)+1h(x)=2h(x-1)+1
  • h(64)=18446744073709551615h(64)=18446744073709551615
  • 假设婆罗门每秒钟搬一个盘子,则总共需要5800亿年!

Snipaste_2024-01-16_22-34-14

Snipaste_2024-01-16_22-34-48

Snipaste_2024-01-16_22-35-25

Snipaste_2024-01-16_22-33-39