算法与数据结构

烂漫一生 提交于 2019-12-05 16:36:13

代码基于Python3

1. 算法的特征?

  1. 有穷性: 一个算法必须保证执行有限步骤之后结束;
  2. 确切性: 算法的每一步骤必须有确切的定义;
  3. 输入:一个算法有 0 个或多个输入,以刻画运算对象的初始情况,所谓 0 个输入是指算法本身给出了初始条件;
  4. 输出:一个算法有一个或多个输出,以反映对输入数据加工后的结果。没有输出的算法是毫无意义的;
  5. 可行性: 算法原则上能够精确地运行,而且人们用笔和纸做有限次数运算后即可完成。

2.冒泡排序的思想

  • 冒泡思想:通过无序区中相邻记录的关键字间的比较和位置的交换,使关键字最小的记录像气泡一样逐渐向上漂至水面。整个算法是从最下面的记录开始,对每两个相邻的关键字进行比较,把关键字较小的记录放到关键字较大的记录的上面,经过一趟排序后,关键字最小的记录到达最上面,接着再在剩下的记录中找关键字次小的记录,把它放在第二个位置上,依次类推,一直到所有记录有序为止
  • 复杂度:时间复杂度为 O(n²),空间复杂度为 O(1)
def bubble_sort(alist):
    """冒泡排序"""
    for j in range(len(alist)-1, 0, -1):
        # j表示每次遍历需要比较的次数,是逐渐减小的
        for i in range(j):
            if alist[i] > alist[i+1]:
                alist[i], alist[i+1] = alist[i+1], alist[i]
                
li = [45, 75, 86, 12, 35, 99, 68, 8, 55, 23]
bubble_sort(li)
print(li)
[8, 12, 23, 35, 45, 55, 68, 75, 86, 99]

3.快速排序

  • 基本思想:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。
  • 复杂度:快速排序是不稳定的排序算法,最坏的时间复杂度是 O(n²),最好的时间复杂度是(nlogn),空间复杂度为 O(logn)
def quick_sort(alist, start, end):
    """快速排序"""
    # 递归出口
    if start >= end:
        return
    
    low = start
    high = end
    pivot_value = alist[start]
    
    while low < high:
        while low < high and alist[high] >= pivot_value:
            high -= 1
        alist[low] = alist[high]

        while low < high and alist[low] < pivot_value:
            low += 1
        alist[high] = alist[low]
    
    alist[low] = pivot_value
    
    quick_sort(alist, start, low-1)
    quick_sort(alist, low+1, end)
    
li = [45, 75, 86, 12, 35, 99, 68, 8, 55, 23]
quick_sort(li, 0, len(li)-1)
print(li)    
[8, 12, 23, 35, 45, 55, 68, 75, 86, 99]

4.如何判断单向链表中是否有环?

  • 思路一:首先遍历链表,寻找是否有相同地址,借此判断链表中是否有环。如果程序进入死循环,则需要一块空间来存储指针,遍历新指针时将其和储存的旧指针比对,若有相同指针,则该链表有环,否则将这个新指针存下来后继续往下读取,直到遇见 NULL,这说明这个链表无环。
class Solution1:
    """
    思路分析:
    判断一个单链表是否有环,
    可以用 set 存放每一个 节点, 这样每次 访问后把节点丢到这个集合里面.
    其实 可以遍历这个单链表, 访问过后,
    如果这个节点 不在 set  里面, 把这个节点放入到 set 集合里面.
    如果这个节点在  set 里面 , 说明曾经访问过, 所以这个链表有重新 走到了这个节点, 因此一定有环.

    如果链表都走完了, 把所有的节点都放完了. 还是没有重复的节点, 那说明没有环.
    """
    def hasCycle(self, head):
        mapping = set()
        flag = False
        p = head

        while p:
            if p not in mapping:
                mapping.add(p)
            else:
                flag = True
                break
            p = p.next

        return flag
  • 思路二:用快慢指针
class Solution:
    """
    定义 两个指针, 一个快指针fast, 一个慢指针slow,  快指针一次都两步,慢指针一次走一步. 
    如果 两个指针相遇了, 则说明链表是有环的. 
    如果 fast 都走到null了, 还没有相遇则说明没有环. 
    """
    def hasCycle(self, head):
        flag = False
        if head is None or head.next is None or head.next.next is None:
            return flag

        fast = head.next.next
        slow = head.next

        while fast is not slow:
            if fast.next is None or fast.next.next is None:
                # no circle
                return flag
            fast = fast.next.next
            slow = slow.next

        # 相遇肯定有环
        if fast is slow:
            # hasCircle
            flag = True

        return flag


if __name__ == '__main__':
    pass
    

引申→快速找到未知长度单链表的中间节点

  • 快慢指针,核心思想:快指针每次走2个结点,慢指针每次走1个结点,当快指针走完链表,慢指针刚好走到中间

5.基础的数据结构有哪些?

  • 集合:集合中的每一个数据元素都是相互独立的
  • 线性结构:数据之间是一对一的关系
  • 树形结构:数据之间存在一对多的关系。
  • 图状结构或者网状结构:数据元素间是多对多的关系。

6. 基本的算法有哪些,怎么评价一个算法的好坏?

  • 基本的算法有:
    • 排序算法(冒泡排序,插入排序, 快速排序, 归并排序), 查找(二分查找)
    • 搜索((DFS)深度优先搜索,(BFS)广度优先搜索),(Dijkstra 算法),动态规划算法
    • 分类(朴素贝叶斯分类算法等)。
  • 评价算法的好坏一般有两种: 时间复杂度和空间复杂度。
    • 时间复杂度:同样的输入规模(问题规模)话费多少时间。
    • 空间复杂度:同样的输入规模花费多少空间(主要是内存)。
      以上两点越小越好。
  • 稳定性:不会引文输入的不同而导致不稳定的情况发生。
  • 算法的思路是否简单:越简单越容易实现的越好。

7. 哪种数据结构可以实现递归?

栈可以实现,递归需要保存正在计算的上下文, 等待当前计算完成后弹出,再继续计算, 只有栈先进后出的特性才能实现。

8. 你知道哪些排序算法(一般是通过问题考算法)

冒泡, 选择, 快排, 归并。

9. 斐波那契数列

斐波那契数列:简单地说,起始两项为 0 和 1,此后的项分别为它的前两项之和。

def fibo(num):
    numList = [0, 1]
    for i in range(num - 2):
        numList.append(numList[-2] + numList[-1])
    return numList 

print(fibo(10))
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34]

10.二叉树如何求两个叶节点的最近公共祖先?

二叉树是搜索二叉树 :
1、原理:二叉搜索树是排序过的 ,位于左子树的结点都比父结点小,位于右子树的结点都比父结点大,我们只需从根节点开始和两个输入的结点进行比较,如果当前节点的值比两个结点的值都大,那么最低的公共祖先结点一定在该结点的左子树中,下一步开遍历当前结点的左子树。如果当前节点的值比两个结点的值都小,那么最低的公共祖先结点一定在该结点的右子树中,下一步开遍历当前结点的右子树。这样从上到下找到第一个在两个输入结点的值之间的结点。

2、实现代码 :

class TreeNode(object):
    def __init__(self, left=None, right=None, data=None):
        self.data = data
        self.left = left
        self.right = right
    def getCommonAncestor(root, node1, node2):
        while root:
            if root.data > node1.data and root.data > node2.data:
               root = root.left
            elif root.data < node1.data and root.data < node2.data:
                root = root.right
            else:
                return root
        return None

11.两个字符串,如何求公共字符串?

def getLCString(str1, str2):
    maxlen = len(str1) if len(str1) < len(str2) else len(str2)  # 较短的字符串长度
    example = str1 if len(str1) < len(str2) else str2  # 较短的字符串
    other = str2 if str1 == example else str1  # 较长的字符串
    for i in range(maxlen):
        for j in range(maxlen, 0,  -1):
            if other.find(example[i:j]) != -1:
                return example[i:j]
            
str1 = "dhbfkdgfhahahbvufhie"
str2 = "eurhernjefgvyfbhaharygufn"
a = getLCString(str1, str2)
print(a)
h
def bull_sort(alist):
    for i in (len(alist) - 1):
        for j in (len(alist) - 1 - i):
            if alist[j] > alist[j + 1]:
                alist[j] , alist[j +1] = alist[j + 1], alist[j]
    return alist    
def quick_sort(arr):
    """快速排序"""
    if len(arr) < 2:
        return arr
    mid = arr[len(arr) // 2]
    left, right = [], []
    arr.remove(mid)
    for item in arr:
        if item < mid:
            start.append(item)
        else:
            end.append(item)
    return quick_sort(left) + [mid] + quick_sort(right)
        
def bubble_sort(arr):
    for i in (len(arr) - 1):
        for j in (len(arr) - 1 - i):
            if arr[j] > arr[j + 1]:
                arr[j], arr[j + 1] = arr[j + 1], arr[j]
    return arr
list(range(10, 5, -1))
[10, 9, 8, 7, 6]
def selection_sort(arr):
    """选择排序"""
    for i in (len(arr) - 1):
        min_index = i
        for j in (i + 1, len(arr)):
            if arr[j] < arr[min_index]:
                min_index = j
        arr[min_index], arr[i] = arr[i], arr[min_index]
    return arr
def insert_sort(arr):
    """插入排序"""
    for i in (1, len(arr)):
        current = arr[i]
        pre_index = i - 1
        while pre_index >= 0 and arr[pre_index] > current:
            arr[pre_index + 1] = arr[pre_index]
            pre_index -= 1
        arr[pre_index + 1] = current
    return arr
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!