常见算法、Arrays、Lambda表达式-Java入门-黑马程序员2022年新视频DAY21笔记

常见算法

此处要介绍的常见的算法为查找算法、排序算法和字符串匹配算法

查找算法

此处要介绍的常见查找算法为基本查找(顺序查找)、二分查找/折半查找、分块查找。(也有插值查找、斐波那契查找、树表查找以及哈希查找)

基本查找(顺序查找)

1.算法核心:从0索引开始挨个往后查找。

二分查找

1.前提条件:数组中的数据必须是有序的。

2.核心逻辑:每次排除一半的查找范围。

3.循环的结束条件:找到了对应数据的位置,或者是min跑到了max的右边。

4.二分查找的优势(相对于顺序查找):提高查找效率。

5.如果数据是乱的,那么先排序再进行二分查找得到的索引就失去了实际的意义,因为希望找到的索引应该是在数组打乱之前的。

6.普通版的二分排序的mid计算是mid = (min + max) / 2可以通过改变mid的计算式去改进算法,mid = min + (key - arr[min]) / (arr[max] - arr[min]) * (max - min),这种查找方法也叫做插值查找。

7.插值查找的意思有点类似于归一化,将待查值与min标志对应的元素值相差的距离相减比上最大最小的差值,这个比值能大概反映出实际值在范围中的位置,此时乘上索引的范围,再加上min,就能比普通二分查找更精确地找到待查值的真实索引值。但是插值查找最好是在分布比较均匀的有序数组上使用,否则效率反而比二分查找低

分块查找

1.分块的原则:

  • 前一块中的最大数据,小于后一块中的所有数据(块内无序,块间有序),比如数组 (7,10)(13,19,16,20)(27,22,30,40,36)(43,50,48)
  • 块数数量一般等于数字的个数开根号。比如:16个数字一般分为四块左右。

2.核心思路:先确定要查找的元素在哪一块,然后在块内挨个查找。

3.实现步骤:

  • 创建数组blockArr存放每一个块对象的信息,Block类中存放属性块中最大值max,块的开始索引和结束索引
  • 先查找blockArr确定要查找的数据属于那一块
  • 再单独遍历这一块的数据即可

4.扩展的分块查找:块内无序,块间也是无序的,但是块内的数据仍然在一定的范围之内,此时只需要在Block类中加一个最小值,整体跟分块查找差不多。

排序算法

主要介绍的是冒泡排序、选择排序、插入排序、快速排序,也会有希尔排序、归并排序、堆排序、计数排序、桶排序和基数排序。

冒泡排序

1.算法步骤:

  • 相邻的元素两两比较,大的放右边,小的放左边
  • 第一轮循环结束,最大值已经找到,在数组的最右边
  • 第二轮循环只要在剩余的元素找最大值就可以,不用再比较最后一个元素
  • 第二轮结束后,数组中第二大的值已经找到,继续在剩余的元素中找最大值,直到排序完成
  • 如果数组中有n个数据,总共只需要执行n-1次

2.改进的冒泡排序:有时候数组中的元素大多数都是有序的,只有一部分是无序的,例如 2 1 3 4 5,这个时候就不需要执行 n-1 次的冒泡排序,只需要设立一个flag标志,若在排序过程中某一次没有元素的顺序发生改变,那就说明排序完成。

选择排序

1.选择排序:从0索引开始,拿着每一个索引上的元素跟后面的元素一次比较,小的放前面,大的放后面,以此类推。

2.步骤分解:

  • 从0索引开始,跟后面的元素一一比较
  • 小的放前面,大的放后面
  • 一轮循环结束后,就会产生一个最小的数据
  • 下一轮循环开始就不需要考虑前面产生的最小的数据

插入排序

1.算法思想:将0索引的 元素到N索引的元素看作是有序的,把N+1索引的元素到最后一个当成是无序的。遍历无序的数据,将遍历到的元素插入有序序列中适当的位置,如遇到相同数据,插在后面。N的范围:0~最大索引。

2.步骤分解:

  • 找到无序的那一组数据是从哪个索引开始的
  • 遍历从无序数据的开始索引到最后一个元素,依次得到无序数据中的每一个元素
  • 将得到的元素插入到有序序列中(从后往前比较)

快速排序

1.递归:

  • 递归指的是方法中调用方法本身的现象
  • 递归的注意点:递归一定要有出口,否则就会出现内存溢出
  • 作用:把一个复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解
  • 递归策略只需少量的程序就可描述出接替过程所需要的多次重复计算
  • 两个核心:1.找出口:什么时候不再调用方法;2.找规则:如何把大问题变成规模较小的问题

2.快排算法步骤:

  • 把当前序列的最前面的索引(标兵)作为基准数,最终实现比基准数小的放在序列左边,比基准数大的放在序列的右边
  • 设立start和end指针,start指针最初指向标兵的后一个索引,end指针指向当前序列的最后一个索引
  • end指针从后往前遍历,当end指针找到比基准数要小的数值后,暂时停止遍历,轮到start指针从前往后遍历,当找到比基准数要大的数值后,暂时停止遍历,交换两个指针对应的元素值(不让start先开始的原因是start开始找到了一个比基准数要大的数之后,此时end往前找有可能就碰到了start,此时两个索引指向的数值在正确排序的右边,此时若是进行基准数归位,这个数值就会去到序列的左边,排序就会出错)
  • 交换完元素值后继续重复第三步,直至两个指针指向同一个索引,此时交换当前索引(一般使用start)与标兵位置的数据值,这个步骤叫做基准数归位
  • 当本轮基准数归为之后,继续将左边序列和右边序列递归调用快速排序,直到传入的start索引大于end索引时,递归结束。

常见算法的API-Arrays

1.Arrays类中有很多方法都经过静态修饰,因此可以直接通过类名调用方法。

2.常用方法:

方法名说明
public static String toString(数组)把数组拼接成一个字符串
public static int binarySearch(数组,查找哦的元素)二分查找法查找元素
public static int[] copyOf(原数组,新数组长度)拷贝数组(如果新数组的长度是大于老数组的长度,会补上默认初始值)
public static int[] coppyOfRange(原数组,起始索引,结束索引)拷贝数组(指定范围,包左不包右)
public static void fill(数组,元素)使用传入元素填充数组
public static void sort(数组)按照默认方式(快排)进行数组排序
public static void sort(数组,排序规则)按照指定的规则排序

 对于public static void sort(数组,排序规则):

  • sort方法实际上就是根据返回值决定当前获取到的两个元素的放置位置,因此最重要的书写返回值的代码在重写的方法中,无论是什么类型都可以进行排序
  • 其只能给引用数据类型的数组进行排序,如果数组是基本数据类型的,需要先变成其对应的包装类数组。
  • 其底层的排序为插入排序 + 折半查找
  • 排序规则是一个接口,因此要传递该接口的实现类对象,而这个对象只使用一次,因此最好使用匿名内部类
  • 该接口中重写的方法(此处先假设传入数据为整数) public int compare compare(Integer o1,Integer o2),o1 表示在无序序列中
  • 当返回值为负数时:当前要插入的元素放前面;当返回值为 0 或者正数时,当前要插入的元素放后面
  • 因此是希望降序还是升序,取决于重写方法的返回值是写 o2 - o1(降序排序)还是o1 - o2(升序排序)。(基于此甚至还能直接返回值写 -1 ,反转数组) 

Lambda表达式

1.一些相关预备知识:

  • 函数式编程:函数式编程是一种思想特点,其忽略面向对象的复杂语法,强调做什么,而不是谁去做(强调实现的逻辑,而不是哪个对象去实现)
  • Lambda表达式就是函数式思想的体现

2.Lambda表达式时JDK8开始后的一种新语法形式:

  • () 对应着方法的形参
  • -> 固定格式
  • {} 对应着方法的方法体

3.注意点:

  • Lambda表达式是用于简化匿名内部类的书写的
  • Lambda表达式只能简化函数式接口的匿名内部类的写法
  • 函数式接口:有且仅有一个抽象方法的接口叫做函数式接口,接口上方可以加@FuncionalInterface注解
  • 如果不是函数式接口,很显然Lambda表达式重写的方法就不知道是哪一个

4.Lambda表达式省略写法:

  • 省略核心:可以推导出来的就可以省略
  • 参数类型可以省略不写
  • 如果只有一个参数,参数类型可以省略,()也可以省略
  • 如果Lambda表达式的方法体只有一行,大括号,分号,return可以省略不写,但是这几项省略时需要同时省略
() -> {

}

//以上面的重写Comparater<Integer>接口为例
//匿名内部类版本
Array.sort(arr,new Comparator<Integer>(){
        @override
        public int compare(Integer o1,Integer o2){
            return o1 - o2;
    }
});

//Lambda普通版本
Array.sort(arr,(Integer o1,Integer o2) -> {
            return o1 - o2;
    }
);

//Lambda省略写法
Array.sort(arr,(o1,o2) ->  o1 - o2);

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值