这个方法名是一名网友给起的,很形象。简单理解就是,在一个数组中,将数值为 a 的元素放到索引为 a 的位置上去,这是一种降低空间复杂度的方法,在一些有条件限制的场景中非常适用。下面给两个力扣的例子进行详解。
练习题目1:
设备中存有 n
个文件,文件 id
记于数组 documents
。若文件 id
相同,则定义为该文件存在副本。请返回任一存在副本的文件 id
。
示例 1:
输入:documents = [2, 5, 3, 0, 5, 0] 输出:0 或 5
提示:
0 ≤ documents[i] ≤ n-1
2 <= n <= 100000
这里利用的是 0 ≤ documents[i] ≤ n-1 这一点,所以我们可以把 documents[i] 的值放到 索引为 documents[i] 的位置,而 documents[i] 位置原来的值则放到索引 i 处,相当于这两个位置上的值进行交换。如果在交换的过程中发现,将要放进去的位置原来的值和即将放进去的值相等,则说明这个数出现了两次。
- class Solution(object):
- def findRepeatDocument(self, documents):
- # 先排序后匹配法:32ms, 21.1MB
- # documents = sorted(documents)
- # for i in range(len(documents) - 1):
- # if documents[i] == documents[i+1]:
- # return documents[i]
-
- # 哈希法:32ms, 22.3MB
- # num_set = set()
- # for i in range(len(documents)):
- # if documents[i] in num_set:
- # return documents[i]
- # else:
- # num_set.add(documents[i])
-
- # 原地哈希法:16ms, 19.8MB
- i = 0
- while i < len(documents):
- if documents[i] != i:
- if documents[documents[i]] == documents[i]:
- return documents[i]
- temp = documents[documents[i]]
- documents[documents[i]] = documents[i]
- documents[i] = temp
- else:
- i += 1
练习题2:
给你一个未排序的整数数组 nums
,请你找出其中没有出现的最小的正整数。
请你实现时间复杂度为 O(n)
并且只使用常数级别额外空间的解决方案。
示例 1:
输入:nums = [1,2,0] 输出:3
示例 2:
输入:nums = [3,4,-1,1] 输出:2
示例 3:
输入:nums = [7,8,9,11,12] 输出:1
提示:
1 <= nums.length <= 5 * 10^5
-2^31 <= nums[i] <= 2^31 - 1
这个是原地哈希 # 80ms, 20.4MB,空间占用少一些
- class Solution(object):
- def firstMissingPositive(self, nums):
- n = len(nums)
- i = 0
- while i < n:
- if nums[i] > 0 and nums[i] <= n and nums[i] != i + 1:
- if nums[nums[i] - 1] == nums[i]:
- nums[i] = -1
- i += 1
- else:
- temp = nums[nums[i] - 1]
- nums[nums[i] - 1] = nums[i]
- nums[i] = temp
- else:
- i += 1
- for i in range(0, n):
- if nums[i] != i + 1:
- return i + 1
- return n + 1
下面这个是先排序后查找,提交记录是:64ms, 21.1M,时间少一点
- class Solution(object):
- def firstMissingPositive(self, nums):
- n = len(nums)
- nums = sorted(nums)
- X = 1
- for i in range(n):
- if nums[i] == X:
- X += 1
- elif nums[i] > X:
- break
- return X