贪心问题

112 阅读2分钟

参考:

  1. 田忌赛马背后的算法决策
类型问题描述完成
402. 移掉K位数字
435. 无重叠区间
55. 跳跃游戏
135. 分发糖果
759. 员工空闲时间
253. 会议室 II
767. 重构字符串
1497. 检查数组对是否可以被k整除
870. 优势洗牌
955. 删列造序 II
991. 坏了的计算器
621. 任务调度器
44. 通配符匹配

870. 优势洗牌

我的思路:

对于nums1中,每一个元素找到对于nums2同位置优势元素中的最小值,这样处理完之后,优势应该是最大的。

这个解法虽然是能通过,但是效率有点低,想一想如何优化?

解答成功:
	执行耗时:271 ms,击败了5.01% 的Java用户
	内存消耗:58.9 MB,击败了23.88% 的Java用户
class Solution {
    public int[] advantageCount(int[] nums1, int[] nums2) { 
        
        int len = nums1.length;
        int[] ans = new int[len];
        
        // 为了方便查找nums1,需要先对nums1进行排序
        Arrays.sort(nums1);
        
        // nums1的内容是不断变化的,因为每次选择完nums1的时候,下一次不能选择同样的元素,所以用List更加方便
        List<Integer> list1 = new ArrayList<>();
        for (int num : nums1) {
            list1.add(num);
        }
        for (int i = 0; i < len; i++) {
            int idx = search(list1, nums2[i]);
            ans[i] = list1.get(idx);
            list1.remove(idx);
        }
        return ans;
    }

    // 用二分查找更快些
    public int search(List<Integer> nums, int k) {
        int left = 0;
        int right = nums.size();
        while (left < right) {
            int mid = left + (right - left) / 2;
            if (nums.get(mid) <= k) {
                left = mid + 1;
            } else {
                right = mid;
            }
        }
        // 找到比k大的第一个元素,这里没有返回left-1是因为不能等于k,必须是大于k
        // 当left == nums.size()时,说明nums里的所有元素都小于k
        return left == nums.size() ? 0 : left;
    }
}

参考了labuladong的思路。

用田忌赛马的方法。用nums1的劣马去匹配nums2的好马。

  1. nums2按照降序排列
  2. nums1按照升序排列
//leetcode submit region begin(Prohibit modification and deletion)
class Solution {
    public int[] advantageCount(int[] nums1, int[] nums2) {
        // 对于nums1中,每一个元素找到对于nums2同位置优势元素中的最小值
        // 这样处理完之后,优势应该是最大的
        Arrays.sort(nums1);
        int len = nums1.length;

        PriorityQueue<int[]> queue = new PriorityQueue<>((o1, o2) -> {
            return o2[1] - o1[1];
        });
        for (int i = 0; i < len; i++) {
            queue.offer(new int[]{i, nums2[i]});
        }
        int right = len - 1;
        int left = 0;
        int[] ans = new int[len];
        while (!queue.isEmpty()) {
            int[] cur2 = queue.poll();
            // 这已经是2中跑的最快的马了,因为2是降序排列
            // 1也用跑的最快的马出列,如果比不过2,那就用自己跑的最慢的马跟2跑的最快的马比赛,如果比得过,因为双方都是最快的,可以直接对子,也不影响
            if (nums1[right] > cur2[1]) {
                ans[cur2[0]] = nums1[right];
                right--;
            } else {
                ans[cur2[0]] = nums1[left];
                left++;
            }
        }
        return ans;
    }
}
//leetcode submit region end(Prohibit modification and deletion)