📜  竞争性编程的十大算法和数据结构(1)

📅  最后修改于: 2023-12-03 15:41:06.422000             🧑  作者: Mango

竞争性编程的十大算法和数据结构

竞争性编程是一种以赛制为主的编程比赛,常常用于测试程序员们的编程技巧和算法能力。在这种比赛中,时间和空间复杂度往往是决定胜负的关键因素。因此,掌握一些基本的算法和数据结构是非常重要的。下面介绍竞争性编程中最常用的十大算法和数据结构。

1. 排序算法

在竞争性编程中,时间复杂度是非常重要的。因此,排序算法是必不可少的一个部分。最常用的排序算法有冒泡排序、选择排序、插入排序、归并排序和快速排序。这些排序算法的时间复杂度分别为O(n^2)、O(n^2)、O(n^2)、O(nlogn)和O(nlogn)。

# 归并排序示例代码
def merge_sort(arr):
    if len(arr) > 1:
        mid = len(arr) // 2
        left_half = arr[:mid]
        right_half = arr[mid:]

        merge_sort(left_half)
        merge_sort(right_half)

        i = 0
        j = 0
        k = 0

        while i < len(left_half) and j < len(right_half):
            if left_half[i] < right_half[j]:
                arr[k] = left_half[i]
                i += 1
            else:
                arr[k] = right_half[j]
                j += 1
            k += 1

        while i < len(left_half):
            arr[k] = left_half[i]
            i += 1
            k += 1

        while j < len(right_half):
            arr[k] = right_half[j]
            j += 1
            k += 1
2. 哈希表

哈希表是一种数据结构,可以用来存储和检索键值对。在竞争性编程中,哈希表被广泛用于对数进行计数。哈希表的时间复杂度为O(1)。

# 哈希表示例代码
table = {}

# 给哈希表添加键值对
table['apple'] = 1
table['banana'] = 2
table['orange'] = 3

# 访问哈希表的键值对
print(table['apple'])   # 输出1
print(table['banana'])  # 输出2
print(table['orange'])  # 输出3
3. 队列

队列是一种基本的数据结构,可以用来实现先进先出的操作。在竞争性编程中,队列通常用于广度优先搜索的算法中。队列的时间复杂度为O(1)。

# 队列示例代码
class Queue:
    def __init__(self):
        self.items = []

    def enqueue(self, item):
        self.items.insert(0, item)

    def dequeue(self):
        return self.items.pop()

    def is_empty(self):
        return len(self.items) == 0

    def size(self):
        return len(self.items)

q = Queue()
q.enqueue(1)
q.enqueue(2)
q.enqueue(3)
print(q.dequeue()) # 输出1
print(q.dequeue()) # 输出2
print(q.dequeue()) # 输出3
4. 栈

栈是一种基本的数据结构,可以用来实现后进先出的操作。在竞争性编程中,栈通常用于深度优先搜索的算法中。栈的时间复杂度为O(1)。

# 栈示例代码
class Stack:
    def __init__(self):
        self.items = []

    def push(self, item):
        self.items.append(item)

    def pop(self):
        return self.items.pop()

    def is_empty(self):
        return len(self.items) == 0

    def size(self):
        return len(self.items)

s = Stack()
s.push(1)
s.push(2)
s.push(3)
print(s.pop()) # 输出3
print(s.pop()) # 输出2
print(s.pop()) # 输出1
5. 二分查找

二分查找是一种基本的搜索算法,可以在有序列表中查找特定元素。在竞争性编程中,二分查找通常用于搜索最优解等问题。二分查找的时间复杂度为O(logn)。

# 二分查找示例代码
def binary_search(arr, x):
    low, high = 0, len(arr)-1
    while low <= high:
        mid = (low + high) // 2
        if arr[mid] < x:
            low = mid + 1
        elif arr[mid] > x:
            high = mid - 1
        else:
            return mid
    return -1
6. 并查集

并查集是一种用于处理集合的数据结构,可以用于动态连通性的问题。在竞争性编程中,并查集通常用于间接的查找元素。并查集的时间复杂度为O(logn)。

# 并查集示例代码
class DSU:
    def __init__(self, n):
        self.parent = list(range(n))

    def find(self, x):
        if self.parent[x] != x:
            self.parent[x] = self.find(self.parent[x])
        return self.parent[x]

    def union(self, x, y):
        self.parent[self.find(x)] = self.find(y)

dsu = DSU(5)
dsu.union(1, 2)
dsu.union(3, 4)
dsu.union(4, 1)
print(dsu.find(1)) # 输出2
print(dsu.find(3)) # 输出4
7. 最短路算法

最短路算法是一种用于查找两点之间最短路径的算法。在竞争性编程中,最短路算法通常用于搜索最优解等问题。最短路算法的时间复杂度为O(E+VlogV),其中E为边数,V为顶点数。

# 最短路算法示例代码
import heapq

def dijkstra(graph, start):
    distances = {v: float('infinity') for v in graph}
    distances[start] = 0
    pq = [(0, start)]
    while pq:
        current_distance, current_vertex = heapq.heappop(pq)
        if current_distance > distances[current_vertex]:
            continue
        for neighbor, weight in graph[current_vertex].items():
            distance = current_distance + weight
            if distance < distances[neighbor]:
                distances[neighbor] = distance
                heapq.heappush(pq, (distance, neighbor))
    return distances

graph = {
    'A': {'B': 2, 'C': 3},
    'B': {'A': 2, 'C': 1},
    'C': {'A': 3, 'B': 1}
}

print(dijkstra(graph, 'A')) # 输出{'A': 0, 'B': 2, 'C': 3}
8. 动态规划

动态规划是一种算法思想,用于解决重叠子问题的最优解问题。在竞争性编程中,动态规划通常用于计算最大子序列、最长上升子序列等问题。动态规划的时间复杂度为O(n^2),其中n为问题的规模。

# 动态规划示例代码
def max_subarray(nums):
    dp = [0] * len(nums)
    dp[0] = nums[0]
    for i in range(1, len(nums)):
        dp[i] = max(nums[i], nums[i] + dp[i-1])
    return max(dp)

print(max_subarray([-2,1,-3,4,-1,2,1,-5,4])) # 输出6
9. 贪心算法

贪心算法是一种算法思想,用于解决最优化问题。在竞争性编程中,贪心算法通常用于计算最大价值、最小花费等问题。贪心算法的时间复杂度为O(nlogn),其中n为问题的规模。

# 贪心算法示例代码
def max_profit(prices):
    profit = 0
    for i in range(1, len(prices)):
        if prices[i] > prices[i-1]:
            profit += prices[i] - prices[i-1]
    return profit

print(max_profit([7, 1, 5, 3, 6, 4])) # 输出7
10. 分治算法

分治算法是一种算法思想,用于解决子问题并组合最终答案。在竞争性编程中,分治算法通常用于计算最大子数组、最近点对等问题。分治算法的时间复杂度为O(nlogn),其中n为问题的规模。

# 分治算法示例代码
def max_subarray(nums, l, h):
    if l == h:
        return nums[l]
    mid = (l + h) // 2
    left_sum = max_subarray(nums, l, mid)
    right_sum = max_subarray(nums, mid+1, h)
    cross_sum = cross_subarray(nums, l, mid, h)
    return max(left_sum, right_sum, cross_sum)

def cross_subarray(nums, l, mid, h):
    left_sum = float('-inf')
    s = 0
    for i in range(mid, l-1, -1):
        s += nums[i]
        left_sum = max(left_sum, s)

    right_sum = float('-inf')
    s = 0
    for i in range(mid+1, h+1):
        s += nums[i]
        right_sum = max(right_sum, s)

    return left_sum + right_sum

arr = [-2,1,-3,4,-1,2,1,-5,4]
print(max_subarray(arr, 0, len(arr)-1)) # 输出6

以上是竞争性编程的十大算法和数据结构。掌握这些算法和数据结构可以提高你在竞争性编程中的成绩,也会使你成为一个更好的程序员。