当前位置: 首页 > news >正文

左神算法之双集合平均值优化操作的最大次数

目录

  • 1. 题目
  • 2. 解释
  • 3. 思路
  • 4. 代码
  • 5. 总结

1. 题目

给定两个整数集合 ab,定义 magic操作 为:

  • 从其中一个集合取出一个元素,放入另一个集合。
  • 操作后,两个集合的平均值都必须严格大于操作前的平均值

限制条件:

  1. 不能将任一集合取空(否则无法计算平均值)。
  2. 如果被移动的元素 x 在目标集合中已存在,则目标集合的平均值不变(因为集合元素不重复),但源集合的平均值可能改变(因为 x 被移除)。

问题: 最多可以进行多少次这样的 magic 操作?


2. 解释

  • Magic操作的条件:

    • 设从集合 A 移动元素 x 到集合 B,则必须满足:
      • A 的新平均值 > A 的旧平均值。
      • B 的新平均值 > B 的旧平均值。
    • 由于集合元素不重复,如果 x 已在 B 中存在,则 B 的平均值不变(因为 B 的元素不变),此时只需 A 的新平均值 > A 的旧平均值。
  • 关键观察:

    • 如果 avg(A) == avg(B),无法进行任何 magic 操作(因为移动后至少一个集合的平均值会减小)。
    • 如果 avg(A) > avg(B),只能从 A 移动 严格小于 avg(A) 且严格大于 avg(B) 的元素到 B,且 B 中不能已有该元素。

3. 思路

  1. 计算初始平均值:

    • 计算 avgA = sum(A) / |A|avgB = sum(B) / |B|
    • 如果 avgA == avgB,直接返回 0(无法操作)。
  2. 确定移动方向:

    • 假设 avgA > avgB,则只能从 A 移动元素到 B
    • 移动的元素 x 必须满足:
      • avgB < x < avgA(保证移动后 AB 的平均值都增大)。
      • x 不在 B 中(否则 B 的平均值不变,无法满足 B 的新平均值 > 旧平均值)。
  3. 贪心策略:

    • A 排序,从小到大检查可以移动的元素。
    • 每次移动后,更新 sumAsumB|A||B|avgAavgB
    • 重复直到无法移动为止。

4. 代码

public class Problem02_Magic0p {// 保证arr1和arr2均没有重复值哦,且一定有数字public static int maxOps(int[] arr1, int[] arr2) {double sum1 = 0;for (int i = 0; i < arr1.length; i++) {sum1 += (double) arr1[i];}double sum2 = 0;for (int i = 0; i < arr2.length; i++) {sum2 += (double) arr2[i];}if(avg(sum1, arr1.length) == avg(sum2, arr2.length)){return 0;}// 平均值不一样int[] arrMore = null;int[] arrLess = null;double sumMore = 0;double sumLess = 0;if(avg(sum1, arr1.length) > avg(sum2, arr2.length)){arrMore = arr1;sumMore = sum1;arrLess = arr2;sumLess = sum2;}else{arrMore = arr2;sumMore = sum2;arrLess = arr1;sumLess = sum1;}Arrays.sort(arrMore);HashSet<Integer> setLess = new HashSet<>();for(int num : arrLess){setLess.add(num);}int moreSize = arrMore.length;  // 平均值大的集合还剩几个数int lessSize = arrLess.length;  // 平均值小的集合还剩几个数int ops = 0;    // 移动次数for(int i = 0; i < arrMore.length; i++){double cur = (double) arrMore[i];if(cur < avg(sumMore, moreSize) && cur > avg(sumLess, lessSize) && !setLess.contains(arrMore[i])){sumMore -= cur;moreSize--;sumLess += cur;lessSize++;setLess.add(arrMore[i]);ops++;}}return ops;}public static double avg(double sum, int length){return sum / length;}public static int sum(int[] arr){int sum = 0;for(int i = 0; i < arr.length; i++){sum += arr[i];}return sum;}public static void main(String[] args) {int[] arr1 = {1, 2, 3};System.out.println(avg(sum(arr1), arr1.length));int[] arr2 = {4, 5, 6};System.out.println(avg(sum(arr2), arr2.length));System.out.println(maxOps(arr1, arr2));}
}

输出结果:

2.0
5.0
2

5. 总结

  • 核心逻辑:
    • 确保 avg(A) > avg(B),然后从 A 移动满足 avg(B) < x < avg(A) 且不在 B 中的元素。
    • 每次移动后更新 sumavg,继续检查能否移动更多元素。
  • 时间复杂度:
    • 排序 A 的时间为 O(n log n),遍历 A 的时间为 O(n),总体 O(n log n)
  • 适用场景:
    • 适用于两个集合平均值不相等且存在可移动元素的情况。
    • 如果 avg(A) == avg(B) 或没有满足条件的 x,则无法操作。

相关文章:

  • 网站开发 jsp开发工具互联网营销推广怎么做
  • 杭州h5建站ps培训
  • 用.net做网站中含有论坛百度网站权重查询
  • 广西网站建设原创云推广
  • 400网站建设办公石家庄seo管理
  • 建筑证书兼职网站排名前50名免费的网站
  • 【Linux】高级IO
  • MySQL:深入总结锁机制
  • 机器学习×第十四卷:集成学习中篇——她从每次错误中修正自己
  • Java实现简易即时通讯系统
  • Linux离线搭建Jenkins
  • C++【生存游戏】开发:荒岛往事 第一期
  • GLib库介绍与linux下应用
  • 基于元学习的回归预测模型如何设计?
  • ubuntu20.04安装多版本python时,如何使用sudo python3.10
  • Linux系统---Nginx配置nginx状态统计
  • 如何使用MQTTX软件来进行MQTT协议的测试
  • Harmony状态管理 @Local和@Param
  • 计算机网络期末复习
  • Git 3天2K星标: Happy-LLM 项目介绍(附教程)
  • 【基础篇-消息队列】—— 如何实现单个队列的并行消费及如何保证消息的严格顺序
  • LangChain网页自动化PlayWrightBrowserToolkit
  • 在Ubuntu下建设自己的本地大模型docker+ollama+openwenui
  • leetcode173.二叉搜索树迭代器
  • 深入理解 BOM:浏览器对象模型详解
  • RabbitMQ是什么?以及优缺点