Q1&Q4
100124. 找出强数对的最大异或值 II
给你一个下标从 0 开始的整数数组 nums
。如果一对整数 x
和 y
满足以下条件,则称其为 强数对 :
你需要从 nums
中选出两个整数,且满足:这两个整数可以形成一个强数对,并且它们的按位异或(XOR
)值是在该数组所有强数对中的 最大值 。
返回数组 nums
所有可能的强数对中的 最大 异或值。
注意 ,你可以选择同一个整数两次来形成一个强数对。
示例 1:
1 2 3 4 输入:nums = [1,2,3,4,5] 输出:7 解释:数组 nums 中有 11 个强数对:(1, 1), (1, 2), (2, 2), (2, 3), (2, 4), (3, 3), (3, 4), (3, 5), (4, 4), (4, 5) 和 (5, 5) 。 这些强数对中的最大异或值是 3 XOR 4 = 7 。
示例 2:
1 2 3 4 输入:nums = [10,100] 输出:0 解释:数组 nums 中有 2 个强数对:(10, 10) 和 (100, 100) 。 这些强数对中的最大异或值是 10 XOR 10 = 0 ,数对 (100, 100) 的异或值也是 100 XOR 100 = 0 。
示例 3:
1 2 3 4 输入:nums = [500 ,520 ,2500 ,3000 ]输出:1020 解释:数组 nums 中有 6 个强数对:(500, 500 ), (500, 520 ), (520, 520 ), (2500, 2500 ), (2500, 3000 ) 和 (3000, 3000 ) 。 这些强数对中的最大异或值是 500 XOR 520 = 1020 ;另一个异或值非零的数对是 (5, 6 ) ,其异或值是 2500 XOR 3000 = 636 。
提示:
1 <= nums.length <= 5 * 104
1 <= nums[i] <= 220 - 1
根据条件|x - y| <= min(x, y)
,很容易想到双指针(滑动窗口)维护满足条件区间,那么就只剩下一个区间内求异或值最大的问题了,很明显可以使用01trie
来实现,相较于平常的01trie
,这个需要实现remove,其实也比较简单,参考正常的字典树,维护一个cnt即可。时间复杂度O(nlogn+nlogU)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 class Solution : __slots__ = ['root' ] class Node : __slots__ = ['nodes' , 'cnt' ] def __init__ (self ): self.nodes = [None , None ] self.cnt = 0 def __init__ (self ): self.root = self.Node() def add (self, x: int ) -> None : temp = self.root for i in range (21 , -1 , -1 ): v = ((x >> i) & 1 ) ^ 1 if temp.nodes[v] is None : temp.nodes[v] = self.Node() temp = temp.nodes[v] temp.cnt += 1 def remove (self, x ): temp = self.root for i in range (21 , -1 , -1 ): v = ((x >> i) & 1 ) ^ 1 temp.nodes[v].cnt -= 1 if temp.nodes[v].cnt == 0 : temp.nodes[v] = None return temp = temp.nodes[v] def get (self, x ): ans = 0 temp = self.root for i in range (21 , -1 , -1 ): v = (x >> i) & 1 if temp.nodes[v] is not None : ans |= (1 << i) temp = temp.nodes[v] else : temp = temp.nodes[v ^ 1 ] return ans def maximumStrongPairXor (self, nums ): ans = 0 nums.sort() n = len (nums) l = 0 for r in range (n): self.add(nums[r]) while nums[r] - nums[l] > nums[l]: self.remove(nums[l]) l += 1 ans = max (ans, self.get(nums[r])) return ans
Q2
100128. 高访问员工
给你一个长度为 n
、下标从 0 开始的二维字符串数组 access_times
。对于每个 i
(0 <= i <= n - 1
),access_times[i][0]
表示某位员工的姓名,access_times[i][1]
表示该员工的访问时间。access_times
中的所有条目都发生在同一天内。
访问时间用 四位 数字表示, 符合 24 小时制 ,例如 "0800"
或 "2250"
。
如果员工在 同一小时内 访问系统 三次或更多 ,则称其为 高访问 员工。
时间间隔正好相差一小时的时间 不 被视为同一小时内。例如,"0815"
和 "0915"
不属于同一小时内。
一天开始和结束时的访问时间不被计算为同一小时内。例如,"0005"
和 "2350"
不属于同一小时内。
以列表形式,按任意顺序,返回所有 高访问 员工的姓名。
示例 1:
1 2 3 4 5 输入:access_times = [["a" ,"0549" ],["b" ,"0457" ],["a" ,"0532" ],["a" ,"0621" ],["b" ,"0540" ]] 输出:["a" ] 解释:"a" 在时间段 [05 :32 , 06 :31 ] 内有三条访问记录,时间分别为 05 :32 、05 :49 和 06 :21 。 但是 "b" 的访问记录只有两条。 因此,答案是 ["a" ] 。
示例 2:
1 2 3 4 5 输入:access_times = [["d" ,"0002" ],["c" ,"0808" ],["c" ,"0829" ],["e" ,"0215" ],["d" ,"1508" ],["d" ,"1444" ],["d" ,"1410" ],["c" ,"0809" ]] 输出:["c" ,"d" ] 解释:"c" 在时间段 [08 :08 , 09 :07 ] 内有三条访问记录,时间分别为 08 :08 、08 :09 和 08 :29 。"d" 在时间段 [14 :10 , 15 :09 ] 内有三条访问记录,时间分别为 14 :10 、14 :44 和 15 :08 。 然而,"e" 只有一条访问记录,因此不能包含在答案中,最终答案是 ["c" ,"d" ] 。
示例 3:
1 2 3 4 5 输入:access_times = [["cd" ,"1025" ],["ab" ,"1025" ],["cd" ,"1046" ],["cd" ,"1055" ],["ab" ,"1124" ],["ab" ,"1120" ]] 输出:["ab" ,"cd" ] 解释:"ab" 在时间段 [10 :25 , 11 :24 ] 内有三条访问记录,时间分别为 10 :25 、11 :20 和 11 :24 。"cd" 在时间段 [10 :25 , 11 :24 ] 内有三条访问记录,时间分别为 10 :25 、10 :46 和 10 :55 。 因此,答案是 ["ab" ,"cd" ] 。
提示:
1 <= access_times.length <= 100
access_times[i].length == 2
1 <= access_times[i][0].length <= 10
access_times[i][0]
仅由小写英文字母组成。
access_times[i][1].length == 4
access_times[i][1]
采用24小时制表示时间。
access_times[i][1]
仅由数字 '0'
到 '9'
组成。
根据每个人分组,排序时间,滑动窗口即可,如果有一个小时内超过三次的,就添加到ans当中。时间复杂度O(Lnlogn)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 class Solution : def findHighAccessEmployees (self, access_times: List [List [str ]] ) -> List [str ]: mp = {} ans = [] for x, y in access_times: if x not in mp: mp[x] = [] mp[x].append(y) def check (s1: str , s2: str ) -> bool : h1 = int (s1[:2 ]) m1 = int (s1[2 :]) h2 = int (s2[:2 ]) m2 = int (s2[2 :]) diff = m1 - m2 + (h1 - h2) * 60 return diff < 60 for x, v in mp.items(): v.sort() n = len (v) if n < 3 : continue for i in range (2 , n): s1, s2 = v[i], v[i - 2 ] if check(s1, s2): ans.append(x) break return ans
Q3
100117. 最大化数组末位元素的最少操作次数
给你两个下标从 0 开始的整数数组 nums1
和 nums2
,这两个数组的长度都是 n
。
你可以执行一系列 操作(可能不执行) 。
在每次操作中,你可以选择一个在范围 [0, n - 1]
内的下标 i
,并交换 nums1[i]
和 nums2[i]
的值。
你的任务是找到满足以下条件所需的 最小 操作次数:
nums1[n - 1]
等于 nums1
中所有元素的 最大值 ,即 nums1[n - 1] = max(nums1[0], nums1[1], ..., nums1[n - 1])
。
nums2[n - 1]
等于 nums2
中所有元素的 最大值 ,即 nums2[n - 1] = max(nums2[0], nums2[1], ..., nums2[n - 1])
。
以整数形式,表示并返回满足上述 全部 条件所需的 最小 操作次数,如果无法同时满足两个条件,则返回 -1
。
示例 1:
1 2 3 4 5 6 7 输入:nums1 = [1,2,7] ,nums2 = [4,5,3] 输出:1 解释:在这个示例中,可以选择下标 i = 2 执行一次操作。 交换 nums1[2] 和 nums2[2] 的值,nums1 变为 [1,2,3] ,nums2 变为 [4,5,7] 。 同时满足两个条件。 可以证明,需要执行的最小操作次数为 1 。 因此,答案是 1 。
示例 2:
1 2 3 4 5 6 7 8 9 10 输入:nums1 = [2,3,4,5,9] ,nums2 = [8,8,4,4,4] 输出:2 解释:在这个示例中,可以执行以下操作: 首先,选择下标 i = 4 执行操作。 交换 nums1[4] 和 nums2[4] 的值,nums1 变为 [2,3,4,5,4] ,nums2 变为 [8,8,4,4,9] 。 然后,选择下标 i = 3 执行操作。 交换 nums1[3] 和 nums2[3] 的值,nums1 变为 [2,3,4,4,4] ,nums2 变为 [8,8,4,5,9] 。 同时满足两个条件。 可以证明,需要执行的最小操作次数为 2 。 因此,答案是 2 。
示例 3:
1 2 3 4 输入:nums1 = [1 ,5 ,4 ],nums2 = [2 ,5 ,3 ] 输出:-1 解释:在这个示例中,无法同时满足两个条件。 因此,答案是 -1 。
提示:
1 <= n == nums1.length == nums2.length <= 1000
1 <= nums1[i] <= 109
1 <= nums2[i] <= 109
显然,如果两个数组中的最大值不位于nums1[n - 1]
或nums2[n - 1]
,一定不符合要求,那么结果就只有两种可能了,第一种是不交换最后一对,计算需要交换多少次,另一个就是交换最后一对需要计算多少次,取最小值即可,如果中间有不符合的情况直接返回-1即可。时间复杂度O(n)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 lass Solution: def minOperations (self, nums1: List [int ], nums2: List [int ] ) -> int : n1 = copy.deepcopy(nums1) n2 = copy.deepcopy(nums2) mx1, mx2 = max (nums1), max (nums2) mx = max (mx1, mx2) if mx != nums1[-1 ] and mx != nums2[-1 ]: return -1 ans = 0 n = len (nums2) for i in range (n - 2 , -1 , -1 ): if nums1[i] <= nums1[-1 ] and nums2[i] <= nums2[-1 ]: continue else : nums2[i], nums1[i] = nums1[i], nums2[i] ans += 1 if nums1[i] > nums1[-1 ] or nums2[i] > nums2[-1 ]: return -1 nums1 = copy.deepcopy(n1) nums2 = copy.deepcopy(n2) ans1 = 1 nums1[-1 ], nums2[-1 ] = nums2[-1 ], nums1[-1 ] for i in range (n - 2 , -1 , -1 ): if nums1[i] <= nums1[-1 ] and nums2[i] <= nums2[-1 ]: continue else : nums2[i], nums1[i] = nums1[i], nums2[i] ans1 += 1 if nums1[i] > nums1[-1 ] or nums2[i] > nums2[-1 ]: return -1 return min (ans, ans1)