田忌赛马(沾点贪心算法)

一、题目

给定两个大小相等的数组 nums1 和 nums2,nums1 相对于 nums 的优势可以用满足 nums1[i] > nums2[i] 的索引 i 的数目来描述。

返回 nums1 的任意排列,使其相对于 nums2 的优势最大化。

也就是说针对数组2中的每个元素,如果在数组1中有比其大的则建立连接(使其索引相同),如果没有更大的,则使用数组1中最小的元素与其建立连接,达到田忌赛马,中等马对下等马,下等马对上等马的目的。

二、思路

针对两个数组进行递增排序。 注:此处排序想要得到的不是递增数组本身,而是递增数组元素在原数组中的索引数组。

此时,nums1和nums2为递增数组,将两个数组进行比较:

1. 中等马对下等马:如果nums1中的首个元素大于nums2中的首个元素,由于nums1中的首个元素是整个数组中的最小元素,则是最小解最优解,那么建立连接,并移除两个比较元素(因为已经建立好连接,不需要继续比较)。

2.下等马对上等马:如果nums1中的首个元素小于nums2中的首个元素,说明该元素小于nums2中的所有元素(因为是nums2中的最小元素),同时也说明nums2中必有一个元素是大于nums1中所有元素的,因为nums1和2数量相等。所以此时将1中该元素与2中最大的元素建立连接,删除两个元素。

注意点:

在循环比较时nums2需要使用循环外设置的left和right指针,双指针不能随着循环的进行随意增加,必须要满足某一匹配条件时才能变动。

三、实现

def advantageCount(self, nums1: List[int], nums2: List[int]) -> List[int]:
        
        size = len(nums1)
        s1 = list(range(size))
        s2 = list(range(size))

        s1.sort(key = lambda x: nums1[x])
        s2.sort(key = lambda x: nums2[x])

        
        left = 0
        right = size - 1
        
        nums = [0]*size
        for i in range(size):
            if nums1[s1[i]] > nums2[s2[left]]:
                nums[s2[left]] = nums1[s1[i]]
                left += 1
            else:
                nums[s2[right]] = nums1[s1[i]]
                right -= 1
        
        return nums

首先定义s1,s2,内容是0~size的连续序列,意为原数组的默认递增索引。

然后根据nums1和2中的值,对索引进行排序,这样既能对nums1和nums2进行排序,又能保存原来的顺序。

设置双指针left和right用于比较nums2中的值。

定义nums数组接受结果。

在循环里,遍历s1数组,根据nums1中的值与双指针指向的nums2数组中的值进行比较,如果nums1最小值大于nums2最小值,建立连接,left指针后移(意为移除nums2中的最小元素)。

如果nums1最小值小于nums2最小值,与right指针指向的nums2中最大元素建立连接,right指针左移(意为移除nums2中最大元素)。

注:因为在每次比较中,无论如何nums1中的最小元素都会被消除,所以可以使用for循环中的i直接遍历,而每次比较中消除的nums2中的元素可能是最大元素也可能是最小元素,所以使用双指针进行消除。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值