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 ...
随机推荐
- Java--接口和抽象类有什么区别
他们都不能实例化对象,都可以包含抽象方法,而且抽象方法必须被继承的类全部实现. 区别: 1.抽象类和接口都不能直接实例化,如果要实例化,抽象类变量必须指向实现所有抽象方法的子类对象,接口变量必须指向实 ...
- rosetta Resfile语法和约束
介绍 参考:https://www.rosettacommons.org/docs/latest/rosetta_basics/file_types/resfiles resfile包含输入到Pack ...
- Google colab复现openpose+st-gcn的心路历程
Google colab复现openpose+st-gcn的心路历程: 因为本人的大致研究方向为动作识别,加上自己的笔记本比较菜鸡,没有牛皮的显卡,所以采用了google的colab.在网上查了三天, ...
- 看了还不懂b+tree的本质就来打我
看了还不懂b+tree的本质就来打我 大家好,我是蓝胖子. 今天我们来看看b+tree这种数据结构,我们知道数据库的索引就是由b+tree实现,那么这种结构究竟为什么适合磁盘呢,它又有哪些缺点呢? 我 ...
- Redis使用ZSET实现消息队列使用总结一
转载请注明出处: 目录 1.zset为什么可以做消息队列 2.zset实现消息队列的步骤 3.使用jedis实现消息队列示例 4.+inf与-inf 5.redis使用list与zset做消息队列有什 ...
- ctfshow VIP限免题目(最新)
源码泄露 这一题主要考察如何查看网页源代码,查看方式主要有三种 在网页前面加上view-source: 右键页面,点击查看页面源代码 键盘上按下F12打开开发者工具,在查看器中查看源代码 这一题随便一 ...
- 在Vue中发起axios请求成功,却被catch捕捉返回Network Error
前端发起请求成功,后台接收处理返回,却被axios的catch捕获,没有走then函数. 最后添加了headers配置成功解决,如上,附上axios接口配置中文文档:axios中文文档|axios中文 ...
- 5.Web信息收集
Web信息收集 目录 Web信息收集 1.whois查询 2.服务器操作系统的识别 3.服务器加固 4.服务版本识别 5.常见组合: 6.指纹识别 7.敏感路径识别 8.历史漏洞信息收集 1.whoi ...
- DOM选择器之元素节点选择器
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- jq-ajax-get
get有三个参数,第一个时候url,第二个是数据,第三个是回调函数(可以用返回值表示,如下所示) 执行正确时,返回的依次是res,type,xhr. 执行错误连接不上的的依次是xhr,type,res ...