正负号标记法在数组相关程序中的使用

正负号标记法在一些关于数组的编程中往往能起到一些出其不意的效果,在这里我以几个示例来解释一下正负号标记法的用法。

1,我们看一下LeetCode的第448题。该题告知你一个有n个元素的数组,数组的所有元素介于1到n之间(包含1与n),但是 一些元素出现了两次,其他的元素都只出现一次,找出所有没有出现的数值。要求你不用额外的空间,并且在O(n)时间复杂度下解决该问题。你可以假设返回的列表不算在额外的元素中。

例如:

Input:
[4,3,2,7,8,2,3,1]

Output:
[5,6]
我们再分析一下题目,给定的n个元素,每个元素都介于1到n,给出这个条件,首先想到的就是可否将数组中的元素与数组的下标对应起来?(这基本可以成为一个套路,当看到这种题目时,首先想到的就是将数组的元素与数组的下标对应起来)。我们用正负号标记法来解决这道题。首先我们遍历整个数组,当前元素为i,令nums[abs(i)-1]=-abs(nums[abs(i)-1]),即让每个元素所对应的下标的元素值变成一个负值。还以上面的例子来说,经过这个操作后数组变为:[-4, -3, -2, -7, 8, 2, -3, -1]。然后再次对数组进行遍历,将值为正数对应的下标加1即为求得结果。处理的后的数组有两个正值,分别为8,2,它们对应的下标为4和5,加1后变为5和6,则未出现的数值为[5, 6]。

我们用Python代码来实现上面的算法:

class Solution(object):
    def findDisappearedNumbers(self, nums):
        """
        :type nums: List[int]
        :rtype: List[int]
        """
        for i in nums:
             nums[i-1] = -abs(nums[abs(i)-1])
        return [i+1 for i, j in enumerate(nums) if j>0]

2,接下来我们再看一下leetcode的第442题。此题的题干与上题一样, 也是有一个n个元素的数组,数组的元素介于1到n之间(包含1到n),一些元素出现了一次,另一些元素出现了两次,让你找出所有出现了两次的元素。要求和上题一样,也是O(n)的空间复杂度,无额外的空间。

例如:

Input:
[4,3,2,7,8,2,3,1]

Output:
[2,3]
与上题一样的思路,看到条件,首先想到的就是可否将数组中的元素与数组的下标对应起来。我们首先遍历数组,将元素值对应的下标所在的元素设为一个负值,比如让其乘以-1;如果在遍历的时候发现元素值对应下标的元素的值为负值,就说明该元素在之前出现过,即出现了两次。

我们用Python代码来实现上面的算法:

class Solution(object):
    def findDuplicates(self, nums):
        """
        :type nums: List[int]
        :rtype: List[int]
        """
        ans = []
        for i in nums:
            if nums[abs(i)-1]<0:
                ans.append(abs(i))
            else:
                nums[abs(i)-1] *= -1
        return ans




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值