LintCode_第k大元素

问题描述:

在数组中找到第k大的元素

样例:给出数组[9,3,2,4,8]第三大的元素是4;给出数组 [1,2,3,4,5],第一大的元素是5,第二大的元素是4,第三大的元素是3,以此类推

挑战:要求时间复杂度为O(n),空间复杂度为O(1)

算法设计:

首先对这个数列使用快速排序算法进行从大到小排序,然后再遍历寻找第k大数据。此算法的重点难点应该在于快速排序

public class Model_KthLargestElement {

    public static int kthLargestElement(int k, ArrayList<Integer> numbers) {
        if(numbers==null||numbers.size()==0||numbers.size()<k){
            return 0;
        }
        
        //保存最终结果
        int result=0;
        //保存numbers的大小
        int size=numbers.size();
        
        //先使用快速排序方法实现numbers所有元素的从大到小排序
        numbers=Quick(numbers,0,numbers.size()-1);
        
        //寻找第一大数,就返回numbers的第一个值
        if(k==1){
            return numbers.get(0).intValue();
        }
        
        //寻找第k大的数字,j为游标,count为第几大
        int j=1;
        int count=1;
        
        while(j<size&&count!=k){
            //相邻两个数字不重复,那么count++
            if(numbers.get(j)!=numbers.get(j-1)){
                count++;
            }
            j++;
        }
        
        //如果count等于k,那么寻找到第k大数据,否则,遍历完numbers最后一个数字了,还没找到第k大数据,表示,这个数据不存在;
        if(count==k){
            result=numbers.get(j-1).intValue();
        }
        
        return result;
    }
    
    //快速排序算法
    public static ArrayList<Integer> Quick(ArrayList<Integer> numbers,int left,int right){
        
        if(numbers==null||numbers.size()==0){
            return null;
        }

        //左边游标
        int pos=left;
        //右边游标
        int i=right;
        //起到交换作用
        int temp=0;
        
        do{
            //如果pos后面的数比pos大,或者pos前面的数比pos大,则相交换;
            if((i>=pos&&numbers.get(i)>=numbers.get(pos))||(i<pos&&numbers.get(i)<=numbers.get(pos))){
                //交换两处对象
                temp=numbers.get(pos);
                numbers.set(pos, numbers.get(i));
                numbers.set(i, temp);
                //交换数值时,不能直接写成numbers.get(i)=numbers.get(pos);
                //因为numbers.get(i)和numbers.get(pos)都非变量
                
                //开始用了下面代码,想实现两个位置值的交换,出现了越界错误
//                numbers.remove(pos);
//                numbers.add(pos, numbers.get(i));
//                numbers.remove(i);
//                numbers.add(i, temp);
//                
                //交换两处下标
                temp=pos;
                pos=i;
                i=temp;
               
            }

            //如果交换后i比pos大,那么i--,否则i++
            if(i>pos){
                i--;
            }else{
                i++;
            }
        }while(i<numbers.size()&&i!=pos);
        
        if(left<pos-1){
            Quick(numbers,left,pos-1);
        }
        
        if(right>pos+1){
            Quick(numbers,pos+1,right);
        }
        
        //开始写成如下:如果numbers中无重复数据,还可以运行,一旦,numbers中的数据有重复,例如有i个8,
        //那么会出现"StackOverflowError"的错误,因为会在这i个8中反复调用Quick()方法,进栈出栈,最终导致栈溢出
        
//        if(left<pos){StackOverflowError
//            Quick(numbers,left,pos-1);
//        }
//        
//        if(right>pos){
//            Quick(numbers,pos+1,right);
//        }
//        
        return numbers;
    }


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值