一、排序算法
快速排序
问题:排序一个列表
解题思路:从索引0到索引末尾,以此对比,如果i索引的位置小于pivot,也就是把比pivot小的,也就是arr[j]挪到前面,最开始挪的位置是索引0,然后再继续对比和pivot,比pivot小就把j的位置和i+1的位置互调;
做完之后把i+1的位置输出。
然后递归去实现循环,结束的条件是头和尾巴相等,也就是low=high
def partition(arr, low, high):
i = (low - 1) # 最小元素索引
pivot = arr[high]
for j in range(low, high):
# 当前元素小于或等于 pivot
if arr[j] <= pivot:
i = i + 1
arr[i], arr[j] = arr[j], arr[i]
arr[i + 1], arr[high] = arr[high], arr[i + 1]
return i + 1
# arr[] --> 排序数组
# low --> 起始索引
# high --> 结束索引
# 快速排序函数
def quickSort(arr, low, high):
if low < high:
pi = partition(arr, low, high)
quickSort(arr, low, pi - 1)
quickSort(arr, pi + 1, high)
if __name__ == '__main__':
arr_ = [10, 7, 8, 9, 1, 5]
print('原始数据列', arr_)
n = len(arr_)
quickSort(arr_, 0, n - 1)
选择排序
问题:排序一个列表
解题思路:每次找最小的值,把最小的值找到之后放到前面,然后再在剩下的元素里面找最小值;
# -*-coding:utf-8-*-
def select_sort(alist):
n = len(alist)
for j in range(n-1):
min_index = j
for i in range(j+1, n):
if alist[min_index] > alist[i]:
min_index = i
alist[j], alist[min_index] = alist[min_index], alist[j]
if __name__ == '__main__':
ls = [3, 5, 1, 10, 4]
select_sort(alist=ls)
print(ls)
时间复杂度:n平方
冒泡排序
问题:排序一个列表
解题思路:从0索引到倒数第二的位置,循环0到n-1-j的位置,相邻两两对比,然后大的值往右边去小的值往左边去,这样做完,最大的值就会做最右边,也就是n-1的索引位置;然后再循环0到n-2位置的元素;
# -*-coding:utf-8-*-
def bubble_sort(alist):
"""冒泡排序"""
n = len(alist)
# j = 0
# for i in range(0, n - 1 - j):
# # 班长从头走到尾
# if alist[i] > alist[i + 1]:
# alist[i], alist[i + 1] = alist[i + 1], alist[i]
for j in range(0, n - 1):
count = 0 # 优化排序
for i in range(0, n - 1 - j):
# 班长从头走到尾
if alist[i] > alist[i + 1]:
alist[i], alist[i + 1] = alist[i + 1], alist[i]
count += 1
if 0 == count:
break
if __name__ == '__main__':
li = [9, 8, 7, 6, 2, 3, 4, 1]
print(li)
bubble_sort(li)
print(li)
时间复杂度:n平方
二、图算法
岛屿数量
问题:
给你一个由 '1'(陆地)和 '0'(水)组成的的二维网格,请你计算网格中岛屿的数量。岛屿总是被水包围,并且每座岛屿只能由水平方向和/或竖直方向上相邻的陆地连接形成。此外,你可以假设该网格的四条边均被水包围。
解题思路:
这道题的主要思路是深度优先搜索。每次走到一个是 1 的格子,就搜索整个岛屿。
网格可以看成是一个无向图的结构,每个格子和它上下左右的四个格子相邻。如果四个相邻的格子坐标合法,且是陆地,就可以继续搜索。
在深度优先搜索的时候要注意避免重复遍历。我们可以把已经遍历过的陆地改成 0,不进行重复遍历。
每遇到一个陆地格子就进行深度优先搜索,最终搜索了几次就知道有几个岛屿。
代码实现:
class Solution(object):
def numIslands(self, grid):
"""
:type grid: List[List[str]]
:rtype: int
"""
count = 0
def bfs(i, j):
if j >= len(grid[0]) or i >= len(grid) or j < 0 or i < 0 or grid[i][j] == '0':
return
grid[i][j] = '0'
bfs(i - 1, j)
bfs(i, j - 1)
bfs(i + 1, j)
bfs(i, j + 1)
for i, row in enumerate(grid):
for j, col in enumerate(row):
if col == '1':
bfs(i, j)
count += 1
return count
if __name__ == '__main__':
grid = [
["1", "1", "0", "1", "0"],
["1", "1", "0", "1", "0"],
["1", "1", "0", "0", "0"],
["0", "0", "0", "0", "0"]]
sol = Solution()
print(sol.numIslands(grid=grid))
二维数组中的查找
问题:
在一个二维数组array中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
[[1,2,8,9],
[2,4,9,12],
[4,7,10,13],
[6,8,11,15]]
给定 target = 7,返回 true。
给定 target = 3,返回 false。
数据范围:矩阵的长宽满足 0≤n,m≤500 , 矩阵中的值满足 0≤val≤109
进阶:空间复杂度 O(1) ,时间复杂度 O(n+m)
解题思路:
左下角和右上角这两个点有一个非常有用的特征,左下角的上面必定比自己小,右边必定比自己大。
- 首先判断边界空值的情况。
- 已左下角作为起点,值大于目标值则x-1,小于目标值则y+1,相同则返回true。
- 若是移动到了矩阵边界也没找到,说明矩阵中不存在目标值。
代码实现:
def find_num(array, num):
# 行数
rows = len(array)
# 行数
cols = len(array[0])
# 从最后一行的第一个元素开始判断
i = rows - 1
# 列的索引
j = 0
while i >= 0 and j <= cols - 1:
value = array[i][j]
if num > value:
j += 1
elif num < value:
i -= 1
else:
return True
return False
if __name__ == '__main__':
num_ = 10
array_ = [[1, 2, 8, 9],
[2, 4, 9, 12],
[4, 7, 10, 13],
[6, 8, 11, 15]]
ss = find_num(array=array_, num=num_)
print(ss)
三、二叉树
基础知识
二叉树(Binary Tree)是一种常见的树状数据结构,它由一组节点组成,每个节点最多有两个子节点,分别称为左子节点和右子节点。二叉树具有以下特点:
- 每个节点最多有两个子节点,分别称为左子节点和右子节点。
- 左子树和右子树也是二叉树,它们的结构与父节点类似。
- 二叉树的顺序不固定,可以是任意形状。
相关算法待补充
四、链表
链表实现
import random
class LNode(object):
def __init__(self, item, next_=None):
self.item = item
self.next = next_
class SingleLinkList(object):
"""
初始化单链表
"""
def __init__(self):
self.head = None
def is_empty(self):
"""链表是否为空"""
return self.head is None
def length(self):
"""获取链表长促"""
cur = self.head
count = 0
while cur:
count += 1
cur = cur.next
return count
def travel(self):
cur = self.head
while cur:
print(cur.item, end='')
if cur.next:
print(',', end='')
cur = cur.next
print('')
def append_front(self, item):
"""头部插入"""
self.head = LNode(item, self.head)
def append_rear(self, item):
"""尾部插入"""
node = LNode(item)
if self.is_empty():
self.head = node
else:
cur = self.head
while cur.next:
cur = cur.next
cur.next = node
def insert(self, item, pos):
"""在第pos个位置插入元素"""
if pos <= 1:
self.append_front(item)
elif pos > self.length():
self.append_rear(item)
else:
node = LNode(item)
cur = self.head
cur_pos = 1
while cur.next and cur_pos < pos - 1:
cur = cur.next
cur_pos += 1
node.next = cur.next
cur.next = node
def getitem(self, pos):
"""获取第pos个位置的元素"""
if pos < 1 or pos > self.length():
print('pos 超出范围')
return None
else:
cur = self.head
cur_pos = 1
while cur.next and cur_pos < pos:
cur = cur.next
cur_pos += 1
return cur.item
def pop(self):
"""移除头部元素"""
if self.is_empty():
print('SingleLinkList is empty')
else:
e = self.head.item
self.head = self.head.next
return e
def remove(self, pos):
"""删除第pos个位置元素"""
if pos < 1 or pos > self.length():
print('pos 超出范围')
elif pos == 1:
self.head = self.head.next
else:
cur = self.head
cur_pos = 1
while cur and cur_pos < pos - 1:
cur = cur.next
cur_pos += 1
cur.next = cur.next.next
if __name__ == '__main__':
SingleLinkList = SingleLinkList()
for i in range(1, 10): # 随机插入100个元素
SingleLinkList.append_rear(random.randint(1, 100))
SingleLinkList.travel()
a = SingleLinkList.head # a 每次走两步
b = SingleLinkList.head # b 每次走一步
while a.next:
if a.next.next:
a = a.next.next
b = b.next
else:
a = a.next
print(b.item)