1.比较器

1.1 Arrays.sort()

Arrays.sort(数组)

  • 若其中的数组元素时自定义类型,报错;
  • 若为基本类型,则按值排序。

Arrays.sort(数组,自己定义的比较器):

  • 会按定义的比较器进行比较排序。

1.2 比较器

是一个自己定义的类。

类名 implements Comparator<Student>

实现其中的public int compare(Student o1,Student o2)方法:

  • 此方法返回一个负数:说明o1更小,即o1应该排在前面;
  • 返回一个正数:第二个应该放在前面;
  • 返回0:两个一样大

C++中重载运算符就是自己定义比较器的一种方式。

package Comparator;import java.util.Arrays;
import java.util.Comparator;class Student{int id;String name;int age;public Student(int id,String name,int age) {this.id=id;this.name=name;this.age=age;}
}
public class ComparatorTest {public static void main(String[] args) {Student[] students=new Student[3];students[0]=new Student(3,"llll",23);students[1]=new Student(2,"ssss",18);students[2]=new Student(1,"qqqq",34);//Arrays.sort(students);//printArray(students);Arrays.sort(students,new IdAscendingComparator());printArray(students);Arrays.sort(students,new IdDscendingComparator());printArray(students);Arrays.sort(students,new AgeAscendingComparator());printArray(students);Arrays.sort(students,new AgeDscendingComparator());printArray(students);}public static void printArray(Student[] arr) {for(int i=0;i<arr.length; i++)System.out.println(arr[i].id+"--"+arr[i].name+"--"+arr[i].age);System.out.println("**************************");}
}class IdAscendingComparator implements Comparator<Student>{@Overridepublic int compare(Student arg0, Student arg1) {/** if(arg0<arg1)* return 负数;* else if(arg0>arg1)* return 正数;* else* return 0;*/return arg0.id-arg1.id;}
}class IdDscendingComparator implements Comparator<Student>{@Overridepublic int compare(Student arg0, Student arg1) {return arg1.id-arg0.id;}
}class AgeAscendingComparator implements Comparator<Student>{@Overridepublic int compare(Student arg0, Student arg1) {return arg0.age-arg1.age;}
}class AgeDscendingComparator implements Comparator<Student>{@Overridepublic int compare(Student arg0, Student arg1) {return arg1.age-arg0.age;}
}

运行结果:

1.3 PriorityQueue

堆结构也可用比较器

优先级队列就是堆。

若没有给比较器,则报错。

package Comparator;import java.util.PriorityQueue;public class PriorityQueueTest {public static void main(String[] args) {Student student1=new Student(3,"llll",23);Student student2=new Student(2,"ssss",18);Student student3=new Student(1,"qqqq",34);PriorityQueue<Student> heap=new PriorityQueue<>(new AgeDscendingComparator());//按age大的放在头部heap.add(student1);heap.add(student2);heap.add(student3);while(!heap.isEmpty()) {Student stu=heap.poll();//弹出堆顶元素,堆大小-1;System.out.println(stu.id+"--"+stu.name+"--"+stu.age);}}
}

运行结果:

1.4 TreeMap

红黑树结构。

系统提供的一个有序的结构,都会伴随着一个比较器的构造。这个比较器告诉这个结构怎么组织。

——基于比较的排序是重点。

2.不基于比较的排序

时间复杂度:

  • 遍历数组的时间

额外空间复杂度:

都是稳定的。

与被排序的样本的实际数据状况很有关系, 所以实际中并不经常使用。

计数排序就是桶排序的一个具体体现。

3.给定一个数组, 求如果排序之后, 相邻两数的最大差值, 要求时间复杂度O(N), 且要求不能用非基于比较的排序。

3.1 举例:

原始数据:

排序之后:

所以应该返回3.

3.2 实现方式

借用了桶的概念,但是未用桶排序。

  1. N个数据,准备N+1个桶;用一个全局变量记录最大差值。
  2. 遍历数组,找到min和max
    1. 若min=max,整个数组只有一种数,返回0;
    2. 若不等,min放入桶0,max放入桶N
      1. 将min~max均分成N份,对应N+1个桶,如下图:
      2. 其他数属于哪个范围,放入对应的桶。
  3. 每个桶设置三个属性:
    1. min
    2. max
    3. flag(boolean):表示这个桶是否有元素进入过
      1. 若x进入桶m时,flag=false,则令flag=true,min=max=x;
      2. 若y进入桶m时,flag=true,则只更新min和max
  4. 遍历完后,找每个桶的flag
    1. 若为false,直接跳下一个;
    2. 若为true,找到此桶的前一个非空桶,此桶的min-前非空桶的max得到这两个桶的差值。
    3. 更新最大差值。

3.3 最大差值肯定跨桶的原因分析

如上图,排序后,相临的两个数可能来自同一个桶(11,15),也可能来自不同的桶(15,21)。

N个数,N+1个桶,根据鸽舍原理,肯定存在一个空桶

存在空桶,就可以说明:最大差值一定不来自相同的桶。

因为:

空桶左肯定存在离它最近的非空桶,空桶右边也肯定存在离它最近的布控的桶(最起码桶0和桶N都非空)。

左.max-右.min>桶表示的范围;

一个桶内部的两个元素的差值<桶表示的范围

所以最大差值不会是同一桶中的两个元素——只用关心不同桶的元素。

为什么不直接找非空桶,得到最大差值=左.max-右.min?

如上图,最大差值为19,是相邻两桶产生的差值。

有空桶,只是说明最大差值肯定不是在同一桶中,但不是说最大差值一定来自空桶两侧非空桶的差值。

3.4 代码实现

package Solution;public class MaxGap {public static void main(String[] args) {int[] array= {3,1,6,2,7};System.out.println("maxGap="+maxGap(array));}public static int maxGap(int[] arr) {       int result=0;if (arr == null || arr.length < 2) {return result;}int min=Integer.MAX_VALUE;int max=Integer.MIN_VALUE;int n=arr.length;for(int i=0;i<n;i++) {max=max>arr[i]?max:arr[i];min=min<arr[i]?min:arr[i];}System.out.println("min:"+min+"   max:"+max);int[] mins=new int[n+1];int[] maxs=new int[n+1];boolean[] flag=new boolean[n+1];if(min==max)return result;//设置桶0和桶nmins[0]=min;maxs[0]=min;mins[n]=max;maxs[n]=max;for(int i=0;i<n;i++) {int index=(int)((arr[i]-min)*n/(max-min));System.out.println("index:"+index);if(flag[index]==false) {mins[index]=arr[i];maxs[index]=arr[i];flag[index]=true;}else {mins[index]=Math.min(mins[index], arr[i]);maxs[index]=Math.max(maxs[index], arr[i]);}}int lastmax=maxs[0];for(int i=1;i<n;i++) {if(flag[i]==true) {result=mins[i]-lastmax;lastmax=maxs[i];}}return result;}
}

运行结果:

3.4.1 结果分析

元素,其中最大值为7,最小值为1。

5个元素,需要6个桶。

首先,将max-min=7-1=6进行5等分,6/5=1.2,得每段距离长1.2。

然后进行每个元素属于的桶号的计算:

  • 3:(3-1)/1.2=2/1.2=1(取整);
  • 6:(6-1)/1.2=5/1.2=4;
  • 2:(2-1)/1.2=1/1.2=0;

所以分桶结果如下图:

所以result=3;

3.4.2 对于计算桶号的公式的分析

即就是:

先算出每段距离的长度(),再求出当前元素据起点min的距离(),最后用后者除以前者就得到当前元素所属于的桶号(index)。

4.用数组结构实现大小固定的栈和队列

4.1 实现栈

4.1.1 分析

index:表示新进来的数应该放置的位置。

一个数入栈时,若index+1>size,则报错;否则这个数放在array[index]的位置,然后index++;

一个数出栈时,若index-1<0,则报错;否则弹出放在array[index-1]位置上的数,然后index--。

4.1.2 代码实现

package Solution;class ArrayStack{Integer[] array;Integer size;  public ArrayStack(int initsize) {if(initsize<0)throw new IllegalArgumentException("The init size is less than 0");elsearray=new Integer[initsize];size=0;}public void push(int num) {if(size==array.length)throw new ArrayIndexOutOfBoundsException("The queue is full");elsearray[size++]=num;}public Integer peek() {if(size==0)throw new ArrayIndexOutOfBoundsException("The queue is empty");elsereturn array[size-1];}public Integer pop() {if(size==0)throw new ArrayIndexOutOfBoundsException("The queue is empty");elsereturn array[--size];}
}   public class ArrayToStack {public static void main(String[] args) {ArrayStack as=new ArrayStack(3);as.push(3);System.out.println("peek:"+as.peek());as.push(24);System.out.println("pop:"+as.pop());System.out.println("pop:"+as.pop());//System.out.println("pop:"+as.pop());}
}

运行结果:

若为注释掉最后一句pop,运行结果为:

4.2 实现队列

4.2.1 分析

如果一个数要入队列,若size<array.length,则将这个数放在array[last]的位置,同时last++;否则报错;

如果一个数要出队列,若size>0,则array[first]位置上的数出队列,同时first++;否则报错。

注:当last和first到达最后一个元素时,让它们下一个位置为0位置。

(last和first之间无关系)

4.2.2 代码实现

package Solution;class ArrayQueue{Integer[] array;Integer first;//出队列时的下标Integer last;//入队列时的下标Integer size;public ArrayQueue(int initsize) {if(initsize<0)throw new IllegalArgumentException("The init size is less than 0");elsearray=new Integer[initsize];size=0;last=0;first=0;}public void push(int num) {if(size==array.length)throw new ArrayIndexOutOfBoundsException("The queue is full");else {array[last]=num;last=last==array.length-1?0:last+1;size++;}}public Integer peek() {if(size==0)throw new ArrayIndexOutOfBoundsException("The queue is empty");else return array[first];}public Integer poll() {if(size==0)throw new ArrayIndexOutOfBoundsException("The queue is empty");else {size--;first=first==array.length-1?0:first+1;return array[first];}}
}
public class ArrayToQueue {public static void main(String[] args) {ArrayQueue as=new ArrayQueue(3);as.push(7);System.out.println("peek:"+as.peek());as.push(6);System.out.println("pop:"+as.poll());//7出as.push(5);as.push(9);//as.push(4);System.out.println("pop:"+as.poll());//6System.out.println("pop:"+as.poll());//5}
}

运行结果:

5. 实现一个特殊的栈, 在实现栈的基本功能的基础上, 再实现返回栈中最小元素的操作。

【要求】
1. pop、 push、 getMin操作的时间复杂度都是O(1)。
2. 设计的栈类型可以使用现成的栈结构。

5.1 方法一

5.1.1 分析:

准备两个栈:data、min

入栈:

第一个元素,压入data、min栈;

后面剩余元素,依次压入data栈;若当前入栈元素比min栈栈顶元素小,则入min栈,否则再一次压入min栈栈顶元素。

出栈:

两个栈同时弹出元素。

5.1.2 代码实现

package Solution;import java.util.Stack;class MyStack{Stack<Integer> data;Stack<Integer> min;public MyStack() {this.data=new Stack<Integer>();this.min=new Stack<Integer>();}public void push(int num) {if(data.isEmpty()) {data.push(num);min.push(num);}if(num<=min.peek()) {data.push(num);min.push(num);}else {data.push(num);min.push(min.peek());}}public Integer pop() {if(data.isEmpty())throw new RuntimeException("Your stack is empty.");min.pop();return data.pop();}public Integer getMin() {if(data.isEmpty())throw new RuntimeException("Your stack is empty.");return min.peek();}
}
public class StackGetMin {public static void main(String[] args) {MyStack ms=new MyStack();ms.push(4);ms.push(5);ms.push(3);ms.push(6);System.out.println("min:"+ms.getMin());System.out.println(ms.pop());System.out.println(ms.pop());System.out.println("min:"+ms.getMin());}
}

运行结果:

5.2 方法二

5.2.1 分析:

准备两个栈:data、min

入栈:

第一个元素,压入data、min栈;

后面剩余元素,依次压入data栈;若当前入栈元素比min栈栈顶元素小,则入min栈,否则不如min栈。

出栈:

若当前弹出的data栈顶元素=min栈栈顶元素,两个栈都弹出栈顶元素,否则只有data栈弹出栈顶元素。

算法练习day7——190325(比较器、不基于比较的排序、maxGap、数组实现栈和队列、minStack)相关推荐

  1. JavaScript数据结构与算法(1)(数组、栈、队列、链表)(ES6)

    注意:原教学视频:JavaScript(ES6)数据结构和算法 | JavaScript数据结构与算法 (都是CoderWhy老师的教学) 原作者(笔记)链接:JavaScript 数据结构与算法 | ...

  2. 常见数据结构和算法实现(排序/查找/数组/链表/栈/队列/树/递归/海量数据处理/图/位图/Java版数据结构)

    常见数据结构和算法实现(排序/查找/数组/链表/栈/队列/树/递归/海量数据处理/图/位图/Java版数据结构) 数据结构和算法作为程序员的基本功,一定得稳扎稳打的学习,我们常见的框架底层就是各类数据 ...

  3. DSt:数据结构的简介、最强学习路线(逻辑结构【数组-链表-栈和队列/树-图-哈希】、物理结构、数据运算【十大排序/四大查找-图三大搜索-树三大遍历】、高级算法【贪心/分治/动态规划】之详细攻略

    DSt:数据结构的简介.最强学习路线(逻辑结构[数组-链表-栈和队列/树-图-哈希].物理结构[元素/关系].数据运算[十大排序/四大查找-图三大搜索-树三大遍历].高级算法[贪心/分治/动态规划]) ...

  4. 《算法(第四版)》1.3.49:有限个栈实现队列,练习题学习小结

    用有限个栈实现一个队列,保证每次出队和入队(在最坏的情况下)都只需要常数次的栈操作. 本文参考了下面两篇博客,解决这个问题的思路可以阅读这两篇博客,本文不在赘述.在核心思路不变的情况下,本文用Java ...

  5. python【力扣LeetCode算法题库】面试题 10.01-合并排序的数组

    面试题 10.01. 合并排序的数组 给定两个排序后的数组 A 和 B,其中 A 的末端有足够的缓冲空间容纳 B. 编写一个方法,将 B 合并入 A 并排序. 初始化 A 和 B 的元素数量分别为 m ...

  6. 数据结构与算法第二章 线性表、栈、队列、数组、字符串、树、二叉树、哈希表的增删查

    03 增删查:掌握数据处理的基本操作,以不变应万变 通过前面课时的学习,相信你已经建立了利用数据结构去完成时空转移的思想.接下来,你需要在理论思想的指导下灵活使用.其实,要想灵活使用数据结构,你需要先 ...

  7. dbscan算法中 参数的意义_基于变参数的DBSCAN算法

    安全模型.算法与编程 |34| 基于变参数的 DBSCAN 算法 ◆付泽强 王晓锋 (江南大学物联网工程学院 江苏 214122) 摘要:DBSCAN 算法是一种常用的基于密度的聚类算法,其优点在于性 ...

  8. 送书 | 你一定能看懂的算法基础书(代码示例基于Python)

    本文引自图灵教育<算法图解> 你一定能看懂的算法基础书:代码示例基于Python:400多个示意图,生动介绍算法执行过程:展示不同算法在性能方面的优缺点:教会你用常见算法解决每天面临的实际 ...

  9. 排序算法之——优先队列经典实现(基于二叉堆)

    许多应用都需要处理有序的元素,但有时,我们不要求所有元素都有序,或是一定要一次就将它们排序,许多情况下,我们会收集这些元素里的最大值或最小值. 这种情况下一个合适的数据结构应该支持两种操作:插入元素. ...

最新文章

  1. 学业水平测试计算机都考什么,高中学业水平考试与高中会考有什么区别
  2. 【GANs入门】pytorch-GANs任务迁移-单个目标(数字的生成)
  3. 函数式编程学习之路(一)
  4. python结课设计力学方面_我对力学教案的评价
  5. android属性动画缩放和平移同时,Android 实现属性动画平移,旋转,缩放,渐变 《H》...
  6. 微软拟测试类微博服务OfficeTalk
  7. 【渝粤教育】国家开放大学2018年秋季 0195-22T机械设计基础 参考试题
  8. 拓端tecdat|R语言非线性回归beta系数估算股票市场的风险分析亚马逊AMZN股票和构建投资组合
  9. 华为交换机ensp基础命令
  10. 目录穿越及文件包含漏洞
  11. 史上最全Unity3D游戏开发教程,从入门到精通(含学习路线图)
  12. 关于登陆百度等网站显示‘’隐私设置错误”的问题
  13. POJ 1625 Censored! (AC自己主动机 + 高精度 + DP)
  14. The Civil War in France translation04
  15. Word在试图打开文件时遇到错误。 请尝试下列方法: * 检查文档或驱动器的文件权限。 * 确保有足够的内存和磁盘空间。 * 用文件恢复转换器打开文件。
  16. 什么是外键约束?外键约束下的多表操作是什么?
  17. java.util.stream.Stream案例解读
  18. 怎么把视频转成mp3音频?
  19. 2020信息通信产业十大技术趋势发布
  20. Github 上的源代码同步到自己的Gitlab 脚本

热门文章

  1. 恒生电子发布云计算金融应用“超云计划”
  2. 银行营业网点管理系统——Servlet包(CityAreaServlet )
  3. 允许java运行不安全或不可信的应用程序
  4. jQuery应用之(二)使用jQuery管理选择结果(荐)
  5. php和mysql建立链接
  6. 实战:配置DNS客户端域名搜索后缀构造域名进行域名解析
  7. SQL语句,统计一段时间内有多少个工作日
  8. docker Harbor
  9. Redis 命令--Redis集合(Set)
  10. go使用反射reflect获取变量类型