算法系列15天速成 第六天 五大经典查找【下】

算法系列15天速成 第六天 五大经典查找【下】- 完整攻略

简介

本篇文章是算法系列15天速成中的第六天内容,主要是介绍五大经典查找的后三种查找算法:插值查找、斐波那契查找以及分块查找。在介绍每一种查找算法时都会包含具体的思路、复杂度和应用场景等内容。

插值查找

思路

插值查找是在二分查找的基础上优化的一种查找算法,它不是通过数组的中间元素进行查找,而是通过插值公式计算出要查找的元素的位置。插值公式如下:

mid = left + (right-left)*(value-arr[left])/(arr[right]-arr[left])

其中value是要查找的元素,arr是已排序的数组。

复杂度

插值查找算法的时间复杂度为O(log n),在特定的情况下,它可以具有比二分查找更高的效率。

应用场景

插值查找可以用于均匀分布的有序数组中。

示例

# 插值查找实现
def interpolation_search(arr, value):
    left, right = 0, len(arr) - 1

    while left <= right and value >= arr[left] and value <= arr[right]:

        mid = left + (right-left)*(value-arr[left])//(arr[right]-arr[left])

        if arr[mid] == value:
            return mid

        elif arr[mid] < value:
            left = mid + 1

        else:
            right = mid - 1

    return -1

# 测试插值查找
arr = [1, 3, 5, 7, 9, 11]
value = 5
print(interpolation_search(arr, value))

斐波那契查找

思路

斐波那契查找是对插值查找算法的进一步优化,它使用斐波那契数列的值来计算要查找的值在数组中的位置。具体来说,要查找的值value在第n个斐波那契数列中出现,使用斐波那契数列的前两个值F(k)F(k-1)来计算要查找的值在数组中的位置。具体过程可以参考:https://www.cnblogs.com/maybe2030/p/4715035.html

复杂度

斐波那契查找算法的时间复杂度为O(log n)。

应用场景

斐波那契查找可以用于有序数组中。

示例

# 斐波那契查找实现
def fibonacci_search(arr, value):
    left, right = 0, len(arr) - 1

    # 构建斐波那契数列
    fib = [0, 1, 1]
    while fib[-1] < len(arr):
        fib.append(fib[-1] + fib[-2])

    # 在斐波那契数列中寻找 value 对应的位置
    k = 0
    while fib[k+1] < len(arr):
        k += 1
    offset = fib[k-1]
    while True:
        if value > arr[right]:
            return -1
        if value < arr[left]:
            return -1
        if left > right:
            return -1

        mid = left + offset
        if value < arr[mid]:
            right = mid - 1
            offset = offset - fib[k-2]
            k -= 1
        elif value > arr[mid]:
            left = mid + 1
            offset = offset - fib[k-1]
            k -= 2
        else:
            return mid

分块查找

思路

分块查找是一种数据分块技术,它将一个大的数据集分割成若干块,并且每一块的数据是有序的,块与块之间的数据无序,这样做的目的是使得查找的复杂度降低。

复杂度

分块查找算法的时间复杂度为O(sqrt(n)),空间复杂度为O(n)。

应用场景

分块查找可以用于难以排序的大规模数据中。

示例

# 分块查找实现
from math import sqrt, ceil

def block_search(arr, value):
    n = len(arr)                          # 数据集大小
    block_size = ceil(sqrt(n))            # 计算分块块长
    block_num = ceil(n / block_size)      # 计算分块数量

    # 计算块的范围,预处理数据块
    blocks = []
    for i in range(block_num):
        left = i * block_size 
        right = min(left + block_size, n)
        blocks.append({'left': left, 'right': right, 'data': arr[left:right]})

    # 在块内二分查找
    target_block = -1
    for i in range(block_num):
        if arr[blocks[i]['left']] <= value <= arr[blocks[i]['right']-1]:
            target_block = i
            break
    if target_block == -1:
        return -1
    else:
        target_index = binary_search(blocks[target_block]['data'], value)
        return blocks[target_block]['left'] + target_index

# 二分查找
def binary_search(arr, value):
    left, right = 0, len(arr) - 1
    while left <= right:
        mid = (left + right) // 2
        if arr[mid] == value:
            return mid
        elif arr[mid] < value:
            left = mid + 1
        else:
            right = mid - 1
    return -1

# 测试分块查找
arr = [5, 2, 7, 9, 1, 3, 11, 6, 8, 4, 12, 10]
value = 10
print(block_search(arr, value))

总结

本文介绍了插值查找、斐波那契查找和分块查找算法,这三种查找算法都是在二分查找的基础上进行的优化,分别针对了不同的场景和数据特点进行了优化。这些算法适用的场景也不尽相同,需要根据具体情况选择适合的算法进行使用。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:算法系列15天速成 第六天 五大经典查找【下】 - Python技术站

(0)
上一篇 2023年5月19日
下一篇 2023年5月19日

相关文章

  • C语言中的结构体快排算法

    C语言中的结构体快排算法 在C语言中,复杂的数据类型可以通过结构体定义。结构体是一种自定义类型,可以由不同类型的变量组成。快速排序算法是一种高效的排序算法,通过十分巧妙的算法思想,可以在平均$O(nlogn)$的时间复杂度内完成数组的排序。对于结构体类型的排序,在快速排序算法中也可以使用。本文主要讲解如何在C语言中使用结构体进行快排排序。 快速排序算法 快速…

    算法与数据结构 2023年5月19日
    00
  • Java分治归并排序算法实例详解

    Java分治归并排序算法实例详解 什么是分治归并排序算法 分治法是一种算法解决问题的思想,即将一个问题分成若干个小问题,再将小问题分成更小的子问题,直到最后子问题可以很容易地直接求解,原问题的解即子问题的解的合并。归并排序算法采用了分治法思想,将一个要排序的数组分成两个小数组,再将这两个小数组分别排序,最终合并两个有序小数组成为一个有序大数组。 算法流程 分…

    算法与数据结构 2023年5月19日
    00
  • 详解次小生成树以及相关的C++求解方法

    详解次小生成树以及相关的C++求解方法 什么是次小生成树 在普通的生成树中,每个节点只有一条边与其相连。而次小生成树则是指,在所有的生成树中,除了最小生成树之外,权值和第二小的生成树。 求解方法 Kruskal算法 Kruskal算法是一种贪心算法,也是求解最小生成树的常用算法。我们可以对Kruskal算法做一些修改,使其求出次小生成树。 一般情况下,我们需…

    算法与数据结构 2023年5月19日
    00
  • 一道JS前端闭包面试题解析

    下面我来为你讲解一道 JS 前端闭包面试题的完整攻略。 面试题 下面是面试题的题目与内容: for (var i = 0; i < 5; i++) { setTimeout(function() { console.log(i); }, 0); } 要求输出 0, 1, 2, 3, 4,但是实际上却是输出了 5, 5, 5, 5, 5。请问这是为什么?…

    算法与数据结构 2023年5月19日
    00
  • javascript笛卡尔积算法实现方法

    JavaScript笛卡尔积算法实现方法 什么是笛卡尔积 笛卡尔积是指给定多个集合,每个集合中分别选取一个元素组成的所有可能组合的集合。例如,有两个集合 X={1,2} 和 Y={3,4},那么它们的笛卡尔积为 {(1,3), (1,4), (2,3), (2,4)}。 实现笛卡尔积算法 JavaScript实现笛卡尔积算法的过程可以分为以下三步: 遍历所有…

    算法与数据结构 2023年5月19日
    00
  • C语言详细讲解qsort函数的使用

    C语言详细讲解qsort函数的使用 qsort函数简介 在C语言中,qsort函数是一个标准库函数,用于将一个数组排序。它使用快速排序算法,实现了高效的排序。qsort函数的原型定义如下: void qsort (void* base, size_t num, size_t size, int (*compar)(const void*,const void…

    算法与数据结构 2023年5月19日
    00
  • JavaScript数据结构与算法之基本排序算法定义与效率比较【冒泡、选择、插入排序】

    JavaScript数据结构与算法之基本排序算法定义与效率比较 概述 排序是计算机科学中最常见的操作之一,是将数据按照一定的顺序重新排列的过程。排序算法被广泛应用于搜索、数据压缩、数据库等领域。JavaScript中常用的基本排序算法有3种:冒泡排序、选择排序和插入排序。本文将详细介绍这三种算法的原理、JavaScript实现以及时间复杂度比较。 冒泡排序 …

    算法与数据结构 2023年5月19日
    00
  • C++九种排序具体实现代码

    针对“C++九种排序具体实现代码”的攻略,我将从以下几个方面进行详细讲解: 九种排序算法介绍 排序算法实现代码示例 一些注意事项 九种排序算法介绍 在介绍具体代码实现之前,我们先来了解一下九种排序算法的特点。 冒泡排序(Bubble Sort):通过不断交换相邻的两个元素,将大的元素逐渐往后移动,最后得到有序序列。 快速排序(Quick Sort):通过设定…

    算法与数据结构 2023年5月19日
    00
合作推广
合作推广
分享本页
返回顶部