剑指offer整理(附python代码)——排序&查找

1.旋转数组的最小数字

问题描述

把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。 输入一个非递减排序的数组的一个旋转,输出旋转数组的最小元素。 例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。 NOTE:给出的所有元素都大于0,若数组大小为0,请返回0

考察点:二分查找
思路1 ?(logn)

旋转后,两段有序,最小位于边界。“二分查找”(用于数据按关键字有序排列)

  1. 设置2个指针,首f、尾l。理论上f>l的值。【特例1:数组没有旋转,此时f<l,返回f】
  2. 找到数组中间值m,比较m与f/l关系。m>=f:m位于前半个数组,f移至中间;否则:l移至中间。
    【特例2:m=f=l的值,无法判断m该归为哪段,此时顺序查找。例如01111,旋转后10111或11101】
  3. 最终情况: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 区别:

  1. sort 是应用在 list 上的方法,sorted 可以对所有可迭代的对象进行排序操作。
  2. sort 方法在原列表上进行操作,而sorted 在新的 list进行操作。
思路2: 基于快排,O(nlogn)
思路3:基于堆排序算法,构建k个元素的最大堆,O(nlogk),适合大数据

【最大堆】根节点的值>子节点的值

k个元素的堆,找最大、删除最大、插入一个新的数字:O(logk)

  1. 构建一个大根堆来存储最小的k个值,容器不满时,直接加入。
  2. 容器满时,比较堆顶与待插入的值,堆顶大,则替换掉。
# -*- 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;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值