L2-017 人以群分 Java题解

2023-10-20 12:59
文章标签 java 题解 l2 017 人以群分

本文主要是介绍L2-017 人以群分 Java题解,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!


原题:

社交网络中我们给每个人定义了一个“活跃度”,现希望根据这个指标把人群分为两大类,即外向型(outgoing,即活跃度高的)和内向型(introverted,即活跃度低的)。要求两类人群的规模尽可能接近,而他们的总活跃度差距尽可能拉开。

输入格式:

输入第一行给出一个正整数N(2≤N≤105)。随后一行给出N个正整数,分别是每个人的活跃度,其间以空格分隔。题目保证这些数字以及它们的和都不会超过231。

输出格式:

按下列格式输出:

Outgoing #: N1
Introverted #: N2
Diff = N3

其中N1是外向型人的个数;N2是内向型人的个数;N3是两群人总活跃度之差的绝对值。

输入样例1:

10
23 8 10 99 46 2333 46 1 666 555

输出样例1:

Outgoing #: 5
Introverted #: 5
Diff = 3611

输入样例2:

13
110 79 218 69 3721 100 29 135 2 6 13 5188 85

输出样例2:

Outgoing #: 7
Introverted #: 6
Diff = 9359

代码长度限制:16 KB        时间限制:150 ms        内存限制:64 MB

题目详情 - L2-017 人以群分 (pintia.cn)https://pintia.cn/problem-sets/994805046380707840/problems/994805061056577536


题解:

只需通过对数组进行排序,得到一个递增的数组,此时数组的前一半每个元素都小于该数组的后一半,不难发现,此时两边的差异达到最大。

通过C++代码运行较为容易,耗时短,内存占用少,但由于最近学习Java,所以尝试通过Java解答本题。C++代码对照在Java代码下方。

在初次运行时,使用Scanner输入流,导致测试样例全部超时,于是尝试用BufferedReader字符流输入,减少了50ms以上的耗时,但仍然有两个测试样例没能通过。

虽然超时,但是占用空间仍然没有达到系统限制,因此我尝试使用相较于Java提供的的sort(Dual-Pivot快排)以及parallelSort排序(并行排序-合并排序)而言(时间复杂度均为O(nlogn)),时间复杂度更低的桶排序(时间复杂度为O(n+m)),但就结果而言,由于Java语言特性,难以使用Java语言通过全部测试用例,使用桶排序会造成内存超出64MB的限制,因此最终还是使用Collections下的sort排序。


Java代码如下:

使用Collections下的sort方法,由于超时,代码未能通过全部测试点:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Collections;public class Main {private final int Num;        //人数private final ArrayList<Integer> People = new ArrayList<>();   //存放每个人的性格private int count;      //性格总计public Main() throws IOException {BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));Num = Integer.parseInt(reader.readLine());String[] ss = reader.readLine().split(" ");for (int i = 0; i < Num; i++) {People.add(Integer.parseInt(ss[i]));count += People.get(i);}Collections.sort(People);}public static void main(String[] args) throws IOException {Main main = new Main();for (int i = 0; i < main.Num / 2; i++)main.count -= 2 * main.People.get(i);System.out.println("Outgoing #: " + (main.Num / 2 + main.Num % 2));System.out.println("Introverted #: " + main.Num / 2);System.out.println("Diff = " + main.count);}
}


C++代码如下:

可以看出,C++代码在运行时,占用内存更小,耗时更短。

#include <iostream>
#include <algorithm>
using namespace std;
int main()
{int num;int diff;cin >> num;int people[num];for (int i = 0; i < num; i++){cin >> people[i];diff += people[i];}sort(people, people + num);for (int i = 0; i < num / 2; i++)diff -= 2 * people[i];cout << "Outgoing #: " << (num + 1) / 2 << endl;cout << "Introverted #: " << num / 2 << endl;cout << "Diff = " << diff << endl;system("pause");return 0;
}


使用桶排序的Java代码:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Collections;public class Main {private int Num;        //人数private ArrayList<Integer> People = new ArrayList<>();   //存放每个人的性格private int count;      //性格总计private int Max;    //数组最大值private int Min;    //数组最小值public Main() throws IOException {BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));Max = Integer.MIN_VALUE;Min = Integer.MAX_VALUE;count = 0;Num = Integer.parseInt(reader.readLine());String[] s = reader.readLine().split(" ");for (int i = 0; i < Num; i++) {People.add(Integer.parseInt(s[i]));Max = Math.max(Max, (Integer) People.get(i));Min = Math.min(Min, (Integer) People.get(i));count += (int) People.get(i);}
//        Collections.sort(People);}public static void main(String[] args) throws IOException {Main split = new Main();split.BucketSort();for (int i = 0; i < split.Num / 2; i++)split.count -= 2 * split.People.get(i);System.out.println("Outgoing #: " + (split.Num / 2 + split.Num % 2));System.out.println("Introverted #: " + split.Num / 2);System.out.println("Diff = " + split.count);}public void BucketSort() {
//       桶数int bucketNum = (Max - Min) / Num + 1;ArrayList<ArrayList<Integer>> bucketArr = new ArrayList<>(bucketNum);for (int i = 0; i < bucketNum; i++) {bucketArr.add(new ArrayList<>());}
//        置入桶中for (int i = 0; i < Num; i++) {int num = (People.get(i) - Min) / (Num);bucketArr.get(num).add(People.get(i));}
//        桶排序for (ArrayList<Integer> integers : bucketArr) {Collections.sort(integers);}
//        返回People.clear();for (ArrayList<Integer> integers : bucketArr) {People.addAll(integers);}}
}

分析:

Java程序编译后产生.class文件运行在JVM上,占用相当大的时间以及内存,在Windows上这种感知尤为明显。

关于桶排序:

详解:https://www.cnblogs.com/bigsaltfish/p/10067011.html

N:待排序长度         M:桶的数量

时间复杂度:O ( N + N * ( logN-logM ) )

空间复杂度:O ( N + M )

桶排序是一种牺牲空间换取时间的排序算法,当分配的桶的数量达到N时,时间复杂度最好,为O ( N  ),但空间复杂度上升,如果N较大,则会占用非常大的内存空间,如上方使用桶排序的Java代码,占用内存超出限制。

这篇关于L2-017 人以群分 Java题解的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/247256

相关文章

SpringBoot全局域名替换的实现

《SpringBoot全局域名替换的实现》本文主要介绍了SpringBoot全局域名替换的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一... 目录 项目结构⚙️ 配置文件application.yml️ 配置类AppProperties.Ja

Java使用Javassist动态生成HelloWorld类

《Java使用Javassist动态生成HelloWorld类》Javassist是一个非常强大的字节码操作和定义库,它允许开发者在运行时创建新的类或者修改现有的类,本文将简单介绍如何使用Javass... 目录1. Javassist简介2. 环境准备3. 动态生成HelloWorld类3.1 创建CtC

JavaScript中的高级调试方法全攻略指南

《JavaScript中的高级调试方法全攻略指南》什么是高级JavaScript调试技巧,它比console.log有何优势,如何使用断点调试定位问题,通过本文,我们将深入解答这些问题,带您从理论到实... 目录观点与案例结合观点1观点2观点3观点4观点5高级调试技巧详解实战案例断点调试:定位变量错误性能分

Java实现将HTML文件与字符串转换为图片

《Java实现将HTML文件与字符串转换为图片》在Java开发中,我们经常会遇到将HTML内容转换为图片的需求,本文小编就来和大家详细讲讲如何使用FreeSpire.DocforJava库来实现这一功... 目录前言核心实现:html 转图片完整代码场景 1:转换本地 HTML 文件为图片场景 2:转换 H

Java使用jar命令配置服务器端口的完整指南

《Java使用jar命令配置服务器端口的完整指南》本文将详细介绍如何使用java-jar命令启动应用,并重点讲解如何配置服务器端口,同时提供一个实用的Web工具来简化这一过程,希望对大家有所帮助... 目录1. Java Jar文件简介1.1 什么是Jar文件1.2 创建可执行Jar文件2. 使用java

SpringBoot实现不同接口指定上传文件大小的具体步骤

《SpringBoot实现不同接口指定上传文件大小的具体步骤》:本文主要介绍在SpringBoot中通过自定义注解、AOP拦截和配置文件实现不同接口上传文件大小限制的方法,强调需设置全局阈值远大于... 目录一  springboot实现不同接口指定文件大小1.1 思路说明1.2 工程启动说明二 具体实施2

Java实现在Word文档中添加文本水印和图片水印的操作指南

《Java实现在Word文档中添加文本水印和图片水印的操作指南》在当今数字时代,文档的自动化处理与安全防护变得尤为重要,无论是为了保护版权、推广品牌,还是为了在文档中加入特定的标识,为Word文档添加... 目录引言Spire.Doc for Java:高效Word文档处理的利器代码实战:使用Java为Wo

SpringBoot日志级别与日志分组详解

《SpringBoot日志级别与日志分组详解》文章介绍了日志级别(ALL至OFF)及其作用,说明SpringBoot默认日志级别为INFO,可通过application.properties调整全局或... 目录日志级别1、级别内容2、调整日志级别调整默认日志级别调整指定类的日志级别项目开发过程中,利用日志

Java中的抽象类与abstract 关键字使用详解

《Java中的抽象类与abstract关键字使用详解》:本文主要介绍Java中的抽象类与abstract关键字使用详解,本文通过实例代码给大家介绍的非常详细,感兴趣的朋友跟随小编一起看看吧... 目录一、抽象类的概念二、使用 abstract2.1 修饰类 => 抽象类2.2 修饰方法 => 抽象方法,没有

SpringBoot 多环境开发实战(从配置、管理与控制)

《SpringBoot多环境开发实战(从配置、管理与控制)》本文详解SpringBoot多环境配置,涵盖单文件YAML、多文件模式、MavenProfile分组及激活策略,通过优先级控制灵活切换环境... 目录一、多环境开发基础(单文件 YAML 版)(一)配置原理与优势(二)实操示例二、多环境开发多文件版