首页 > 其他分享 >【综合笔试题】难度 2/5,简单且经典面试题

【综合笔试题】难度 2/5,简单且经典面试题

时间:2023-01-25 20:07:11浏览次数:43  
标签:面试题 int 笔试 tset l2 难度 ans nums1 nums2

题目描述

这是 LeetCode 上的 ​​870. 优势洗牌​​ ,难度为 中等

Tag : 「红黑树」、「哈希表」、「排序」、「双指针」、「贪心」

给定两个大小相等的数组 ​​nums1​​​ 和 ​​nums2​​​,​​nums1​​​ 相对于 ​​nums​​​ 的优势可以用满足 ​​nums1[i] > nums2[i]​​​ 的索引 ​​i​​ 的数目来描述。

返回 ​​nums1​​​ 的任意排列,使其相对于 ​​nums2​​ 的优势最大化。

示例 1:

输入:nums1 = [2,7,11,15], nums2 = [1,10,4,11]

输出:[2,11,7,15]

示例 2:

输入:nums1 = [12,24,8,32], nums2 = [13,25,32,11]

输出:[24,32,8,12]

提示:

  • 【综合笔试题】难度 2/5,简单且经典面试题_List
  • nums2.length = nums1.length
  • 【综合笔试题】难度 2/5,简单且经典面试题_Java_02, 【综合笔试题】难度 2/5,简单且经典面试题_List_03

数据结构

显然,对于任意一个 【综合笔试题】难度 2/5,简单且经典面试题_后端_04 而言,我们应当在候选集合中选择比其大的最小数,若不存在这样的数字,则选择候选集合中的最小值

同时,由于 【综合笔试题】难度 2/5,简单且经典面试题_Java_05

也就是我们总共涉及两类操作:

  1. 实时维护一个候选集合,该集合支持高效查询比某个数大的数值操作;
  2. 对候选集合中每个数值的可使用次数进行记录,当使用到了候选集合中的某个数后,要对其进行计数减一操作,若计数为 【综合笔试题】难度 2/5,简单且经典面试题_数据结构_06,则将该数值从候选集合中移除。

计数操作容易想到哈希表,而实时维护候选集合并高效查询可以使用基于红黑树的 ​​TreeSet​​ 数据结构。

Java 代码:

class Solution {
public int[] advantageCount(int[] nums1, int[] nums2) {
int n = nums1.length;
TreeSet<Integer> tset = new TreeSet<>();
Map<Integer, Integer> map = new HashMap<>();
for (int x : nums1) {
map.put(x, map.getOrDefault(x, 0) + 1);
if (map.get(x) == 1) tset.add(x);
}
int[] ans = new int[n];
for (int i = 0; i < n; i++) {
Integer cur = tset.ceiling(nums2[i] + 1);
if (cur == null) cur = tset.ceiling(-1);
ans[i] = cur;
map.put(cur, map.get(cur) - 1);
if (map.get(cur) == 0) tset.remove(cur);
}
return ans;
}
}

Python 代码:

from sortedcontainers import SortedList

class Solution:
def advantageCount(self, nums1: List[int], nums2: List[int]) -> List[int]:
n = len(nums1)
cnts, tset = defaultdict(int), SortedList()
for i in range(n):
cnts[nums1[i]] += 1
if cnts[nums1[i]] == 1:
tset.add(nums1[i])
ans = [0] * n
for i in range(n):
t = nums2[i]
if (idx := tset.bisect_left(t + 1)) == len(tset):
idx = tset.bisect_left(-1)
ans[i] = tset[idx]
cnts[ans[i]] -= 1
if cnts[ans[i]] == 0:
tset.remove(ans[i])
return ans
  • 时间复杂度:【综合笔试题】难度 2/5,简单且经典面试题_Java_07
  • 空间复杂度:【综合笔试题】难度 2/5,简单且经典面试题_Java_08

排序 + 双指针

在解法一中,我们是从每个 【综合笔试题】难度 2/5,简单且经典面试题_数据结构_09 出发考虑,使用哪个 【综合笔试题】难度 2/5,简单且经典面试题_List_10

实际上,我们也能从 【综合笔试题】难度 2/5,简单且经典面试题_List_10 出发,考虑将其与哪个 【综合笔试题】难度 2/5,简单且经典面试题_数据结构_09

为了让每个决策回合具有独立性,我们需要对两数组进行排序,同时为了在构造答案时,能够对应回 ​​nums2​​​ 的原下标,排序前我们需要使用「哈希表」记录每个 【综合笔试题】难度 2/5,简单且经典面试题_数据结构_09

使用变量 ​​l1​​​ 代表当前决策将 【综合笔试题】难度 2/5,简单且经典面试题_Java_14 分配到哪个 ​​​nums2​​​ 的位置,使用 ​​l2​​​ 和 ​​r2​​​ 代表当前 ​​nums2​​​ 中还有 【综合笔试题】难度 2/5,简单且经典面试题_Java_15

可以证明我们在从前往后给每个 【综合笔试题】难度 2/5,简单且经典面试题_Java_14 分配具体位置时,分配的位置只会在 ​​​l2​​​ 和 ​​r2​​ 两者之间产生。

Java 代码:

class Solution {
public int[] advantageCount(int[] nums1, int[] nums2) {
int n = nums1.length;
Map<Integer, List<Integer>> map = new HashMap<>();
for (int i = 0; i < n; i++) {
List<Integer> list = map.getOrDefault(nums2[i], new ArrayList<>());
list.add(i);
map.put(nums2[i], list);
}
Arrays.sort(nums1); Arrays.sort(nums2);
int[] ans = new int[n];
for (int l1 = 0, l2 = 0, r2 = n - 1; l1 < n; l1++) {
int t = nums1[l1] > nums2[l2] ? l2 : r2;
List<Integer> list = map.get(nums2[t]);
int idx = list.remove(list.size() - 1);
ans[idx] = nums1[l1];
if (t == l2) l2++;
else r2--;
}
return ans;
}
}

Python 代码:

class Solution:
def advantageCount(self, nums1: List[int], nums2: List[int]) -> List[int]:
n = len(nums1)
mapping = defaultdict(list)
for i in range(n):
mapping[nums2[i]].append(i)
nums1.sort()
nums2.sort()
ans = [0] * n
l2, r2 = 0, n - 1
for l1 in range(n):
t = l2 if nums1[l1] > nums2[l2] else r2
ans[mapping[nums2[t]].pop()] = nums1[l1]
if t == l2:
l2 += 1
else:
r2 -= 1
return ans
  • 时间复杂度:【综合笔试题】难度 2/5,简单且经典面试题_Java_07
  • 空间复杂度:【综合笔试题】难度 2/5,简单且经典面试题_Java_08

最后

这是我们「刷穿 LeetCode」系列文章的第 ​​No.870​​ 篇,系列开始于 2021/01/01,截止于起始日 LeetCode 上共有 1916 道题目,部分是有锁题,我们将先把所有不带锁的题目刷完。

在这个系列文章里面,除了讲解解题思路以外,还会尽可能给出最为简洁的代码。如果涉及通解还会相应的代码模板。

为了方便各位同学能够电脑上进行调试和提交代码,我建立了相关的仓库:​​github.com/SharingSour…​​ 。

在仓库地址里,你可以看到系列文章的题解链接、系列文章的相应代码、LeetCode 原题链接和其他优选题解。

更多更全更热门的「笔试/面试」相关资料可访问排版精美的 ​​合集新基地​​

标签:面试题,int,笔试,tset,l2,难度,ans,nums1,nums2
From: https://blog.51cto.com/acoier/6022757

相关文章

  • 笔试:交换两个int的值,且不使用第三个变量的引入
    初级解法:#include<stdio.h>intmain(){inta=3;intb=5;printf("交换前:a=%db=%d\n",a,b);a=a+b;//a变成了两个数字的和但b还是原来的bb=a-b;//得到了原来的a,将......
  • 微软面试题
    例题1:为什么下水道的盖子是圆的?回答案例它们并不都是圆的,有些是方的。的确有些圆井盖,但我也看过方的、长方的。试题点评该求职者的回答巧妙之处在于敢于提出自己的看法,而不......
  • 【java面试题】lock和synchronized有什么区别?
    学习目标:掌握lock与synchronized的区别理解ReentrantLock的公平、非公平锁理解ReentrantLock中的条件变量lock与synchronized的区别有三个层面学习内容:1.......
  • 前端面试题 - javaScript系列
    Time:2023-01-2021:14:37ES6系列1.说说var、let、const之间的区别var、let、const三者区别可以围绕下面五点展开:变量提升暂时性死区块级作用域重复声明修......
  • 面试题-索引设计的原则
    索引设计的原则针对于数据量较大,且查询比较频繁的表建立索引。针对于常作为查询条件(where)、排序(orderby)、分组(groupby)操作的字段建立索引。尽量选择区分度高......
  • LeetCode.面试题02.05-链表求和-题解分析
    题目来源面试题02.05.链表求和题目详情给定两个用链表表示的整数,每个节点包含一个数位。这些数位是反向存放的,也就是个位排在链表首部。编写函数对这两个整数求和,并......
  • 前端面试题合集-第一篇
    前端面试题合集-第一篇......
  • 面试题-什么是最左前缀法则?什么时候索引将失效?
    什么是最左前缀法则?什么时候索引将失效?如果索引了多列(联合索引),要遵守最左前缀法则。最左前缀法则指的是查询从索引的最左列开始,并且不跳过索引中的列。如果跳跃某一列,索......
  • 2022最新MySQL高频面试题汇总
    sidebar:heading事务的四大特性?事务特性ACID:原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)、持久性(Durability)。原子性是指事务包含的所有操作要么全部成......
  • 2022年面试题之JS
    1. js数组的哪些方法会改变原数组pop()删除arrayObject的最后一个元素,把数组长度减1,并且返回它删除的元素的值push()方法可把它的参数顺序添加到arrayObject的尾......