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的前提下,最小化宴会的阶层差距。的更多相关文章

  1. bootstrap中container 类和container-fluid类的区别container类所谓的自适应也是通过margin的改变来完成,container-fluid类的百分百宽度是指在固有的15px的padding前提下宽度总是当前视口的宽度。

    container 类和container-fluid类的区别体现在是否有随视口宽度改变的margin存在. container类所谓的自适应也是通过margin的改变来完成,container-fl ...

  2. 腾讯优图&港科大提出一种基于深度学习的非光流 HDR 成像方法

    目前最好的高动态范围(HDR)成像方法通常是先利用光流将输入图像对齐,随后再合成 HDR 图像.然而由于输入图像存在遮挡和较大运动,这种方法生成的图像仍然有很多缺陷.最近,腾讯优图和香港科技大学的研究 ...

  3. C语言实现 二分查找数组中的Key值(递归和非递归)

    基本问题:使用二分查找的方式,对数组内的值进行匹配,如果成功,返回其下标,否则返回 -1.请使用递归和非递归两种方法说明. 非递归代码如下: #include <stdio.h> int ...

  4. 不修改模板的前提下修改VisualState中的某些值

    原文链接:不修改模板的前提下修改VisualState中的某些值 - 超威蓝火 UWP里有一件非常令人不爽的事,大部分控件只提供了Normal状态下的Background,Foreground,Bor ...

  5. 删除链表中全部值为k的节点

    1. 问题描写叙述 给定一个单链表,删除当中值为k的全部节点.比如:1→2→6→3→4→5→61 \to 2 \to 6 \to 3 \to 4 \to 5 \to 6,删除当中值为6的节点,返回:1 ...

  6. LeetCode 周赛 342(2023/04/23)容斥原理、计数排序、滑动窗口、子数组 GCB

    本文已收录到 AndroidFamily,技术和职场问题,请关注公众号 [彭旭锐] 提问. 大家好,我是小彭. 前天刚举办 2023 年力扣杯个人 SOLO 赛,昨天周赛就出了一场 Easy - Ea ...

  7. 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个区 ...

  8. How Javascript works (Javascript工作原理) (二) 引擎,运行时,如何在 V8 引擎中书写最优代码的 5 条小技巧

    个人总结: 一个Javascript引擎由一个标准解释程序,或者即时编译器来实现. 解释器(Interpreter): 解释一行,执行一行. 编译器(Compiler): 全部编译成机器码,统一执行. ...

  9. 从算法入手讲解如何在SQL Server中实现最优最简

    算法是计算机科学中一个重要的研究方向,是解决复杂问题的关键.在计算机世界中,算法无处不在.数据库是存储数据和执行大批量计算的场所,在数据库中使用一些简单的SQL命令,进行存储.查询.统计.以解决现实世 ...

  10. 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 ...

随机推荐

  1. 【StoneDB 模块介绍】服务器模块

    [StoneDB 模块介绍]服务器模块 一.介绍 客户端程序和服务器程序本质上都是计算机上的一个进程,客户端进程向服务器进程发送请求的过程本质上是一种进程间通信的过程,StoneDB 数据库服务程序作 ...

  2. 文件上传靶场 upload-labs搭建 Pass 1-4

    upload-labs是一个练习文件上传的靶场 我们需要先安装中间件和PHP,推荐使用小皮面板,如何安装使用见sqli-labs搭建前部分 upload-labs下载:https://gitcode. ...

  3. 痞子衡嵌入式:在i.MXRT1060-EVK上利用memtester程序给SDRAM做压力测试

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是在i.MXRT1060-EVK上利用memtester程序给SDRAM做压力测试. 我们知道恩智浦i.MXRT1xxx系列是高性能MCU ...

  4. 声网Agora Lipsync 技术揭秘:通过实时语音驱动人像模拟真人说话

    元宇宙的火热让人们对未来虚拟世界的形态充满了幻想,此前我们为大家揭秘了声网自研的 3D 空间音频技术如何在虚拟世界中完美模拟现实听觉体验,增加玩家沉浸感.今天我们暂时离开元宇宙,回到现实世界,来聊聊声 ...

  5. DevOps|研发效能不是老板工程,是开发者服务

    有人说研发效能是老板工程.不是的,研发效能不是老板工程,它不直接服务于老板(虽然老板可能看一些报表),反而是服务于广大产研运(产品+研发+质量+运维)的同学,所以有的公司也把研发效能叫做基础中台,平台 ...

  6. 【读书笔记】组合计数中的行列式方法 专题3 完美匹配: the Pfaffian method

    目录 专题3-Perfect matchings: the Pfaffian method 一些定义 用2×1的砖密铺a×b的大矩形的方法数 专题3-Perfect matchings: the Pfa ...

  7. 大数据面试——Flink

    一.公司怎么提交的实时任务,有多少 Job Manager.TaskManager 是多少 我们使用 yarn session 模式提交任务:另一种方式是每次提交都会创建一个新的 Flink集群,为每 ...

  8. RabbitMQ 消息中间件总结

    RabbitMQ 是实现高级消息队列协议(AMQP:Advanced Message Queue Protocol)的开源代理软件,也称为面向消息的中间件.支持多种操作系统.多种编程语言.Rabbit ...

  9. Hyper-V由于虚拟机监控程序未运行

    以管理员权限打开命令提示符 输入bcdedit /set hypervisorlaunchtype Auto 重启计算机

  10. 【深入浅出 Yarn 架构与实现】6-1 NodeManager 功能概述

    本节开始将对 Yarn 中的 NodeManager 服务进行剖析. NodeManager 需要在每个计算节点上运行,与 ResourceManager 和 ApplicationMaster 进行 ...