为了更好的阅读体检,可以查看我的算法学习博客
在线评测链接:P1300

题目描述

塔子哥最近对在开发一个简单的操作系统,今天他的任务是为操作系统的动态内存管理模块实现内存块的合并功能。

介绍一下操作系统的内存管理模块:操作系统的动态内存管理模块是操作系统中非常重要的一部分,其主要功能是在程序运行时动态地分配和释放内存。动态内存管理模块根据程序的内存需求,调用物理内存管理模块,对内存进行分配或者释放。为了使得内存的分配更加高效,动态内存管理模块通常会实现内存池的机制。内存池就是一个预先分配好一定数量的内存块的集合,程序运行时可以从内存池中获取内存块,而不必动态地去分配内存空间。这样可以极大地提高内存分配的速度。动态内存管理模块还负责内存的回收和整理。当程序不再使用某些内存空间时,动态内存管理模块将这些空间标记为可回收空间,并把它们加入内存释放队列。在适当的时候,动态内存管理模块就会回收这些空间,并重新整理内存空间,以便留出更大的连续内存块来给后续的内存分配操作使用。”

塔子哥考虑这个模块可以根据用户需求分配任意大小的内存块,并在用户释放内存时将其回收到内存池中以供其他用户使用,他把这个任务安排给了小G同学。小G同学需要设计并实现这个回收合并模块,这个模块在每次释放内存块后返回当前最大的连续内存块的起始位置和长度。如果存在多个最大连续内存块,返回起始位置最小的内存块。

输入描述

输入是一组释放的内存块编号,用逗号分隔。例如,输入 “ 1 , 3 , 2 , 51,3,2,51,3,2,5” 表示释放了四个内存块,它们的编号分别为 1 、 3 、 21、3、2132 555。每个内存块的大小为 111 个单位。请注意,函数执行前所有内存块都已被申请完毕,没有空闲内存块。不需要考虑重复释放内存块。

内存块编号: 000 ≤\leq 编号 ≤\leq 231− 12^{31} – 12311

单词释放的内存块个数 ≤\leq 100001000010000

输出描述

输出是一个由两个整数组成的元组,表示经过回收处理后当前可用的最大连续内存块的起始编号和长度。例如,输出 “ 1 , 31,31,3” 表示合并后的连续内存块的起始编号是 111,长度为 333。如果存在多个最大连续内存块,则返回起始编号最小的那个。

样例

输入

2,4,3,7,6

输出

2,3

解释

2 , 4 , 3 , 7 , 62 ,4, 3, 7 ,62,4,3,7,6 表示释放了 555 块内存,内存块编号分别为 2 , 4 , 3 , 7 , 62, 4, 3 ,7, 62,4,3,7,6 .

经过回收合并后, 2 , 3 , 42,3,42,3,4 三块内存连续,可以合并为一块大内存、大小为 333 个单位

6 , 76 ,76,7 两块内存连续,合并后连续内存大小为 222

因此返回此时的最大连续内存的起始位置为 222 ,内存大小为 333

样例2

输入

1,3,7,9,8,6

输出

6,4

思路

由于需要我们查找连续数字,因此,我们需要对给定的数组进行排序,这样我们判断两个数字连续只需要判断 a r r [ i ] − a r r [ i − 1 ] = = 1arr[i]-arr[i-1]==1arr[i]arr[i1]==1即可.

那么我们可以对于每一个数字 a r r [ i ]arr[i]arr[i]都以它本身编号i为起始编号,不断向后查找求得最长长度,时间复杂度为 O ( n2)O(n^2)O(n2).这个时间复杂度可以优化.我们发现假设i为起始编号对应最长长度为 c n t ( c n t > 1 )cnt(cnt>1)cnt(cnt>1),那么 i + 1i+1i+1为起始编号时,最长长度肯定是 c n t − 1cnt-1cnt1.因此,我们一旦发现最长长度 c n tcntcnt大于1时,那么后续的 c n t − 1cnt-1cnt1个数都不需要寻找最长长度,因为必定小于 c n tcntcnt.

按照上面的思路,我们假设 iii为起始编号时,对应最长长度为 c n tcntcnt.此时,下一步我们需要判断的下标就可以为 i + c n ti+cnti+cnt,其中 [ i + 1 , i + c n t − 1 ][i+1,i+cnt-1][i+1,i+cnt1]的下标都不需要判断最长长度.所以总的时间复杂度为 O ( n )O(n)O(n),因为每个点都只会被所有循环加起来枚举到一次.

类似题目推荐

代码

CPP

#include #include #include int main() {std::vector<int> arr;std::string input;std::getline(std::cin, input);std::string token;size_t pos = 0;while ((pos = input.find(',')) != std::string::npos) {token = input.substr(0, pos);arr.push_back(std::stoi(token));input.erase(0, pos + 1);}arr.push_back(std::stoi(input));//处理输入std::sort(arr.begin(), arr.end());//排序int i = 0;int ans1 = -1;int ans2 = -1;while (i < arr.size()) {//第一层循环int cnt = 1;//记录最大相邻数for (int j = i + 1; j < arr.size(); j++) {//向后找有没有相邻的if (arr[j] - arr[j - 1] == 1) {cnt++;} else {break;}}if (cnt > ans2) {//更新答案ans2 = cnt;ans1 = arr[i];}i += cnt;//按照题解意思,我们后面需要查找的下标为i+cnt}std::cout << ans1 << ",";std::cout << ans2 << std::endl;return 0;}

python

arr = [int(i) for i in input().split(",")]#处理输入arr.sort()#排序i = 0ans1 = -1ans2 = -1while i < len(arr):#第一层循环cnt = 1for j in range(i + 1, len(arr)):#记录最大相邻数 if arr[j] - arr[j - 1] == 1:#向后找有没有相邻的 cnt += 1 else: breakif cnt > ans2:#更新答案ans2 = cntans1 = arr[i]i += cnt#按照题解意思,我们后面需要查找的下标为i+cntprint(ans1,end="")print(",",end="")print(ans2,end="")

Java

import java.util.*;public class Main {public static void main(String[] args) {Scanner scanner = new Scanner(System.in);String[] input = scanner.nextLine().split(",");List<Integer> arr = new ArrayList<>();for (String s : input) {arr.add(Integer.parseInt(s));}//处理输入Collections.sort(arr);//排序int i = 0;int ans1 = -1;int ans2 = -1;while (i < arr.size()) {//第一层循环int cnt = 1;for (int j = i + 1; j < arr.size(); j++) {//记录最大相邻数if (arr.get(j) - arr.get(j - 1) == 1) {//向后找有没有相邻的cnt++;} else {break;}}if (cnt > ans2) {//更新答案ans2 = cnt;ans1 = arr.get(i);}i += cnt;//按照题解意思,我们后面需要查找的下标为i+cnt}System.out.print(ans1 + ",");System.out.print(ans2);}}

Go

package mainimport ("fmt""sort""strconv""strings")func main() {var input stringfmt.Scanln(&input)arrStr := strings.Split(input, ",")arr := make([]int, len(arrStr))for i, numStr := range arrStr {arr[i], _ = strconv.Atoi(numStr)}//处理输入sort.Ints(arr)//排序i := 0ans1 := -1ans2 := -1for i < len(arr) {//第一层循环cnt := 1for j := i + 1; j < len(arr); j++ {//记录最大相邻数if arr[j]-arr[j-1] == 1 {//向后找有没有相邻的cnt++} else {break}}if cnt > ans2 {//更新答案ans2 = cntans1 = arr[i]}i += cnt//按照题解意思,我们后面需要查找的下标为i+cnt}fmt.Printf("%d,%d", ans1, ans2)}

Js

const readline = require('readline');const rl = readline.createInterface({input: process.stdin,output: process.stdout});rl.question('', input => {const arr = input.split(',').map(Number);//处理输入arr.sort((a, b) => a - b);//排序let i = 0;let ans1 = -1;let ans2 = -1;while (i < arr.length) {//第一层循环let cnt = 1;for (let j = i + 1; j < arr.length; j++) {//记录最大相邻数if (arr[j] - arr[j - 1] === 1) {//向后找有没有相邻的cnt++;} else {break;}}if (cnt > ans2) {//更新答案ans2 = cnt;ans1 = arr[i];}i += cnt;//按照题解意思,我们后面需要查找的下标为i+cnt}console.log(`${ans1},${ans2}`);rl.close();});

题目内容均收集自互联网,如如若此项内容侵犯了原著者的合法权益,可联系我: (CSDN网站注册用户名: 塔子哥学算法) 进行删除。