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