zoukankan      html  css  js  c++  java
  • 算法-----数组------ 数组中的第K个最大元素

    在未排序的数组中找到第 k 个最大的元素。请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素。
    
    示例 1:
    
    输入: [3,2,1,5,6,4] 和 k = 2
    输出: 5
    示例 2:
    
    输入: [3,2,3,1,2,4,5,5,6] 和 k = 4
    输出: 4
    说明:
    
    你可以假设 k 总是有效的,且 1 ≤ k ≤ 数组的长度。
    

    上面算法题:

    我的解答:

     public static int findKthLargest(int[] nums, int k) {
            if (nums ==null) {
                return 0;
            }
            if (k <1) {
                return -1;
            }
            int len = nums.length;
            int temp;
            for (int i = 0; i < len; i++) {
                for (int j = i + 1; j < len; j++) {
                    if (nums[i] < nums[j]) {
                        temp = nums[j];
                        nums[j] = nums[i];
                        nums[i] = temp;
                    }
                }
                if (i == k) {
                    break;
                }
            }
                    return nums[k -1];
    }
    

    基本思路

    冒泡排序,可以得到最大值,那么第k 大,就是排序排到k次就结束,就可以了。

    网上最快的解答:

        public static int findKthLargest(int[] nums, int k) {
    
            int left=0,right=nums.length-1;
            while(left<right){
                int pivot = partition(nums, left,right);
                if(pivot ==k-1) {
                    return nums[pivot];
                } else if(pivot>k-1){
                    right=pivot-1;
                } else {
                    left=pivot+1;
                }
            }
            return nums[left];
        }
    private static int partition(int[] nums,int left,int right) {
            //先获取三个数的中位数
            int pivot = median3(nums,left,right);
            //int pivot = nums[left];
    
            int start=left,end=right-1;
            while(start<end) {
                //从pivot左边找起,停在第一个比pivot小的地方,等待交换
                while(nums[++start]>pivot) {}
                //从pivot右边朝气,停在第一个比pivot大的地方,等待交换
                while(nums[--end]<pivot) {}
                if(start<end) {
                    swap(nums,start,end);
                }
            }
            //此时,交换start与pivot
            swap(nums,start, right-1);
            return start;
        }
    
        private static int median3(int[] nums,int left, int right){
            int median=(left+right)/2;
            if(nums[left]<nums[median]) {
                swap(nums, left, median);
            }
            if(nums[left]<nums[right]) {
                swap(nums,left, right);
            }
            if(nums[median]<nums[right]) {
                swap(nums, median, right);
            }
            swap(nums, median, right-1);
            return nums[right-1];
    
        }
    
        private static void swap(int[] nums, int left, int right) {
            int temp = nums[left];
            nums[left] = nums[right];
            nums[right] = temp;
        }
    
    
    

    写的有些复杂,大概是这样的思路。
    二分一下,然后把最大的放在左边,中间,右边最小。然后把中间的数字,放在最右边的前一个位置。
    然后从左边开始,找到比中间位置大的数字,和比中间位置小的他们两个换下位置。最后,比中间位置下的数字,和中间位置换下。
    总体结果下来,就是,可以得到第n 大的数字。
    如果说这个数字刚好是你要的第k 大,那么就返回。如果比你要的小,那么右边减一,把左边的数字排序,得出第k 大。如果比你要的大,k > n ,那么右边的数组去做上述的模糊排序。然后取值。

    分析

    上面第二个算法,确实在命中你的要求的话,确实很快,但是不好理解。有些复杂,一些基础的程序员可能理解起来比较困难,
    上面冒泡,理解起来简单,但是排序的次数,k 越大,次数越多。算法时间复杂度是O(n^2)
    

    总结:
    自己找一份工作,确实没有什么难的。但是找一份薪资报酬,条件高的公司,确实还需要继续努力。需要巩固的知识,还有很多。加油吧,不要止步不前。

  • 相关阅读:
    SDUT 1299 最长上升子序列
    HDU 1754 I Hate It
    SDUT 2080 最长公共子序列问题
    HDU 1102 Constructing Roads HDU1863 畅通工程
    HDU 1166 敌兵布阵
    HDU 1874 畅通工程续
    准备翻译Windows 8 动手实验系列教程
    Windows 8 动手实验系列教程 简介
    一起学Windows phone7开发(十九. Windows phone7发布)
    一起学Windows phone7(十六. windows phone 7 developer tool RTM 发布)
  • 原文地址:https://www.cnblogs.com/caoxinyu/p/10568516.html
Copyright © 2011-2022 走看看