Python 必做算法题(一)

一、排序算法

快速排序

问题:排序一个列表

解题思路:从索引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)

Python 快速排序 | 菜鸟教程

选择排序

问题:排序一个列表

解题思路:每次找最小的值,把最小的值找到之后放到前面,然后再在剩下的元素里面找最小值;

# -*-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)

解题思路:

左下角和右上角这两个点有一个非常有用的特征,左下角的上面必定比自己小,右边必定比自己大。

  1. 首先判断边界空值的情况。
  2. 已左下角作为起点,值大于目标值则x-1,小于目标值则y+1,相同则返回true。
  3. 若是移动到了矩阵边界也没找到,说明矩阵中不存在目标值。

代码实现:

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)是一种常见的树状数据结构,它由一组节点组成,每个节点最多有两个子节点,分别称为左子节点和右子节点。二叉树具有以下特点:

  1. 每个节点最多有两个子节点,分别称为左子节点和右子节点。
  2. 左子树和右子树也是二叉树,它们的结构与父节点类似。
  3. 二叉树的顺序不固定,可以是任意形状。

相关算法待补充

四、链表

链表实现

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)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Qing_er爱吃山竹

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值