2023-04-08:社交网络中的最优邀请策略探究。本文以小红准备开宴会为例,提出一种基于贪心算法和二分查找的解决方案,帮助读者在保证愉悦值不低于k的前提下,最小化宴会的阶层差距。
2023-04-08:小红有n个朋友, 她准备开个宴会,邀请一些朋友,
i号朋友的愉悦值为a[i],财富值为b[i],
如果两个朋友同时参加宴会,这两个朋友之间的隔阂是其财富值差值的绝对值,
宴会的隔阂值,是财富差距最大的两人产生的财富值差值的绝对值,
宴会的愉悦值,是所有参加宴会朋友的愉悦值总和。
小红可以邀请任何人,
希望宴会的愉悦值不能小于k的情况下, 宴会的隔阂值能最小是多少?
如果做不到,返回-1。
1 <= n <= 2 * 10^5,
1 <= 愉悦值、财富值 <= 10^9,
1 <= k <= 10^14。
来自蚂蚁金服。
答案2023-04-08:
方法一:暴力枚举
思路:
对于每一个可能的区间,计算区间中 bb 数组元素的最大值和最小值,然后计算跨度并统计愉悦值。记录跨度最小的区间的元素和与跨度,最后返回跨度最小的值。
步骤:
1.使用递归函数枚举所有可能的区间,函数参数包括数组 a、数组 b、当前递归到的位置 i、剩余需要选择的元素个数 restr,以及已经选过的区间中的最小值 min 和最大值 max。
2.当需要选择的元素个数 rest 小于等于 0 时,返回跨度最小的区间对应数组 b 的元素的最大值和最小值之差;
3.当递归到数组 a 的末尾时,返回一个足够大的数(这里使用了 Rust 中整型类型 i32 的最大值)表示无法选出符合要求的区间;
4.否则,分别计算选择当前位置的元素和不选择当前位置的元素两种情况下所能得到的跨度最小的区间,然后取两者的最小值作为函数的返回值。
时间复杂度:O(2^n),其中 n 是数组长度。
空间复杂度:O(n)。
方法二:二分答案
思路:
对于每一个可能的区间跨度 x,我们可以判断是否有一个区间的元素和最接近 k 且其跨度不大于 x。具体实现时,先将数组 b 按照元素大小排序,然后利用二分查找的思想,在排序后的数组上二分答案。
步骤:
1.将数组 b 按照元素大小排序,并记录 b 数组的最小值和最大值;
2.使用二分答案法,在区间 [0,max−min] 上进行二分,其中 max 和 min 分别为 b 数组中的最大值和最小值;
3.对于每一个二分得到的可能的跨度 x,计算在跨度不大于 x 的情况下,宴会的愉悦值能否大于等于 k。具体实现时,使用双指针法维护当前区间的左右端点,计算当前区间内 a 数组元素的和并记录其最大值;
4.如果在跨度不大于 x 的情况下宴会的愉悦值大于等于 k,则更新答案,并将区间左端点右移;
5.否则,将区间右端点右移。
时间复杂度:O(nlognlogV),其中 n 是数组长度,V 是数组元素的最大值。
空间复杂度:O(n)。
方法三:滑动窗口
思路:
我们可以使用双指针法在 b 数组上维护一个区间,使得该区间的财富值差距不大于当前尝试的跨度,并计算在该区间中元素值和能否大于等于 k。具体实现时,先将数组 b 按照元素大小排序,然后使用两个指针 l 和 r 维护当前区间,用变量 happy 记录当前区间内元素值之和,每次将指针向右移动时对 happy 进行更新,直到找到一个满足愉悦值大于等于 k 的区间。
步骤:
1.将数组 b 按照元素大小排序;
2.使用双指针法,在数组 b 上维护一个区间,使得该区间的财富值差距不大于当前尝试的跨度,并计算在该区间中元素值和能否大于等于 k。具体实现时,使用两个指针 l 和 rr 维护当前区间,用变量 happy 记录当前区间内元素值之和。每次将指针向右移动时对 happy 进行更新,并在 happy≥k 的情况下更新答案;
3.如果找到了一个满足愉悦值大于等于 k 的区间,则返回该区间的跨度;否则返回 −1。
时间复杂度:O(nlogn),其中 n 是数组长度。
空间复杂度:O(n)。
三种方法分析
从时间复杂度和空间复杂度两个方面来看,方法二和方法三都比方法一要好得多。在实际应用中,我们应该优先选择方法二或方法三。
rust完整代码如下:
fn less_gap1(a: &Vec<i32>, b: &Vec<i32>, k: i32) -> i32 {
let ans = process(a, b, 0, k, std::i32::MAX, std::i32::MIN);
return if ans < std::i32::MAX as i64 {
ans as i32
} else {
-1
};
}
fn process(a: &Vec<i32>, b: &Vec<i32>, i: usize, rest: i32, min: i32, max: i32) -> i64 {
if rest <= 0 {
(max - min).abs() as i64
} else if i == a.len() {
std::i32::MAX as i64
} else {
let p1 = process(a, b, i + 1, rest, min, max);
let p2 = process(a, b, i + 1, rest - a[i], min.min(b[i]), max.max(b[i]));
p1.min(p2)
}
}
fn less_gap2(a: &Vec<i32>, b: &Vec<i32>, k: i64) -> i32 {
let n = a.len();
let mut f = vec![vec![0; 2]; n];
let mut min = b[0];
let mut max = b[0];
for i in 0..n {
f[i][0] = a[i];
f[i][1] = b[i];
min = min.min(b[i]);
max = max.max(b[i]);
}
f.sort_by_key(|x| x[1]);
let (mut l, mut r) = (0, max - min);
let mut ans = -1;
while l <= r {
let m = (l + r) / 2;
if max_happy(&f, m) >= k {
ans = m;
r = m - 1;
} else {
l = m + 1;
}
}
return ans;
}
fn max_happy(f: &Vec<Vec<i32>>, limit: i32) -> i64 {
let n = f.len();
let mut sum = 0;
let mut ans = 0;
let mut r = 0;
for l in 0..n {
while r < n && f[r][1] - f[l][1] <= limit {
sum += f[r][0];
r += 1;
}
ans = ans.max(sum);
sum -= f[l][0];
r = r.max(l + 1);
}
return ans as i64;
}
fn less_gap3(a: &Vec<i32>, b: &Vec<i32>, k: i64) -> i32 {
let n = a.len();
let mut f = vec![vec![0; 2]; n];
for i in 0..n {
f[i][0] = a[i];
f[i][1] = b[i];
}
f.sort_by_key(|x| x[1]);
let (mut ans, mut happy) = (std::i32::MAX, 0_i64);
let (mut l, mut r) = (0, 0);
while l < n {
while r < n && happy < k {
happy += f[r][0] as i64;
r += 1;
}
if happy >= k {
ans = ans.min(f[r - 1][1] - f[l][1]);
}
happy -= f[l][0] as i64;
l += 1;
}
return if ans == std::i32::MAX { -1 } else { ans };
}
fn random_array(n: usize, v: i32) -> Vec<i32> {
let mut arr = vec![0; n];
for i in 0..n {
arr[i] = (rand::random::<f64>() * v as f64 + 1.0) as i32;
}
return arr;
}
fn main() {
const N: usize = 15;
const V: i32 = 20;
const TEST_TIME: i32 = 5000;
println!("功能测试开始");
for _ in 0..TEST_TIME {
let n = rand::random::<usize>() % N + 1;
let a = random_array(n, V);
let b = random_array(n, V);
let k = rand::random::<usize>() % (n * V as usize) + 1;
let ans1 = less_gap1(&a, &b, k as i32);
let ans2 = less_gap2(&a, &b, k as i64);
let ans3 = less_gap3(&a, &b, k as i64);
if ans1 != ans2 || ans1 != ans3 {
println!("出错了!");
println!("a = {:?}", a);
println!("b = {:?}", b);
println!("k = {}", k);
println!("ans1 = {}", ans1);
println!("ans2 = {}", ans2);
println!("ans3 = {}", ans3);
return;
}
}
println!("功能测试结束");
}
2023-04-08:社交网络中的最优邀请策略探究。本文以小红准备开宴会为例,提出一种基于贪心算法和二分查找的解决方案,帮助读者在保证愉悦值不低于k的前提下,最小化宴会的阶层差距。的更多相关文章
- bootstrap中container 类和container-fluid类的区别container类所谓的自适应也是通过margin的改变来完成,container-fluid类的百分百宽度是指在固有的15px的padding前提下宽度总是当前视口的宽度。
container 类和container-fluid类的区别体现在是否有随视口宽度改变的margin存在. container类所谓的自适应也是通过margin的改变来完成,container-fl ...
- 腾讯优图&港科大提出一种基于深度学习的非光流 HDR 成像方法
目前最好的高动态范围(HDR)成像方法通常是先利用光流将输入图像对齐,随后再合成 HDR 图像.然而由于输入图像存在遮挡和较大运动,这种方法生成的图像仍然有很多缺陷.最近,腾讯优图和香港科技大学的研究 ...
- C语言实现 二分查找数组中的Key值(递归和非递归)
基本问题:使用二分查找的方式,对数组内的值进行匹配,如果成功,返回其下标,否则返回 -1.请使用递归和非递归两种方法说明. 非递归代码如下: #include <stdio.h> int ...
- 不修改模板的前提下修改VisualState中的某些值
原文链接:不修改模板的前提下修改VisualState中的某些值 - 超威蓝火 UWP里有一件非常令人不爽的事,大部分控件只提供了Normal状态下的Background,Foreground,Bor ...
- 删除链表中全部值为k的节点
1. 问题描写叙述 给定一个单链表,删除当中值为k的全部节点.比如:1→2→6→3→4→5→61 \to 2 \to 6 \to 3 \to 4 \to 5 \to 6,删除当中值为6的节点,返回:1 ...
- LeetCode 周赛 342(2023/04/23)容斥原理、计数排序、滑动窗口、子数组 GCB
本文已收录到 AndroidFamily,技术和职场问题,请关注公众号 [彭旭锐] 提问. 大家好,我是小彭. 前天刚举办 2023 年力扣杯个人 SOLO 赛,昨天周赛就出了一场 Easy - Ea ...
- hdu6003 Problem Buyer 贪心 给定n个区间,以及m个数,求从n个区间中任意选k个区间,满足m个数都能在k个区间中找到一个包含它的区间,如果一个区间包含了x,那么 该区间不能再去包含另一个数,即k>=m。求最小的k。如果不存在这样的k,输出“IMPOSSIBLE!”。
/** 题目:hdu6003 Problem Buyer 链接:http://acm.hdu.edu.cn/showproblem.php?pid=6003 题意:给定n个区间,以及m个数,求从n个区 ...
- How Javascript works (Javascript工作原理) (二) 引擎,运行时,如何在 V8 引擎中书写最优代码的 5 条小技巧
个人总结: 一个Javascript引擎由一个标准解释程序,或者即时编译器来实现. 解释器(Interpreter): 解释一行,执行一行. 编译器(Compiler): 全部编译成机器码,统一执行. ...
- 从算法入手讲解如何在SQL Server中实现最优最简
算法是计算机科学中一个重要的研究方向,是解决复杂问题的关键.在计算机世界中,算法无处不在.数据库是存储数据和执行大批量计算的场所,在数据库中使用一些简单的SQL命令,进行存储.查询.统计.以解决现实世 ...
- POJ_3685_Matrix_(二分,查找第k大的值)
描述 http://poj.org/problem?id=3685 一个n*n的矩阵,(i,j)的值为i*i+100000*i+j*j-100000*j+i*j,求第m小的值. Matrix Time ...
随机推荐
- OSPF RFC 1583 兼容
- HAL层分析
1. 安卓HAL模块基本 2. 定义hal层代码的5个特性 1)硬件抽象层具有与硬件的密切相关性. 2) 硬件抽象层具有与操作系统无关性. 3) 接口定义的功能应该包含硬件或者系统所需硬件支持的所有功 ...
- 关于python print函数format 格式化
关于python print函数format 格式化 Your Guide to the Python print() Function https://realpython.com/python- ...
- DRF的序列化器Serializer
一 序列化器的作用 1. 序列化,序列化器会把模型对象转换成字典,经过视图中response对象以后变成json字符串 2. 反序列化,视图中request会把客户端发送过来的数据转换成字典,序列化器 ...
- 开学考--MIS系统(javaweb的开学练习--网络新闻发布系统)
关于本次考试的相关理解 看到题目的时候,第一反应是这道题不难,之前已经做过十分类似的题目了,然后对于难度是很有自信的(当然,对于用户的权限管理部分,还是很懵): 而第二反应就是,题量挺大的,我在这有限 ...
- FWT/快速沃尔什变换 入门指南
来学点好玩的. 引入 我们也许学过,\(FFT\) 可以解决一类卷积: \[C_i=\sum^{k+j=i} A_iB_j \] 现在我们稍微变一下式子: \[C_i=\sum^{i=k \And j ...
- Java面试——MyBatis
一.MyBatis 与 JDBC 的区别 [1]JDBC 是 Java 提供操作数据库的 API:MyBatis 是一个持久层 ORM 框架,底层是对 JDBC 的封装.[2]使用 JDBC 需要连接 ...
- 迁移学习(NRC)《Exploiting the Intrinsic Neighborhood Structure for Source-free Domain Adaptation》
论文信息 论文标题:Exploiting the Intrinsic Neighborhood Structure for Source-free Domain Adaptation论文作者:Shiq ...
- 来自jackson的灵魂一击:@ControllerAdvice就能保证万无一失吗?
前几天写了篇关于fastjson的文章,<fastjson很好,但不适合我>.里面探讨到关于对象循环引用的序列化问题.作为spring序列化的最大竞品,在讨论fastjson的时候肯定要对 ...
- 刷爆 LeetCode 周赛 339,贪心 / 排序 / 拓扑排序 / 平衡二叉树
本文已收录到 AndroidFamily,技术和职场问题,请关注公众号 [彭旭锐] 提问. 大家好,我是小彭. 上周末是 LeetCode 第 339 场周赛,你参加了吗?这场周赛覆盖的知识点比较少, ...