1.桶排序(数字之间差值)
桶排序的3个核心问题:
1.每个桶的长度是多少?
我们期望将数组中的各个数等距离分配,也就是每个桶的长度相同,也就是对于所有桶来说,桶内最大值减去桶内最小值都是一样的。
2.一共要准备多少个桶?
确定桶的数量,最后的加一保证了数组的最大值也能分到一个桶。
3.如何确定每个数应该对应哪个桶?
我们的做法是要将数组中的数放到一个个桶里面,不断更新更大的(后一个桶内元素的最小值 - 前一个桶内元素的最大值),最后就得到了答案。
例题1:相邻元素之间最大的差值
给定一个无序的数组,找出数组在排序之后,相邻元素之间最大的差值。如果数组元素个数小于 2,则返回 0。
输入: [3,6,9,1]
输出: 3
解释: 排序后的数组是 [1,3,6,9], 其中相邻元素 (3,6) 和 (6,9) 之间都存在最大差值 3。
class Solution(object):
def maximumGap(self, nums):
if not nums or len(nums) < 2: return 0
batch_size = max(1,(max(nums)-min(nums)) // (len(nums)-1))
batch_num=(max(nums)-min(nums))//batch_size+1
batch_min=[999999999999 for i in range(batch_num)]
batch_max = [-999999999999 for i in range(batch_num)]
batch_has = [0 for i in range(batch_num)]
for i in range(len(nums)):
index=(nums[i]-min(nums))//batch_size
batch_max[index] = max(batch_max[index],nums[i])
batch_min[index] = min(batch_min[index], nums[i])
batch_has[index]+=1
new_batch_max=[]
new_batch_min=[]
for i in range(batch_num):
if batch_has[i]!=0:
new_batch_max.append(batch_max[i])
new_batch_min.append(batch_min[i])
if len(new_batch_max)==1:
return new_batch_max[0]-new_batch_min[0]
max_value=-999999999999
for i in range(1,len(new_batch_max)):
max_value=max(max_value,new_batch_min[i]-new_batch_max[i-1])
return max_value
Javascript代码
function MySort( arr ) {
// write code here
var quicksort = function(arr, low,high){
var partition = function(arr,low,high){
let i = low-1;
const pivot = arr[high];
for (let j=low;j<high;j++){
if (arr[j]<pivot){
i+=1;
let mid = arr[j]
arr[j] = arr[i]
arr[i] = mid
}
}
let mid = arr[i+1]
arr[i+1] = arr[high]
arr[high] = mid
return i+1
}
let p = partition(arr, low, high)
if(p-1>low)
quicksort(arr , low,p-1)
if (p+1<high)
quicksort(arr , p+1,high)
}
quicksort(arr ,0, arr.length-1)
return arr
}
2.快速排序(最小值问题)
该方法的基本思想是:
1.先从数列中取出一个数作为基准数。
2.分区过程,将比这个数大的数全放到它的右边,小于或等于它的数全放到它的左边。
3.再对左右区间重复第二步,直到各区间只有一个数。
题目1:最小的k个数
输入整数数组 arr ,找出其中最小的 k 个数。例如,输入4、5、1、6、2、7、3、8这8个数字,则最小的4个数字是1、2、3、4。
**题解:**元素位于下标 m,也就是说,左侧的数组有 m 个元素,是原数组中最小的 m 个数。那么:
若 k = m,我们就找到了最小的 k 个数,就是左侧的数组;
若 k<m ,则最小的 k 个数一定都在左侧数组中,我们只需要对左侧数组递归地 parition 即可;
若 k>m,则左侧数组中的 mm 个数都属于最小的 k 个数,我们还需要在右侧数组中寻找最小的 k-m个数,对右侧数组递归地 partition 即可。
class Solution(object):
def getLeastNumbers(self, arr, k):
"""
:type arr: List[int]
:type k: int
:rtype: List[int]
"""
if k==0: return []
def partition(arr, low, high):
pivot = arr[high]
i = low - 1
for j in range(low, high):
if arr[j] <= pivot:
i += 1
arr[i], arr[j] = arr[j], arr[i]
arr[i + 1], arr[high] = arr[high], arr[i + 1]
return (i + 1)
def quick_sort(arr, low, high,k):
p = partition(arr, low, high)
num=p-low+1
if k<num:
quick_sort(arr, low, p - 1,k)
elif k>num:
quick_sort(arr, p + 1, high,k-num)
quick_sort(arr,0,len(arr)-1,k)
return arr[:k]
题目2:数组排成最小的数
输入一个非负整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。
输入: [3,30,34,5,9]
输出: “3033459”
我爱你:字符串排序利用python中的>
仅仅将排序算法修改为:
(str(nums[j])+str(pivot))<=(str(pivot)+str(nums[j])):
class Solution(object):
def minNumber(self, nums):
def partition(nums,l,r):
pivot=nums[r]
i=l-1
for j in range(l,r):
if (str(nums[j])+str(pivot))<=(str(pivot)+str(nums[j])):
i+=1
nums[i],nums[j]=nums[j],nums[i]
nums[i+1],nums[r]=nums[r],nums[i+1]
return i+1
def quick_sort(nums,l,r):
p=partition(nums,l,r)
if p-1>l:
quick_sort(nums,l,p-1)
if p+1<r:
quick_sort(nums, p + 1, r)
quick_sort(nums,0,len(nums)-1)
str_nums=[str(i) for i in nums]
return ''.join(str_nums)
3.归并排序(逆序对问题)
def mergesort(seq):
"""归并排序"""
if len(seq) <= 1:
return seq
mid = len(seq) / 2 # 将列表分成更小的两个列表
# 分别对左右两个列表进行处理,分别返回两个排序好的列表
left = mergesort(seq[:mid])
right = mergesort(seq[mid:])
# 对排序好的两个列表合并,产生一个新的排序好的列表
return merge(left, right)
def merge(left, right):
"""合并两个已排序好的列表,产生一个新的已排序好的列表"""
result = [] # 新的已排序好的列表
i = 0 # 下标
j = 0
# 对两个列表中的元素 两两对比。
# 将最小的元素,放到result中,并对当前列表下标加1
while i < len(left) and j < len(right):
if left[i] <= right[j]:
result.append(left[i])
i += 1
else:
result.append(right[j])
j += 1
result += left[i:]
result += right[j:]
return result
题目1:逆序对
在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数。
题解:归并排序:
如果将数组1【2,3,4,5】与数组2【1,5,6,8】合并,数组1在数组2之前。首先合并2与1中的最小值1。由于2比1大,数组1中的所有数都比1大且都能构成逆序对,逆序对总数加4,以此类推。
class Solution:
def mergeSort(self, nums, tmp, l, r):
if l >= r:
return 0
mid = (l + r) // 2
inv_count = self.mergeSort(nums, tmp, l, mid) + self.mergeSort(nums, tmp, mid + 1, r)
i, j, pos = l, mid + 1, l
while i <= mid and j <= r:
if nums[i] <= nums[j]:
tmp[pos] = nums[i]
i += 1
inv_count += (j - (mid + 1))
else:
tmp[pos] = nums[j]
j += 1
pos += 1
for k in range(i, mid + 1):
tmp[pos] = nums[k]
inv_count += (j - (mid + 1))
pos += 1
for k in range(j, r + 1):
tmp[pos] = nums[k]
pos += 1
nums[l:r+1] = tmp[l:r+1]
return inv_count
def reversePairs(self, nums: List[int]) -> int:
n = len(nums)
tmp = [0] * n
return self.mergeSort(nums, tmp, 0, n - 1)
4.冒泡排序法
原理代码
时间复杂度为O(N^2)。
def bubbleSort(arr):
n = len(arr)
# 遍历所有数组元素
for i in range(n):
# Last i elements are already in place
for j in range(0, n-i-1):
if arr[j] > arr[j+1] :
arr[j], arr[j+1] = arr[j+1], arr[j]