题目描述
给你一个整数数组 nums 。你需要找到一个 连续子数组 ,如果对这个子数组中的所有元素进行按位 异或 运算,结果等于 0 。
请你返回 符合题目要求 的子数组的数目。
示例
示例 1:
输入:nums = [2,1,3] 输出:3 解释:存在三个符合题目要求的子数组:
- [2]:2 ^ 2 = 0
- [1]:1 ^ 1 = 0
- [2,1,3]:2 ^ 1 ^ 3 = 0
示例 2:
输入:nums = [1,1,1,1,1] 输出:10 解释:每个子数组都符合题目要求。
示例 3:
输入:nums = [2,3,1,6,7] 输出:4 解释:只有四个子数组符合题目要求:
- [1]:1 ^ 1 = 0
- [6]:6 ^ 6 = 0
- [2,3,1,6]:2 ^ 3 ^ 1 ^ 6 = 0
- [3,1,6]:3 ^ 1 ^ 6 = 0
解题思路
这道题可以用前缀和的思想来解决。我们可以用一个哈希表来记录每个前缀和的出现次数,其中前缀和就是从数组开头到当前位置的所有元素的异或和。如果两个前缀和相等,那么它们之间的子数组的异或和就是0。例如,如果前缀和为[0,2,3,0,7],那么第一个0和第四个0之间的子数组[2,3]的异或和就是0。因此,我们只需要遍历一遍数组,计算每个位置的前缀和,并在哈希表中查找是否有相同的前缀和出现过,如果有,就说明存在一个符合条件的子数组,并把它的个数加到答案中。最后,我们还需要考虑前缀和本身为0的情况,这时候也需要把答案加一。
Python代码
class Solution:
def countTriplets(self, nums: List[int]) -> int:
# 初始化前缀和为0
prefix = 0
# 初始化哈希表,记录每个前缀和出现的次数
# 初始时,前缀和为0出现了一次
count = {0: 1}
# 初始化答案为0
ans = 0
# 遍历数组中的每个元素
for num in nums:
# 计算当前位置的前缀和
prefix ^= num
# 如果当前前缀和在哈希表中出现过,说明存在一个符合条件的子数组
if prefix in count:
# 把符合条件的子数组的个数加到答案中
ans += count[prefix]
# 把当前前缀和在哈希表中的次数加一
count[prefix] = count.get(prefix, 0) + 1
# 返回答案
return ans
题目描述
给你一个整数数组 arr ,请你找出并返回其中最大的幸运数 。
「幸运数」是指在数组中出现频率 恰好等于 其数值的数。
如果数组中不存在这样的数,则返回 -1 。如果数组中存在多个幸运数,只需返回 最大 的那个。
示例
示例 1:
输入:arr = [2,2,3,4] 输出:2 解释:数组中唯一的幸运数是 2 ,因为数组中恰好有 2 个 2 。
示例 2:
输入:arr = [1,2,2,3,3,3] 输出:3 解释:1、2 以及 3 都是幸运数,只需要返回其中最大的 3 。
示例 3:
输入:arr = [2,2,2,3,3] 输出:-1 解释:数组中不存在幸运数。
示例 4:
输入:arr = [5] 输出:-1
示例 5:
输入:arr = [7,7,7,7,7,7,7] 输出:7
解题思路
这道题可以用一个哈希表来记录每个元素出现的次数,然后遍历哈希表,找出满足条件的幸运数,并记录最大的一个。如果没有找到任何幸运数,就返回-1。
Python代码
class Solution:
def findLucky(self, arr: List[int]) -> int:
# 初始化哈希表,记录每个元素出现的次数
count = {}
# 遍历数组中的每个元素
for num in arr:
# 把元素在哈希表中的次数加一
count[num] = count.get(num, 0) + 1
# 初始化答案为-1
ans = -1
# 遍历哈希表中的每个键值对
for num, freq in count.items():
# 如果键和值相等,说明是一个幸运数
if num == freq:
# 更新答案为最大的幸运数
ans = max(ans, num)
# 返回答案
return ans
题目描述
给你一个长度为 n 的整数数组 nums ,和一个整数 k 。
请你返回数组中乘积最小的 k 个 连续子数组 的乘积组成的数组。可以按 任意 顺序返回答案。
示例
示例 1:
输入:nums = [10,2,3,7,5,1,4], k = 3 输出:[2,3,5] 解释:乘积最小的连续子数组分别是 [2] ,[3] 和 [5] 。注意,即使乘积相同,也需要按照出现在原数组中的顺序返回结果。
示例 2:
输入:nums = [10,2,-3,-7,5,1,-4], k = 3 输出:[-7,-4,-3] 解释:乘积最小且负数的连续子数组分别是 [-7] ,[-4] 和 [-3] 。注意,即使乘积相同,也需要按照出现在原数组中的顺序返回结果。
示例 3:
输入:nums = [10,2,3,7,5,1,4], k = 4 输出:[10,2,3,5] 解释:乘积最小的连续子数组分别是 [10] ,[2] ,[3] 和 [5] 。注意,即使乘积相同,也需要按照出现在原数组中的顺序返回结果。
解题思路
这道题可以用一个优先队列(堆)来维护乘积最小的 k 个连续子数组。我们可以用一个双指针的方法来遍历所有的连续子数组,对于每个子数组,我们计算它的乘积,并把它和它的起始位置一起放入优先队列中。优先队列按照乘积从大到小排序,这样我们可以保证队列中始终有 k 个最小的乘积。当遍历完所有的子数组后,我们就可以从优先队列中取出 k 个元素,并按照它们在原数组中出现的顺序返回答案。
Python代码
import heapq
class Solution:
def smallestK(self, nums: List[int], k: int) -> List[int]:
# 初始化优先队列(堆),按照乘积从大到小排序
queue = []
# 初始化左指针为0
left = 0
# 初始化当前子数组的乘积为1
product = 1
# 遍历右指针从0到n-1
for right in range(len(nums)):
# 更新当前子数组的乘积
product *= nums[right]
# 如果当前子数组的乘积为0,说明不能再往右扩展了,需要把左指针移动到右指针的下一个位置,并重置乘积为1
if product == 0:
left = right + 1
product = 1
continue
# 否则,把当前子数组的乘积和起始位置放入优先队列中
heapq.heappush(queue, (-product, left))
# 如果优先队列中元素个数超过k,就弹出最大的元素,保证队列中始终有k个最小的乘积
if len(queue) > k:
heapq.heappop(queue)
# 初始化答案列表为空
ans = []
# 把优先队列中的元素按照起始位置从小到大排序
queue.sort(key=lambda x: x[1])
# 遍历优先队列中的元素
for product, left in queue:
# 取出乘积的绝对值,放入答案列表中
ans.append(abs(product))
# 返回答案列表
return ans
题目描述
给你一个长度为 n 的整数数组 nums ,和一个整数 k 。
请你返回数组中乘积最小的 k 个 异或和 的乘积组成的数组。可以按 任意 顺序返回答案。
「异或和」是指对数组中的所有元素进行按位 异或 运算的结果。
示例
示例 1:
输入:nums = [10,2,3,7,5,1,4], k = 3 输出:[2,3,5] 解释:乘积最小的异或和分别是 [2] ,[3] 和 [5] 。注意,即使乘积相同,也需要按照出现在原数组中的顺序返回结果。
示例 2:
输入:nums = [10,2,-3,-7,5,1,-4], k = 3 输出:[-7,-4,-3] 解释:乘积最小且负数的异或和分别是 [-7] ,[-4] 和 [-3] 。注意,即使乘积相同,也需要按照出现在原数组中的顺序返回结果。
示例 3:
输入:nums = [10,2,3,7,5,1,4], k = 4 输出:[10,2,3,5] 解释:乘积最小的异或和分别是 [10] ,[2] ,[3] 和 [5] 。注意,即使乘积相同,也需要按照出现在原数组中的顺序返回结果。
解题思路
这道题可以用一个优先队列(堆)来维护乘积最小的 k 个异或和。我们可以用一个回溯的方法来遍历所有可能的异或和,对于每个异或和,我们计算它的绝对值,并把它放入优先队列中。优先队列按照绝对值从大到小排序,这样我们可以保证队列中始终有 k 个最小的绝对值。当遍历完所有可能的异或和后,我们就可以从优先队列中取出 k 个元素,并按照它们在原数组中出现的顺序返回答案。
Python代码
import heapq
class Solution:
def smallestK(self, nums: List[int], k: int) -> List[int]:
# 初始化优先队列(堆),按照绝对值从大到小排序
queue = []
# 定义一个回溯函数,用于遍历所有可能的异或和
def backtrack(start, xor):
# 如果已经遍历完所有元素,就把当前异或和放入优先队列中
if start == len(nums):
heapq.heappush(queue, (-abs(xor), xor))
# 如果优先队列中元素个数超过k,就弹出最大的元素,保证队列中始终有k个最小的绝对值
if len(queue) > k:
heapq.heappop(queue)
return
# 对于当前元素,有两种选择:加入或不加入异或和
# 不加入时,直接跳过当前元素,继续遍历下一个元素
backtrack(start + 1, xor)
# 加入时,更新当前异或和,继续遍历下一个元素
backtrack(start + 1, xor ^ nums[start])
# 调用回溯函数,从第一个元素开始遍历,初始异或和为0
backtrack(0, 0)
# 初始化答案列表为空
ans = []
# 把优先队列中的元素按照出现在原数组中的顺序排序
queue.sort(key=lambda x: nums.index(x[1]))
# 遍历优先队列中的元素
for _, xor in queue:
# 取出异或和,放入答案列表中
ans.append(xor)
# 返回答案列表
return ans