zoukankan      html  css  js  c++  java
  • Q870 优势洗牌(田忌赛马)

    Q870 优势洗牌(田忌赛马)

    题目描述

    通过题目描述,我们很容易联想到田忌赛马的故事。

    第一种解题思路(超时)

    我在思考这道题的时候,想到直接将nums1数组升序排列得到clone,然后将clone数组从小到大和nums2中的数进行对,如果clone中有数大于nums2[i],就将这个数赋值给nums1[i],如果找遍clone都没有找到大于nums2[i]的数,则用list记录下下标index,然后用clone中剩余的数挨个赋值给nums[index];

     public int[] advantageCount(int[] nums1, int[] nums2) {
             ArrayList<Integer> clone = new ArrayList<>();
            int n = nums1.length;
            for (int i = 0; i < n; i++) {
                clone.add(nums1[i]);
            }
            Collections.sort(clone);
            List<Integer> index = new ArrayList<>();
            L:
            for (int i = 0; i < n; i++) {
                for (int num : clone) {
                    if (num > nums2[i]) {
                        nums1[i] = num;
                        clone.remove(Integer.valueOf(num));
                        continue L;
                    }
                }
                index.add(i);
            }
            if (!clone.isEmpty()) {
                int size = clone.size();
                for (int i = 0; i < size; i++) {
                    nums1[index.get(i)] = clone.get(i);
                }
            }
            return nums1;
        }
    

    超时原因(时间复杂度分析):

    这种算法施加复杂度为O(n2),for循环嵌套for循环。(Collection.sort()的时间复杂度为nlogn)造成的原因是未对nums2进行排序,导致了对每一个nums2的数,都需要遍历nums1,虽然题目要求nums2的顺序不能改变,但是如果不对nums2进行排序的话,肯定会超时。

    优先队列+双指针

    我们使用优先队列加双指针的方式,先对nums1和nums2进行排序,这里我们使用在优先队列中使用int[]数组来记录nums2[i]的值和下标i,然后对nums2[i]进行降序排列。

     PriorityQueue<int[]> pq = new PriorityQueue<>((a, b) -> (b[1] - a[1]));
            int n = nums2.length;
            for (int i = 0; i < n; i++) {
                pq.add(new int[]{i, nums2[i]});
            }
            Arrays.sort(nums1);
            int l = 0, r = n - 1;
            int[] res = new int[n];
            while (!pq.isEmpty()) {
                int[] pair = pq.poll();
                if (nums1[r] > pair[1]) {
                    res[pair[0]] = nums1[r];
                    r--;
                } else {
                    res[pair[0]] = nums1[l];
                    l++;
                }
            }
            return res;
    

    然后我们对nums1进行降序排列。

    随后,我们用两个指针l,r分别指向nums1的开始和结尾。

    这里必须要说明的是,我们用nums1的最大的数和nums2最大的数比较,会有两种情况:

    1、如果nums1最大的数大于nums2最大的数(田忌的上等马跑过齐王的上等马):

    则让index=pq.poll()[0];使res[index]=nums1[r];

    2、如果nums1最大的数小于nums2最大的数:则找个下等马(nums1最小的数)去送,使res[index]=nums1[l](nums1[l]是nums1数组中最小的数);

    时间复杂度分析:

    很好分析;优先队列排序的时间复杂度为nlogn,算主体的复杂度为滑动窗口的复杂度O(n),所以总体来说复杂度为nlogn。

  • 相关阅读:
    机器学习项目流程(二)探索并可视化数据
    机器学习项目流程(一)初探数据集
    数据类型.md
    keepalived.md
    LVS.md
    tomcat多实例.md
    LANMP常用配置.md
    php-fpm配置参数.md
    Nginx学习.md
    Redis.md
  • 原文地址:https://www.cnblogs.com/ruonan1997/p/15243420.html
Copyright © 2011-2022 走看看