1.数据结构&算法的引言+时间复杂度

数据结构&算法的引言+时间复杂度

  • 一.什么是计算机科学?

    • 首先明确的一点就是计算机科学不仅仅是对计算机的研究,虽然计算机在科学发展的过程中发挥了重大的作用,但是它只是一个工具,一个没有灵魂的工具而已。所谓的计算机科学实际上是对问题、解决问题以及解决问题的过程中产生产生的解决方案的研究。例如给定一个问题,计算机科学家的目标是开发一个算法来处理该问题,最终得到该问题的解、或者最优解。所以说计算机科学也可以被认为是对算法的研究。因此我们也可以感受到,所谓的算法就是对问题进行处理且求解的一种实现思路或者思想。
  • 二.如何形象化的理解算法?
    • 案例引导:

      • 一个常胜将军在作战之前都会进行战略的制定,目的是为了能够在最短的时间切成本消耗最低的情况下获取最终的胜利。如果将编码作为战场,则程序员就是这场战役的指挥官,你如何可以将你的程序可以在最短且消耗资源最小的情况下获取最终的执行结果呢?算法就是我们的策略!
    • 意义所在:
      • 数据结构和算法思想的通用性异常的强大,在任何语言中都被使用,它们将会是我们编码生涯中伴随我们最长久利器(左膀右臂)。有一定经验的程序员最终拼的就是算法和数据结构。
      • 数据结构和算法思想也可以帮助我们拓展和历练编码的思维,可以让我们更好的融入到编程世界的角角落落。
  • 三.什么是算法分析?
    • 案例引入:

      • 刚接触编程的学生经常会将自己编写的程序和别人的程序做比对,获取在比对的过程中会发现双方编写的程序很相似但又各不相同。那么就会出现一个有趣的现象:两组程序都是用来解决同一个问题的,但是两组程序看起来又各不相同,那么哪一组程序更好呢?例如下述代码:

        #方案一
        def sumOfN(n):
            theSum = 0
            for i in range(1,n+1):
                theSum = theSum + i
        
            return theSum
        
        print(sumOfN(10))
        
        #方案二
        def foo(tom):
            fred = 0
            for bill in range(1,tom+1):
                barney = bill
                fred = fred + barney
        
            return fred
        
        print(foo(10))
        • 分析:很明显上述两中问题的解决方案是不同的。那如何判定上述两种解决方案(算法)的优劣呢?有同学会说,观察计算两种算法使用耗费计算机资源的大小和它们的执行效率呀!但是我想说的是,一些较为复杂的算法,它耗费计算机资源的大小和执行效率我们很难能够直观的从算法的编码上分析出来。所以我们必须采用某种量化的方式求出不同算法的资源耗费和执行效率的具体值来判定算法之间的优劣。问题来了,如何进行量化计算呢?方法有两种:

          #方法1:计算算法执行的耗时(不推荐)。
          import time
          start_time = time.time()
          for a in range(0,1001):
              for b in range(0,1001):
                  for c in range(0,1001):
                      if a**2+b**2 == c**2 and a+b+c==1000:
                          print(a,b,c)
          end_time = time.time()
          print(end_time-start_time)
          
          #执行结果为:
          0 500 500
          200 375 425
          375 200 425
          500 0 500
          1221.7778379917145
          
          #方法2:计算算法的时间复杂度(推荐)
          import time
          start_time = time.time()
          for a in range(0,1001):
              for b in range(0,1001):
                  c = 1000 - a - b
                  if a**2+b**2 == c**2 and a+b+c==1000:
                          print(a,b,c)
          end_time = time.time()
          print(end_time-start_time)
          
          #执行结果为:
          0 500 500
          200 375 425
          375 200 425
          500 0 500
          1.410386085510254
          • 注意:单靠执行时间可以反应算法的效率吗?不能。跟机器(执行环境)存在很大关系。
  • 四.时间复杂度
    • 时间复杂度:量化算法需要的操作或者执行步骤的数量。
    • 我们试图通过算法的执行时间来判定算法的优劣。但是仅仅根据执行时间判定算法优劣有些片面,因为算法是独立于计算机的。重要的是量化算法需要的操作或者步骤的数量。选择适当的基本计算单位是个复杂的问题,并且将取决于如何实现算法。对于先前的求和算法,一个比较好的基本计算单位是对执行语句进行计数。
    • 在 sumOfN 中,赋值语句的计数为 1(theSum = 0) 加上 n 的值(我们执行 theSum=theSum+i 的次数)。我们通过函数 T 表示 T(n)=1+n。参数 n 通常称为“问题的规模”,我们称作 “T(n) 是解决问题大小为 n 所花费的时间,即 1+n 步长”。在上面的求和函数中,使用 n 来表示问题大小是有意义的。我们可以说,100,000 个整数和比 1000 个问题规模大。因此,所需时间也更长。我们的目标是表示出算法的执行时间是如何相对问题规模大小而改变的。
    • 计算机科学家更喜欢将这种分析技术进一步扩展。事实证明,操作步骤数量不如确定 T(n) 最主要的部分来的重要。换句话说,当问题规模变大时,T(n) 函数某些部分的分量会超过其他部分。函数的数量级表示了随着 n 的值增加而增加最快的那些部分。
    • 数量级通常称为大O符号,写为 O(f(n))。它表示对计算中的实际步数的近似。函数 f(n) 提供了 T(n) 最主要部分的表示方法。T(n)的最主要部分是:在上述示例中,T(n)=1+n。当 n 变大时,常数 1 对于最终结果变得越来越不重要。如果我们找的是 T(n) 的近似值,我们可以删除 1。因此T(n)中最主要的部分为n,因此f(n)=n。因此在sumOfN函数对应的算法的时间复杂度可即为O(f(n)),即为O(n)。
    • 另外一个示例,假设对于一些算法,确定的步数是 T(n)=5n^2+27n+1005。当 n 很小时, 例如 1 或 2 ,常数 1005 似乎是函数的主要部分。然而,随着 n 变大,n^2 这项变得越来越重要。事实上,当 n 真的很大时,其他两项在它们确定最终结果中所起的作用变得不重要。当 n 变大时,为了近似 T(n),我们可以忽略其他项,只关注 5n^2 。系数 5 也变得不重要。我们说,T(n) 具有的数量级为 f(n)=n^2,或者 O( n^2 )。
    • 常见的时间复杂度:O(1) < O(logn) < O(n) < O(nlogn) < O(n^2) < O(n^3) < O(2^n) < O(n!) < O(n^n)
    • 案例分析:计算下列算法的时间复杂度
       1 a=5
       2 b=6
       3 c=10
       4 for i in range(n):
       5    for j in range(n):
       6       x = i * i
       7       y = j * j
       8       z = i * j
       9 for k in range(n):
      10    w = a*k + 45
      11    v = b*b
      12 d = 33
    • 分析:前三行赋值语句执行操作步骤为3,5-8行的执行操作步骤为3n,结合第四行的外部循环,整个内外循环的执行步骤为3n^2。9-11行为2n,12行为1。最终得出T(n)=3+3n^2+2n+1,简化操作后T(n)=3n^2+2n+4。通过查看指数,我们可以看到 n^2 项是最重要的,因此这个代码段是 O(n^ 2)。当 n 增大时,所有其他项以及主项上的系数都可以忽略。
  • 五.数据结构:
    • 对于数据(基本类型的数据(int,float,char))的组织方式就被称作为数据结构。数据结构解决的就是一组数据如何进行保存,保存形式是怎样的。
    • 案例:需要存储一些学生的学生信息(name,score),那么这些数据应该如何组织呢?查询某一个具体学生的时间复杂度是什么呢?
      • 组织形式1:

        [{'name':'zhangsan','score':100},
         {'name':'lisi','score':99}
        ]
      • 组织形式2:
        [('zhangsan',100),
         ('lisi',99)
        ] 
      • 组织形式3:
        {'zhangsan':{'score':100},
         'lisi':{'score':99}
        } 
    • 三种组织形式基于查询的时间复杂度分别为:O(n),O(n),O(1)
    • 发现:python中的字典,列表,元组本身就是已经被封装好的一种数据结构啦。使用不同的数据结构进行数据的存储,所导致的时间复杂度是不一样。因此认为算法是为了解决实际问题而设计的,数据结构是算法需要处理问题的载体。

原文地址:https://www.cnblogs.com/Godisgirl/p/11025888.html

时间: 2024-11-06 07:38:33

1.数据结构&算法的引言+时间复杂度的相关文章

【数据结构&amp;&amp;算法系列】KMP算法介绍及实现(c++ &amp;&amp; java)

KMP算法如果理解原理的话,其实很简单. KMP算法简介 这里根据自己的理解简单介绍下. KMP算法的名称由三位发明者(Knuth.Morris.Pratt)的首字母组成,又称字符串查找算法. 个人觉得可以理解为最小回溯算法,即匹配失效的时候,尽量少回溯,从而缩短时间复杂度. KMP算法有两个关键的地方,1)求解next数组,2)利用next数组进行最小回溯. 1)求解next数组 next数组的取值只与模式串有关,next数组用于失配时回溯使用. 在简单版本的KMP算法中,每个位置 j 的 n

微软等数据结构+算法面试100题全部答案集锦

1.把二元查找树转变成排序的双向链表. 题目: 输入一棵二元查找树,将该二元查找树转换成一个排序的双向链表. 要求不能创建任何新的结点,只调整指针的指向. 10  / \  6 14  / \ / \  4 8 12 16 转换成双向链表 4=6=8=10=12=14=16. 首先我们定义的二元查找树节点的数据结构如下: struct BSTreeNode  {  int m_nValue; // value of node  BSTreeNode *m_pLeft; // left child

day40 数据结构-算法(二)

什么是数据结构? 简单来说,数据结构就是设计数据以何种方式组织并存储在计算机中. 比如:列表.集合与字典等都是一种数据结构. N.Wirth: "程序=数据结构+算法" 列表 列表:在其他编程语言中称为"数组",是一种基本的数据结构类型. 关于列表的问题: 列表中元素使如何存储的? 列表提供了哪些基本的操作? 这些操作的时间复杂度是多少? 列表与可变对象* 栈 栈(Stack)是一个数据集合,可以理解为只能在一端进行插入或删除操作的列表. 栈的特点:后进先出(las

数据结构算法——算法复杂度分析

算法复杂度分为时间复杂度和空间复杂度 首先要清楚一点,大O表示法的时间复杂度高不代表程序运行时间长,空间复杂度高不代表占用空间多. 他们表示的是代码执行时间随着数据规模增长的变化趋势.和算法储存空间与数据规模之间的增长关系. 时间复杂度判断方法 1.只关注循环次数最多的一段代码 2.加法法则:总复杂度等于量级最大的那段代码的复杂度 3.乘法原则:嵌套代码的复杂度等于嵌套内外代码复杂度的乘积 常见的复杂度量级(按数量级递增) 常量阶:O(1) 对数阶:O(logn) 线性阶:O(n) 线性对数阶:

算法基础 -- 简介时间复杂度与空间复杂度

算法是为求解一个问题所需要遵循的.被清楚地指定的简单指令的集合.对于一个问题,一旦给定某种算法并且确定其实正确的,那么重要的一步就是确定该算法将需要多少诸如时间或空间等资源量的问题,这就是时间复杂度和空间复杂度存在的意义.常用时间复杂度和空间复杂度来衡量不同算法的优劣. 一.从数学的角度理解 O(n).Ω(n).o(n)和Θ(n) 通常,我们以函数所处理的数据量来表示算法的性能,也就是说,对于大小为 n 的数据,我们用函数 f(n) 来表示它的算法性能.在很多情况下,我们可以完全确定 f 的具体

第4章 数据结构算法

py内置数据结构算法常考 常用内置的算法和数据结构 sorted list/set/dict/tuple 常用内置数据结构和算法 数据结构/算法 语言内置 内置库 线性结构 list(列表)/tuple(元组) array(数组, 不常用)/collections.namedtuple 链式结构 collections.deque(双端队列) 字典结构 dict(集合) collections.Counte(计数器)/OrderedDict(有序字典) 集合结构 set(集合)/frozense

算法 笔记1 时间复杂度计算

评价一个算法的优劣应该从三个方面判断 1.时间复杂度 : 执行算法所耗费的时间,即时间复杂度 2.空间复杂度 : 执行算法所耗费的存储空间,主要是辅助空间 3.可读性和可操作性 : 算法应当易于理解,易于编程,易于调试等 时间复杂度 一般情况下,将算法所要求求解问题的输入量称为问题的规模,并用一个正整数n来表示 T(n)就是该算法的时间耗费,他是该算法所求问题规模n的函数 算法中基本操作重复执行的次数时问题规模n的某个函数f(n) 算法的时间量度记为: T(n) = O(F(n)) 时间复杂度的

数据结构算法1------算法和算法分析

最近面试iOS实习生.几次都是败在数据结构算法上面了.决定重新捡起大学的课本,复习一下数据结构算法相关知识. 1.反转一个链表.循环算法.               1     List   reverse(List   l)   {       2     if(!l)   return   l;       3         list   cur   =   l.next;       4     list   pre   =   l;       5     list   tmp;  

[数据结构]算法

算法定义 算法是解决特定问题求解步骤的描述,在计算机中表现为指令的有限序列,并且每条指令表示一个或多个操作 算法特性 有穷性(死循环) 确定性(除零) 可行性 有输入 有输出 算法设计要求 正确性 可读性 健壮性 高效率和低存储量需求 算法描述 如何描述输出型参数 C++语言中提供引用运算符"&"用于描述输出型参数. int a=10; int &b=a; a.b两个变量共享内存空间-->a.b同步发生改变 示例:交换两个整数的算法. 编写一个函数swap1(x,