数组查找:让你快速找到想要的元素!

630 阅读19分钟

哈喽,各位小伙伴们,你们好呀,我是喵手。

  今天我要给大家分享一些自己日常学习到的一些知识点,并以文字的形式跟大家一起交流,互相学习,一个人虽可以走的更快,但一群人可以走的更远。

  我是一名后端开发爱好者,工作日常接触到最多的就是Java语言啦,所以我都尽量抽业余时间把自己所学到所会的,通过文章的形式进行输出,希望以这种方式帮助到更多的初学者或者想入门的小伙伴们,同时也能对自己的技术进行沉淀,加以复盘,查缺补漏。

小伙伴们在批阅的过程中,如果觉得文章不错,欢迎点赞、收藏、关注哦。三连即是对作者我写作道路上最好的鼓励与支持!

前言

  在日常开发中,我们经常需要对一些数据进行查找操作,这时候数组就是一个经典的数据结构。数组是一种线性数据结构,它可以以固定的时间复杂度 O(1) 访问任何一个元素。但是,如果我们需要查找一个元素是否存在于一个数组中,就需要遍历整个数组进行查找,这样的时间复杂度就变成了 O(n),显然这样的效率是不够高的。所以,在此介绍一些数组查找算法,让你能够在更高效的时间内找到你想要的元素。

摘要

  本文将介绍常用的数组查找算法,包括顺序查找、二分查找、哈希查找等。我们将通过源代码解析、应用场景案例、优缺点分析、类代码方法介绍、测试用例等方面来详细讲解每种查找算法的特点,以及如何根据实际需求来选择合适的查找算法。

数组查找

简介

  数组查找是一种常见的数据操作,也是数据结构中最基本的操作之一。数组查找算法按照查找的方式不同,可以分为顺序查找、二分查找、哈希查找等。其中顺序查找是最简单的查找算法,它的时间复杂度为 O(n),二分查找和哈希查找的时间复杂度分别为 O(logn) 和 O(1)。因此,在实际开发中,我们应该根据问题的特点来选择不同的查找算法。

源代码解析

顺序查找

  顺序查找是一种最基本的查找算法,它的原理是依次遍历数组的每个元素,直到找到目标元素或遍历完整个数组。在 Java 中,顺序查找可以通过 for 循环来实现。

public static int sequentialSearch(int[] arr, int target) {
    for (int i = 0; i < arr.length; i++) {
        if (arr[i] == target) {
            return i;
        }
    }
    return -1;
}

代码分析:

  该代码实现了一个简单的顺序查找算法。其输入参数为一个整数数组和需要查找的目标值。函数通过遍历数组中的每一个元素,判断该元素是否等于目标值,如果等于则返回该元素的下标,否则返回-1表示目标值未找到。

具体实现包括以下几个步骤:

  1. 定义一个函数,输入为一个整数数组arr和一个目标值target,输出为整数类型的下标值或者-1。
  2. 遍历整个数组arr,从下标0开始,一直到下标arr.length-1为止。
  3. 在每一个下标位置上判断该位置上的元素是否等于目标值target,如果相等,则返回该下标值。
  4. 如果遍历完整个数组后,仍然没有找到目标值,则返回-1表示未找到。

  总体来说,该算法的时间复杂度为O(n),其中n为数组的长度,因为在最坏情况下需要遍历整个数组才能找到目标值。

二分查找

  二分查找是一种利用二分的思想来查找元素的算法。在查找过程中,需要首先确定中间元素的值,然后通过比较目标元素和中间元素的大小关系,逐步缩小查找范围,直到找到目标元素或确定不存在。在 Java 中,二分查找可以通过递归或循环来实现。

public static int binarySearch(int[] arr, int target, int left, int right) {
    if (left > right) {
        return -1;
    }
    int mid = (left + right) / 2;
    if (arr[mid] == target) {
        return mid;
    } else if (arr[mid] > target) {
        return binarySearch(arr, target, left, mid - 1);
    } else {
        return binarySearch(arr, target, mid + 1, right);
    }
}

代码分析:

  这段代码实现了二分查找算法,接收四个参数:待查找的数组arr,目标值target,数组的左索引left和右索引right。首先判断left是否大于right,如果是,返回-1,表示未找到目标值。否则,将数组分成两半,计算中间位置mid。如果中间位置的值等于目标值,返回mid。如果中间位置的值大于目标值,说明目标值在左半部分,递归调用自身并将右索引设为mid-1。如果中间位置的值小于目标值,说明目标值在右半部分,递归调用自身并将左索引设为mid+1。最后,如果未找到目标值,返回-1。

哈希查找

  哈希查找是一种利用哈希表来实现快速查找的算法。在哈希查找过程中,首先需要将元素通过哈希函数映射到哈希表中,然后在哈希表中查找目标元素。在 Java 中,哈希查找可以通过 HashMap 或 HashSet 等集合类来实现。

public static boolean hashSearch(int[] arr, int target) {
    Set<Integer> set = new HashSet<>();
    for (int num : arr) {
        set.add(num);
    }
    return set.contains(target);
}

代码分析:

  这段代码实现了在一个整数数组中判断是否存在目标数的功能,使用了HashSet来实现快速查找。具体分析如下:

  1. 方法名:该方法名为hashSearch,说明使用了哈希表中的Set数据结构。

  2. 形参:该方法的形参有两个,分别为整数数组arr和目标数target。

  3. Set定义:在方法内部定义了一个HashSet类型的set,用于存放数组元素。

  4. 遍历数组:使用增强型for循环遍历整数数组arr,将数组中的元素一个个加入set中。

  5. 查找目标数:通过set的contains方法查找目标数target是否存在于set中,如果存在则返回true,否则返回false。

  6. 返回值:该方法的返回值为布尔类型,表示目标数是否存在于数组中。

  所以,该方法使用了HashSet来实现数组中元素的快速查找,时间复杂度为O(1)。同时,该方法只需要遍历一遍整个数组,所以时间复杂度为O(n)。

应用场景案例

  不同的查找算法适用于不同的场景。顺序查找适用于数据量小或者无序的数组,时间复杂度为 O(n)。二分查找适用于数据量大且有序的数组,时间复杂度为 O(logn)。哈希查找适用于需要频繁查找的场景,时间复杂度为 O(1)。下面通过实例来展示三种查找算法的应用场景。

顺序查找

  假设现在有一个长度为 100 的数组,需要查找其中是否包含元素 50。由于数据量较小,直接使用顺序查找即可。

int[] arr = new int[100];
int target = 50;
if (sequentialSearch(arr, target) != -1) {
    System.out.println("找到了目标元素");
} else {
    System.out.println("未找到目标元素");
}

代码分析:

  这段代码定义了一个包含100个整数的数组 arr 和一个目标整数 target。接着,它使用 sequentialSearch 方法在数组中查找目标元素。如果找到目标元素,则输出“找到了目标元素”,否则输出“未找到目标元素”。

  其中 sequentialSearch 方法是一个顺序查找算法的实现,它会逐个比较数组中的元素,直到找到目标元素或者遍历完整个数组。如果找到目标元素,则返回该元素在数组中的位置;否则返回 -1。

  需要注意的是,在使用 sequentialSearch 方法之前,需要确保数组 arr 已经被初始化并且包含要查找的元素。否则,算法将无法正确运行。

二分查找

  假设现在有一个长度为 10000000 的有序数组,需要查找其中是否包含元素 500000。由于数据量较大且有序,直接使用二分查找可以在较短时间内找到目标元素。

int[] arr = new int[10000000];
int target = 500000;
if (binarySearch(arr, target, 0, arr.length - 1) != -1) {
    System.out.println("找到了目标元素");
} else {
    System.out.println("未找到目标元素");
}

代码分析:

  该代码创建了一个长度为10000000的整型数组,并定义了一个名为target的整型变量,并赋值为500000。然后通过调用二分查找方法binarySearch来查找数组中是否存在值为target的元素。如果binarySearch方法返回值不等于-1,则说明找到了目标元素,否则未找到目标元素。最后输出结果到控制台。

哈希查找

  假设现在需要对一个数组进行频繁的查找操作,为了提高查找效率,可以使用哈希查找。

int[] arr = new int[1000000];
int target = 500000;
if (hashSearch(arr, target)) {
    System.out.println("找到了目标元素");
} else {
    System.out.println("未找到目标元素");
}

代码分析:

  该代码中定义了一个长度为1000000的整型数组arr和一个目标值target为500000,然后调用了一个名为hashSearch的搜索函数,在搜索函数中使用了哈希表的思想来定位目标元素是否存在于数组中。

若找到了目标元素则打印“找到了目标元素”,否则打印“未找到目标元素”。但是该代码并没有给出具体的hashSearch函数实现,因此无法对其效率等进行评估。

优缺点分析

顺序查找

  顺序查找是一种最简单的查找算法,它的优点是实现简单,适用于简单的数据结构;缺点是时间复杂度高,对于较大的数据集不适用。

二分查找

  二分查找是一种高效的查找算法,它的优点是时间复杂度低,使用范围广;缺点是只适用于有序数组,实现相对复杂。

哈希查找

  哈希查找是一种快速查找算法,它的优点是时间复杂度低,适用于频繁查找的场景;缺点是需要额外的存储空间,哈希函数的设计较为困难。

类代码方法介绍

顺序查找

public static int sequentialSearch(int[] arr, int target)

参数说明

  • arr:待查找的数组
  • target:目标元素

返回值

  • 如果找到目标元素,则返回其在数组中的索引值;
  • 如果未找到目标元素,则返回 -1。

二分查找

public static int binarySearch(int[] arr, int target, int left, int right)

参数说明

  • arr:待查找的有序数组
  • target:目标元素
  • left:查找范围的左边界
  • right:查找范围的右边界

返回值

  • 如果找到目标元素,则返回其在数组中的索引值;
  • 如果未找到目标元素,则返回 -1。

哈希查找

public static boolean hashSearch(int[] arr, int target)

参数说明

  • arr:待查找的数组
  • target:目标元素

返回值

  • 如果找到目标元素,则返回 true;
  • 如果未找到目标元素,则返回 false。

测试用例

下面是几个针对不同查找算法的测试用例:

先附上完整的查找类代码:

package com.example.javase.se.array;

import java.util.HashSet;
import java.util.Set;

/**
 * @Author ms
 * @Date 2023-11-14 21:11
 */
public class ArraySearch {

    public static int sequentialSearch(int[] arr, int target) {
        for (int i = 0; i < arr.length; i++) {
            if (arr[i] == target) {
                return i;
            }
        }
        return -1;
    }

    public static int binarySearch(int[] arr, int target, int left, int right) {
        if (left > right) {
            return -1;
        }
        int mid = (left + right) / 2;
        if (arr[mid] == target) {
            return mid;
        } else if (arr[mid] > target) {
            return binarySearch(arr, target, left, mid - 1);
        } else {
            return binarySearch(arr, target, mid + 1, right);
        }
    }

    public static boolean hashSearch(int[] arr, int target) {
        Set<Integer> set = new HashSet<>();
        for (int num : arr) {
            set.add(num);
        }
        return set.contains(target);
    }
}

代码分析:

  该代码实现了三种不同的数组查找方法:顺序查找、二分查找和哈希表查找。

  顺序查找方法(sequentialSearch)遍历整个数组,逐一比较每一个元素是否等于目标值。如果找到目标值,则返回该值在数组中的索引位置;如果遍历完整个数组都没找到,则返回-1。

  二分查找(binarySearch)方法是一种更为高效的查找方法,但前提是数组必须是有序的。该方法首先计算出数组的中间位置 mid,如果 mid 等于目标值,则返回该位置;如果 mid 大于目标值,则在数组的左半部分继续查找;如果 mid 小于目标值,则在数组的右半部分继续查找。递归执行,直到找到目标值或遍历完整个数组都没找到,返回-1。

  哈希表查找(hashSearch)方法使用了 Java 中的 Set 集合,将数组中的每个元素存储到集合中,然后使用 contains 方法判断目标值是否存在于集合中。如果存在,则返回 true;如果不存在,则返回 false。

  综上所述,这些查找方法在不同的情况下有不同的适用性。顺序查找适用于数组元素较少、无序的情况;二分查找适用于数组元素有序、大小合适的情况;哈希表查找适用于需要频繁查找、插入、删除元素的情况。

顺序查找

测试数据:

int[] arr = {1, 3, 5, 7, 9};
int target1 = 5; // 目标元素存在
int target2 = 6; // 目标元素不存在

测试代码:

package com.example.javase.se.array;

/**
 * @Author ms
 * @Date 2023-11-14 21:11
 */
public class ArrayTest5 {

    public static void main(String[] args) {

        int[] arr = {1, 3, 5, 7, 9};
        int target1 = 5; // 目标元素存在
        int target2 = 6; // 目标元素不存在

        // 测试顺序查找
        int index1 = ArraySearch.sequentialSearch(arr, target1);
        int index2 = ArraySearch.sequentialSearch(arr, target2);
        if (index1 != -1) {
            System.out.println("目标元素 " + target1 + " 存在于数组中,索引为 " + index1);
        } else {
            System.out.println("未找到目标元素 " + target1);
        }
        if (index2 != -1) {
            System.out.println("目标元素 " + target2 + " 存在于数组中,索引为 " + index2);
        } else {
            System.out.println("未找到目标元素 " + target2);
        }
    }
}

测试结果:

目标元素 5 存在于数组中,索引为 2
未找到目标元素 6

测试结果

  根据如上测试用例,本地测试结果如下,仅供参考,你们也可以自行修改测试用例或者添加更多的测试数据或测试方法,进行熟练学习以此加深理解。

在这里插入图片描述

测试代码分析

  根据如上测试用例,在此我给大家进行深入详细的解读一下测试代码,以便于更多的同学能够理解并加深印象。   这是一个 Java 类,其中包含了一个名为 main 的方法。该方法中定义了一个整型数组 arr,用于存储一些整数。另外,分别定义了变量 target1target2,它们分别表示要查找的目标元素。

  在代码中调用了 ArraySearch 类中的 sequentialSearch 方法对数组进行顺序查找,该方法会返回目标元素在数组中的索引位置(从 0 开始),如果未找到则返回 -1。接着,判断查找结果是否为 -1,如果不是则说明目标元素存在于数组中,输出其在数组中的索引位置;如果为 -1 则说明目标元素不存在于数组中,输出未找到目标元素的提示信息。最后会输出结果到控制台。

  整体来说,该程序就是通过简单的顺序查找算法在给定数组中查找目标元素的位置,然后输出结果。

二分查找

测试数据:

int[] arr = {1, 3, 5, 7, 9};
int target1 = 5; // 目标元素存在
int target2 = 6; // 目标元素不存在

测试代码:

package com.example.javase.se.array;

/**
 * @Author ms
 * @Date 2023-11-14 21:11
 */
public class ArrayTest5 {

    public static void main(String[] args) {

        int[] arr = {1, 3, 5, 7, 9};
        int target1 = 5; // 目标元素存在
        int target2 = 6; // 目标元素不存在

        // 测试哈希查找
        boolean result1 = ArraySearch.hashSearch(arr, target1);
        boolean result2 = ArraySearch.hashSearch(arr, target2);
        if (result1) {
            System.out.println("目标元素 " + target1 + " 存在于数组中");
        } else {
            System.out.println("未找到目标元素 " + target1);
        }
        if (result2) {
            System.out.println("目标元素 " + target2 + " 存在于数组中");
        } else {
            System.out.println("未找到目标元素 " + target2);
        }
    }
}

测试结果

  根据如上测试用例,本地测试结果如下,仅供参考,你们也可以自行修改测试用例或者添加更多的测试数据或测试方法,进行熟练学习以此加深理解。

测试结果:

目标元素 5 存在于数组中,索引为 2
未找到目标元素 6

在这里插入图片描述

测试代码分析

  根据如上测试用例,在此我给大家进行深入详细的解读一下测试代码,以便于更多的同学能够理解并加深印象。   该代码主要是测试哈希查找的使用,使用一个整型数组来存储数据,并定义两个目标元素(一个存在,一个不存在),然后调用哈希查找方法进行查找并输出结果。

  哈希查找是一种优秀的查找方法,通过将数组元素映射到哈希表中,可以大幅度提高查找效率。其原理是将目标元素通过哈希函数计算出其在哈希表中对应的索引位置,然后在该位置的链表中查找目标元素是否存在。

  在代码中,我们定义了一个ArraySearch类,并在其中实现了哈希查找方法hashSearch。该方法首先将数组元素插入到哈希表中,然后计算目标元素的哈希值,并在对应索引位置的链表中查找目标元素是否存在。如果找到了,则返回true,否则返回false。

  在main方法中,我们创建一个整型数组arr并初始化,然后定义两个目标元素(一个存在,一个不存在),分别调用哈希查找方法,并通过控制台输出查找结果。如果找到了目标元素,则输出“目标元素存在于数组中”,否则输出“未找到目标元素”。

哈希查找

测试数据:

int[] arr = {1, 3, 5, 7, 9};
int target1 = 5; // 目标元素存在
int target2 = 6; // 目标元素不存在

测试代码:

package com.example.javase.se.array;

/**
 * @Author ms
 * @Date 2023-11-14 21:11
 */
public class ArrayTest5 {

    public static void main(String[] args) {

        int[] arr = {1, 3, 5, 7, 9};
        int target1 = 5; // 目标元素存在
        int target2 = 6; // 目标元素不存在

        // 测试哈希查找
        boolean result1 = ArraySearch.hashSearch(arr, target1);
        boolean result2 = ArraySearch.hashSearch(arr, target2);
        if (result1) {
            System.out.println("目标元素 " + target1 + " 存在于数组中");
        } else {
            System.out.println("未找到目标元素 " + target1);
        }
        if (result2) {
            System.out.println("目标元素 " + target2 + " 存在于数组中");
        } else {
            System.out.println("未找到目标元素 " + target2);
        }
    }
}

测试结果:

目标元素 5 存在于数组中
未找到目标元素 6

测试结果

  根据如上测试用例,本地测试结果如下,仅供参考,你们也可以自行修改测试用例或者添加更多的测试数据或测试方法,进行熟练学习以此加深理解。

在这里插入图片描述

测试代码分析

  根据如上测试用例,在此我给大家进行深入详细的解读一下测试代码,以便于更多的同学能够理解并加深印象。

  该代码主要是测试数组中的哈希查找方法。首先定义了一个整型数组arr,然后分别定义了两个目标元素target1target2,并通过调用ArraySearch类中的hashSearch方法查找这两个目标元素是否存在于arr数组中。最后根据查找结果输出对应的提示信息。

小结

  1. 数组查找是数据结构中最基本的操作之一。
  2. 常见的数组查找算法包括顺序查找、二分查找、哈希查找等。
  3. 根据问题的特点来选择不同的查找算法。
  4. 顺序查找适用于数据量小或者无序的数组。
  5. 二分查找适用于数据量大且有序的数组。
  6. 哈希查找适用于需要频繁查找的场景。
  7. 在实际开发中,我们应该根据需求选择合适的查找算法。

总结

  数组查找是数据结构中最基本的操作之一,常见的数组查找算法包括顺序查找、二分查找、哈希查找等。不同的查找算法适用于不同的场景,根据问题的特点来选择不同的查找算法。顺序查找适用于数据量小或者无序的数组;二分查找适用于数据量大且有序的数组;哈希查找适用于需要频繁查找的场景。在实际开发中,我们应该根据需求选择合适的查找算法。

... ...

文末

好啦,以上就是我这期的全部内容,如果有任何疑问,欢迎下方留言哦,咱们下期见。

... ...

学习不分先后,知识不分多少;事无巨细,当以虚心求教;三人行,必有我师焉!!!

wished for you successed !!!


⭐️若喜欢我,就请关注我叭。

⭐️若对您有用,就请点赞叭。

⭐️若有疑问,就请评论留言告诉我叭。