Medium
题目描述
给你一个整数数组 cards,其中 cards[i] 表示第 i 张卡牌的值。如果两张卡牌的值相同,则认为这一对卡牌匹配。
返回你必须拿起的最少连续卡牌数,以使其中包含一对匹配的卡牌。如果无法得到一对匹配的卡牌,返回 -1。
示例 1:
输入:cards = [3,4,2,3,4,7]
输出:4
解释:我们可以拿起卡牌 [3,4,2,3],其中包含匹配的一对值为 3 的卡牌。注意,拿起卡牌 [4,2,3,4] 也是最优方案。
示例 2:
输入:cards = [1,0,5,3]
输出:-1
解释:无法拿起一组连续的卡牌,其中包含匹配的卡牌。
提示:
1 <= cards.length <= 10^50 <= cards[i] <= 10^6
解题思路
这道题要求找到包含一对相同值卡牌的最短连续子数组长度。
核心思路: 当我们遇到一个值时,如果之前见过相同的值,那么从上次出现位置到当前位置的区间就包含了一对匹配卡牌。我们要找的是所有这样区间中长度最小的。
算法步骤:
- 使用哈希表记录每个卡牌值最后一次出现的位置
- 遍历数组,对于每个位置的卡牌值:
- 如果该值之前出现过,计算当前位置与上次出现位置的距离+1(即子数组长度)
- 更新最小长度
- 更新该值在哈希表中的最新位置
- 如果找到了匹配的卡牌对,返回最小长度;否则返回-1
时间复杂度: O(n),只需遍历一次数组 空间复杂度: O(k),k为不同卡牌值的数量,最坏情况下为O(n)
这种方法比暴力枚举所有连续子数组更高效,避免了O(n³)的复杂度。
代码实现
class Solution {
public:
int minimumCardPickup(vector<int>& cards) {
unordered_map<int, int> lastIndex;
int minLen = INT_MAX;
for (int i = 0; i < cards.size(); i++) {
if (lastIndex.find(cards[i]) != lastIndex.end()) {
minLen = min(minLen, i - lastIndex[cards[i]] + 1);
}
lastIndex[cards[i]] = i;
}
return minLen == INT_MAX ? -1 : minLen;
}
};
class Solution:
def minimumCardPickup(self, cards: List[int]) -> int:
last_index = {}
min_len = float('inf')
for i, card in enumerate(cards):
if card in last_index:
min_len = min(min_len, i - last_index[card] + 1)
last_index[card] = i
return min_len if min_len != float('inf') else -1
public class Solution {
public int MinimumCardPickup(int[] cards) {
Dictionary<int, int> lastIndex = new Dictionary<int, int>();
int minLen = int.MaxValue;
for (int i = 0; i < cards.Length; i++) {
if (lastIndex.ContainsKey(cards[i])) {
minLen = Math.Min(minLen, i - lastIndex[cards[i]] + 1);
}
lastIndex[cards[i]] = i;
}
return minLen == int.MaxValue ? -1 : minLen;
}
}
var minimumCardPickup = function(cards) {
const lastIndex = new Map();
let minDistance = Infinity;
for (let i = 0; i < cards.length; i++) {
if (lastIndex.has(cards[i])) {
minDistance = Math.min(minDistance, i - lastIndex.get(cards[i]) + 1);
}
lastIndex.set(cards[i], i);
}
return minDistance === Infinity ? -1 : minDistance;
};
复杂度分析
| 复杂度类型 | 复杂度 | 说明 |
|---|---|---|
| 时间复杂度 | O(n) | 只需遍历一次数组,哈希表操作为O(1) |
| 空间复杂度 | O(k) | k为不同卡牌值的数量,最坏情况O(n) |