九章微课 

 

1.最高频 K 项问题

前导问题:前k大数 

在一个整数数组中,找最大的k个数

 这个问题有在线和离线两种解法:

  1. 离线算法:允许多遍遍历数组。排序后找的方法时间复杂度O(nlogn),但是需要找O(n)的解法。答案就是使用快速选择算法,先一遍遍历找到第k大的数,然后再一遍遍历找到前k大的数,总复杂度为o(n)
  2. 在线算法:数据以数据流进入,只允许一遍遍历。
    public class topK {
        /**
         * @param nums: an integer array
         * @param k: An integer
         * @return: the top k largest numbers in array
         */
        public int[] topkOffline(int[] nums, int k) {
            // 1.离线算法:
            // 首先一遍遍历找到第K大的数:快速选择算法O(n)
            int kLargestNum = QuickSelect(nums, k, 0, nums.length - 1);
            int [] res = new int[k];
            int i = 0;
            for (Integer num : nums) {
                if (num >= kLargestNum && i < k) res[i++] = num;
            }
            return res;
        }
        public int[] topkOnline(int[] nums, int k) {
            // 2.在线算法:数据流形式进入,只允许一遍遍历: 使用最大堆
            Comparator<Integer> comparator = new Comparator<Integer>() {
                @Override
                public int compare(Integer o1, Integer o2) {
                    if (o1 > o2) return -1;
                    else if (o1 < o2) return 1;
                    else return 0;
                }
            };
            PriorityQueue<Integer> pq = new PriorityQueue<>(k, comparator);
            for (Integer num : nums) {
                pq.add(num);
            }
            int[] res = new int[k];
            for (int i = 0; i < k; i++) res[i] = pq.poll();
            return res;
        }
        private int QuickSelect(int[] nums, int k, int start, int end) {
            if (k > nums.length || start > end) return -1;
            int pivot = end;
            int left = start;
            int right = end;
            while (left < right) {
                while (nums[left] <= pivot && left < right) left++;
                while (nums[right] >= pivot && left < right) right--;
                swap(nums, left, right);
            }
            swap(nums, left, pivot);
            
            if (k - 1 > left) QuickSelect(nums, k, left + 1, end);
            if (k - 1 < left) QuickSelect(nums, k, start, left - 1);
            return nums[left];
        }
        private void swap(int[] nums, int x, int y) {
            int tmp = nums[x];
            nums[x] = nums[y];
            nums[y] = tmp;
        }
        public static void main(String[] args) {
            topK tk = new topK();
            int [] nums = {6, 4, 10, 14, 3, 7, 2, 9};
            int[] res = tk.topkOnline(nums, 4);
            for (Integer num : res) System.out.println(num);
        }
    }
    View Code

相关文章:

  • 2022-02-26
  • 2021-09-14
  • 2021-10-13
  • 2021-07-26
  • 2022-01-25
  • 2022-12-23
猜你喜欢
  • 2021-05-24
相关资源
相似解决方案