1.旋转数组的最小数字
问题描述
把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。 输入一个非递减排序的数组的一个旋转,输出旋转数组的最小元素。 例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。 NOTE:给出的所有元素都大于0,若数组大小为0,请返回0
考察点:二分查找
思路1 ?(logn)
旋转后,两段有序,最小位于边界。“二分查找”(用于数据按关键字有序排列)
- 设置2个指针,首f、尾l。理论上f>l的值。【特例1:数组没有旋转,此时f<l,返回f】
- 找到数组中间值m,比较m与f/l关系。m>=f:m位于前半个数组,f移至中间;否则:l移至中间。
【特例2:m=f=l的值,无法判断m该归为哪段,此时顺序查找。例如01111,旋转后10111或11101】 - 最终情况:f位于前半个数组的末尾,l位于后半个数组的开头(最小值),即f、l相邻,返回l值。
class Solution1:
def search(self,rotateArray):
mid = rotateArray[0]
for i in range(1,len(rotateArray)):
if rotateArray[i]<mid:
mid = rotateArray[i]
return mid
def minNumberInRotateArray(self, rotateArray):
# write code here
left = 0
right = len(rotateArray)-1
mid = 0 #针对特例1,不进入while
while(rotateArray[left]>=rotateArray[right]):
if ((right-left)==1):
mid = right
break
mid = (left+right)/2
#针对特例2,
if ((rotateArray[left]==rotateArray[right]) and (rotateArray[mid]==rotateArray[left])):
return search(rotateArray)
if(rotateArray[mid]>=rotateArray[left]):
left = mid
else:
right = mid
return rotateArray[mid]
if __name__ == '__main__':
s = Solution1()
print s.minNumberInRotateArray([3,4,5,1,2])
1
2.最小的K个数
问题描述
输入n个整数,找出其中最小的K个数。例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4,。
考察点
排序,优化时间空间效率
思路1:sorted,O(nlogn)
利用python中的内置函数sorted().
sort 与 sorted 区别:
- sort 是应用在 list 上的方法,sorted 可以对所有可迭代的对象进行排序操作。
- sort 方法在原列表上进行操作,而sorted 在新的 list进行操作。
思路2: 基于快排,O(nlogn)
思路3:基于堆排序算法,构建k个元素的最大堆,O(nlogk),适合大数据
【最大堆】根节点的值>子节点的值
k个元素的堆,找最大、删除最大、插入一个新的数字:O(logk)
- 构建一个大根堆来存储最小的k个值,容器不满时,直接加入。
- 容器满时,比较堆顶与待插入的值,堆顶大,则替换掉。
# -*- coding:utf-8 -*-
class Solution:
def GetLeastNumbers_Solution(self, tinput, k):
# write code here
if not tinput:
return []
if len(tinput)<k:
return []
# sorted 与 sort区别
# sort()在本地进行排序
# sorted() 返回副本,原始输入不变
tinput = sorted(tinput)
return tinput[:k]
# -*- coding:utf-8 -*-
class Solution:
def GetLeastNumbers_Solution(self, tinput, k):
# write code here
#此方法时间复杂度为O(nlogn)
if k >len(tinput) or not tinput:
return []
#tinput.sort()
#实现一个快速排序
def quick_sort(array):
if not array:
return []
pivot=array[0]
left=quick_sort([x for x in array[1:] if x<pivot])
right=quick_sort([x for x in array[1:] if x>=pivot])
return left+[pivot]+right
return quick_sort(tinput)[:k]
# -*- coding:utf-8 -*-
import heapq
# 基于堆排序
class Solution:
def GetLeastNumbers_Solution(self, tinput, k):
if not tinput or not k or k > len(tinput):
return []
# 创建小根堆
heapq.heapify(tinput)
# heappop弹出堆顶元素
return [heapq.heappop(tinput) for _ in xrange(k)]
# 直接:return heapq.nsmallest(k,tinput)也可实现,但是时间复杂度比这个高。
# 此方法为java实现,时间复杂度小,数据量小时,空间复杂度略高于其他。
/*
*基于堆排序算法,构建最大堆。时间复杂度为O(nlogk)
*如果用快速排序,时间复杂度为O(nlogn);
*如果用冒泡排序,时间复杂度为O(n*k)
*/
import java.util.ArrayList;
public class Solution {
public ArrayList<Integer> GetLeastNumbers_Solution(int [] input, int k) {
ArrayList<Integer> list=new ArrayList<Integer>();
//检查输入的特殊情况
if(input==null || input.length<=0 || input.length<k){
return list;
}
//构建最大堆
for(int len=k/2-1; len>=0; len--){
adjustMaxHeapSort(input,len,k-1);
}
//从第k个元素开始分别与最大堆的最大值做比较,如果比最大值小,则替换并调整堆。
//最终堆里的就是最小的K个数。
int tmp;
for(int i=k; i<input.length; i++){
if(input[i]<input[0]){
tmp=input[0];
input[0]=input[i];
input[i]=tmp;
adjustMaxHeapSort(input,0,k-1);
}
}
for(int j=0; j<k; j++){
list.add(input[j]);
}
return list;
}
public void adjustMaxHeapSort(int[] input, int pos, int length){
int temp;
int child;
for(temp=input[pos]; 2*pos+1<=length; pos=child){
child=2*pos+1;
if(child<length && input[child]<input[child+1]){
child++;
}
if(input[child]>temp){
input[pos]=input[child];
}else{
break;
}
}
input[pos]=temp;
}
}