线性时间的排序算法--桶排序(以leetcode164. Maximum Gap为例讲解)
前言
在比较排序的算法中,快速排序的性能最佳,时间复杂度是O(N*logN).因此,在使用比较排序时,时间复杂度的下限就是O(N*logN)。而桶排序的时间复杂度是O(N+C),因为它的实现并不是基于比较实现的,而是基于映射函数实现的。
桶排序
桶排序工作的原理是将数组分到有限数量的桶子里。每个桶子再个别排序(有可能再使用别的排序算法或是以递归方式继续使用桶排序进行排序)。
桶排序利用函数的映射关系,减少了几乎所有的比较工作。实际上,桶排序的f(k)值的计算,其作用就相当于快排中划分,已经把大量数据分割成了基本有序的数据块(桶)。然后只需要对桶中的少量数据做先进的比较排序即可。
时间复杂度和空间复杂度分析
Try to solve it in linear time/space. //题目要求我们使用线性的时间
Return 0 if the array contains less than 2 elements.
You may assume all elements in the array are non-negative integers and fit in the 32-bit signed integer range.
解题思路:
首先对数组进行桶排序,然后找出最大的gap。
首先明确,最大的gap肯定是后桶的最小值减去前桶的最大值,注意此处说的桶均为有效桶,即不包括空桶。
因此无需进行桶内排序,仅需记录每个有效桶的最大值和最小值即可。
为何最大的gap肯定是后桶的最小值减去前桶的最大值?
假设有数组x[1...n],其中最大的元素为max,最小元素为min,将左闭右开的实数区间[min,max)划分为n-1个等长的子区间(桶),每个子区间也是左闭右开的,我们用len来表示每个子区间的长度。除去max和min,剩下的n-2个数,每个数都属于其中一个桶。对于同一个桶的两个数,因为桶是左闭右开的,所以他们的距离肯定是小于len的。然后,关键的一点是,n-2个数放进n-1个桶,由抽屉原理可以知道,肯定有一个桶是空的,所以,距离最远的相邻的两个数,肯定是属于两个不同的桶。于是,我们可以把每个桶都扫描一次,相邻最远的两个数,必定其中一个是某个桶里的最大值,另一个是另一个桶里的最小值。
代码:
public class Solution {
public int maximumGap(int[] num) {
if(num == null || num.length<2){
return 0;
}
int maxval = Integer.MIN_VALUE;
int minval = Integer.MAX_VALUE;
//求解数组最值
for(int i=0; i<num.length; i++){
if(num[i]>maxval) maxval = num[i];
if(num[i]<minval) minval = num[i];
}
//数组内的元素值相同
if(minval==maxval){
return 0;
}
//数组仅有两个元素
if(num.length==2){
return maxval-minval;
}
int len = (int)Math.ceil((double)(maxval-minval)/(num.length-1)); //求解桶间差值,向上取整
int n = (maxval-minval)/len;
int maxBuk[] = new int[n+1];
int minBuk[] = new int[n+1];
Arrays.fill(maxBuk,Integer.MIN_VALUE);
Arrays.fill(minBuk,Integer.MAX_VALUE);
//桶映射
for(int val:num){
int temp = (val-minval)/len;
maxBuk[temp] = Math.max(val,maxBuk[temp]);
minBuk[temp] = Math.min(val,minBuk[temp]);
}
//求解最大gap,最大差值位于后桶的min-前桶的max
int gap = 0;
int pre = maxBuk[0];
for(int i=1; i<=n; i++){
if(maxBuk[i]==Integer.MIN_VALUE && minBuk[i]==Integer.MAX_VALUE){ //忽略空桶
continue;
}
gap = Math.max(gap,minBuk[i]-pre);
pre = maxBuk[i];
}
return gap;
}
}
线性时间的排序算法--桶排序(以leetcode164. Maximum Gap为例讲解)的更多相关文章
- 使用 js 实现十大排序算法: 桶排序
使用 js 实现十大排序算法: 桶排序 桶排序 refs xgqfrms 2012-2020 www.cnblogs.com 发布文章使用:只允许注册用户才可以访问!
- Java排序算法——桶排序
文字部分为转载:http://hxraid.iteye.com/blog/647759 对N个关键字进行桶排序的时间复杂度分为两个部分: (1) 循环计算每个关键字的桶映射函数,这个时间复杂度是O(N ...
- 排序算法-桶排序(Java)
package com.rao.sort; import java.util.*; /** * @author Srao * @className BucketSort * @date 2019/12 ...
- 十大经典排序算法+sort排序
本文转自:十大经典排序算法,其中有动图+代码详解,本文简单介绍+个人理解. 排序算法 经典的算法问题,也是面试过程中经常被问到的问题.排序算法简单分类如下: 这些排序算法的时间复杂度等参数如下: 其中 ...
- 计数排序和桶排序(Java实现)
目录 比较和非比较的区别 计数排序 计数排序适用数据范围 过程分析 桶排序 网络流传桶排序算法勘误 桶排序适用数据范围 过程分析 比较和非比较的区别 常见的快速排序.归并排序.堆排序.冒泡排序等属于比 ...
- 计数排序与桶排序python实现
计数排序与桶排序python实现 计数排序 计数排序原理: 找到给定序列的最小值与最大值 创建一个长度为最大值-最小值+1的数组,初始化都为0 然后遍历原序列,并为数组中索引为当前值-最小值的值+1 ...
- 【JS面试向】选择排序、桶排序、冒泡排序和快速排序简介
新年伊始,又到了金三银四的时候了.面对前端越来越多的算法面试题,我简单的整理了一下几种比较常见的数组排序方式,分别介绍其基本原理和优劣势.(ps:才疏学浅,希望大家可以在issues下面指出问题) 选 ...
- 经典排序算法 - 高速排序Quick sort
经典排序算法 - 高速排序Quick sort 原理,通过一趟扫描将要排序的数据切割成独立的两部分,当中一部分的全部数据都比另外一部分的全部数据都要小,然后再按此方法对这两部分数据分别进行高速排序,整 ...
- 排序算法--希尔排序(Shell Sort)_C#程序实现
排序算法--希尔排序(Shell Sort)_C#程序实现 排序(Sort)是计算机程序设计中的一种重要操作,也是日常生活中经常遇到的问题.例如,字典中的单词是以字母的顺序排列,否则,使用起来非常困难 ...
随机推荐
- BZOJ2400: Spoj 839 Optimal Marks
Description 定义无向图中的一条边的值为:这条边连接的两个点的值的异或值. 定义一个无向图的值为:这个无向图所有边的值的和. 给你一个有n个结点m条边的无向图.其中的一些点的值是给定的,而其 ...
- hadoop编程小技巧(5)---自定义输入文件格式类InputFormat
Hadoop代码测试环境:Hadoop2.4 应用:在对数据需要进行一定条件的过滤和简单处理的时候可以使用自定义输入文件格式类. Hadoop内置的输入文件格式类有: 1)FileInputForma ...
- Sortable Observable Collection in C#
Sorting outside the collection protected override void OnNavigatedTo(NavigationEventArgs e) { if (Se ...
- 【MongoDB】2014-07-25T11:00:48.634+0800 warning: Failed to connect to 127.0.0.1:27017, reason: errno:10061 由于目标计算机积极拒绝,无法连接。
1:启动MongoDB 2014-07-25T11:00:48.634+0800 warning: Failed to connect to 127.0.0.1:27017, reason: errn ...
- LaTex Font Size 字体大小命令
LaTex中字体大小有很多中等级,分别由下列命令控制: \tiny \scriptsize \footnotesize \small \normalsize \large \Large \LARGE ...
- CodeForces 219D 树形DP
D. Choosing Capital for Treeland time limit per test 3 seconds memory limit per test 256 megabytes i ...
- Daily Scrum 10.24
昨天我们的工作已经全面开始了,本来想等今天(25号)看那个燃尽图和燃速图能不能出来,结果还是没有,就先把我们的Task统计贴上来吧. 今天的Task统计: 至于燃尽图和燃速图的问题已经发老师邮件提问了 ...
- javascript 原型链
浅谈JS原型链 原型链 ECMAScript中描述了原型链的概念.我们知道ECMAScript并不像C++,Java那样使用类,但是对象仍然可以通过多种方式创建,其中就有构造函数方式.每个构造函数都有 ...
- C++STL -- vector 使用
vector是一种顺序容器. vector常用API: 现在一个个分析: 1. assign 这是一种赋值方法,但是会覆盖原来容器内的值. void assign( size_type num, co ...
- 杭电ACM 1197
#include<stdio.h>main(){ int temp,i,t,sum10,sum12,sum16; for(i=1000;i<=9999;i++) { temp=i; ...