news 2026/5/23 17:08:01

(100分)- 端口合并(Java JS Python)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
(100分)- 端口合并(Java JS Python)

(100分)- 端口合并(Java & JS & Python)

题目描述

有M个端口组(1<=M<=10),
每个端口组是长度为N的整数数组(1<=N<=100),
如果端口组间存在2个及以上不同端口相同,则认为这2个端口组互相关联,可以合并。

输入描述

第一行输入端口组个数M,再输入M行,每行逗号分割,代表端口组。

备注:端口组内数字可以重复。

输出描述

输出合并后的端口组,用二维数组表示。

  • 组内相同端口仅保留一个,从小到达排序。
  • 组外顺序保持输入顺序

备注:M,N不在限定范围内,统一输出一组空数组[[]]

用例
输入4
4
2,3,2
1,2
5
输出[[4],[2,3],[1,2],[5]]
说明仅有一个端口2相同,不可以合并。
输入3
2,3,1
4,3,2
5
输出[[1,2,3,4],[5]]
说明
输入6
10
4,2,1
9
3,6,9,2
6,3,4
8
输出[[10],[1,2,3,4,6,9],[9],[8]]
说明
输入11
输出[[]]
说明
题目解析

本题有一个疑点:

如果端口组间存在2个及以上不同端口相同,则认为这2个端口组互相关联,可以合并。

关于"不同端口"的具体含义:

以您提供的用例为例,两个端口组都包含端口3和3,这种情况是否可以合并呢?

2
3 3 5
1 3 3

假设数组 a = [3,3,5],b = [1,3,3],其中a[0]与b[1]的值相同,a[1]与b[2]的值也相同。这种情况下,虽然端口位置不同但数值相同,是否可以视为两个不同的端口匹配?

这个问题会导致两种不同的解题思路:

  1. 若两个端口组能形成两对数值相同的端口匹配,即可进行合并
  2. 必须形成两对数值不同的端口匹配,才能进行合并

如果能形成2个端口值相同的端口对,那么也可以合并

JavaScript算法源码
/* JavaScript Node ACM模式 控制台输入获取 */ const readline = require("readline"); const rl = readline.createInterface({ input: process.stdin, output: process.stdout, }); const lines = []; let m; rl.on("line", (line) => { lines.push(line); if (lines.length === 1) { m = lines[0] - 0; // M,N不在限定范围内,统一输出一组空数组[[]] if (m > 10 || m < 1) { console.log("[[]]"); lines.length = 0; return; } } if (m && lines.length === m + 1) { lines.shift(); const ports = lines.map((line) => line.split(",").map(Number)); for (let port of ports) { const n = port.length; // M,N不在限定范围内,统一输出一组空数组[[]] if (n < 1 || n > 100) { console.log("[[]]"); lines.length = 0; return; } } console.log(getResult(ports)); lines.length = 0; } }); // 算法入口 function getResult(ports) { outer: while (true) { // 这里倒序遍历端口组是为了实现:组外顺序保持输入顺序 for (let i = ports.length - 1; i >= 0; i--) { for (let j = i - 1; j >= 0; j--) { // 判断两个端口是否可以合并 if (canUnion(ports[i], ports[j])) { // 将后面的端口组,并入前面的端口组,这样就不会破坏组外顺序 ports[j].push(...ports[i]); ports.splice(i, 1); continue outer; } } } break; } const ans = ports.map((port) => [...new Set(port)].sort((a, b) => a - b)); return JSON.stringify(ans); } // 如果端口组间存在2个及以上不同端口相同,则认为这2个端口组互相关联,可以合并。 // 下面方法实现中:对于“不同端口”的理解是:端口位置不同,端口值可以相同,即以不同位置的端口视为不同端口 function canUnion(port1, port2) { port1.sort((a, b) => a - b); port2.sort((a, b) => a - b); let same = 0; let i = 0; let j = 0; while (i < port1.length && j < port2.length) { if (port1[i] == port2[j]) { i++; j++; if (++same >= 2) return true; } else if (port1[i] > port2[j]) { j++; } else { i++; } } return false; }
Java算法源码
import java.util.*; public class Main { public static void main(String[] args) { Scanner sc = new Scanner(System.in); int m = Integer.parseInt(sc.nextLine()); // M,N不在限定范围内,统一输出一组空数组[[]] if (m > 10 || m < 1) { System.out.println("[[]]"); return; } // 这里使用ArrayList接收端口组,是为了后面更方便进行端口组之间的合并 ArrayList<ArrayList<Integer>> ports = new ArrayList<>(); for (int i = 0; i < m; i++) { Integer[] tmp = Arrays.stream(sc.nextLine().split(",")).map(Integer::parseInt).toArray(Integer[]::new); // M,N不在限定范围内,统一输出一组空数组[[]] int n = tmp.length; if (n < 1 || n > 100) { System.out.println("[[]]"); return; } ArrayList<Integer> tmpList = new ArrayList<>(Arrays.asList(tmp)); ports.add(tmpList); } System.out.println(getResult(ports)); } // 算法入口 public static String getResult(ArrayList<ArrayList<Integer>> ports) { outer: while (true) { // 这里倒序遍历端口组是为了实现:组外顺序保持输入顺序 for (int i = ports.size() - 1; i >= 0; i--) { for (int j = i - 1; j >= 0; j--) { // 判断两个端口是否可以合并 if (canUnion(ports.get(i), ports.get(j))) { // 将后面的端口组,并入前面的端口组,这样就不会破坏组外顺序 ports.get(j).addAll(ports.get(i)); ports.remove(i); continue outer; } } } break; } StringJoiner out = new StringJoiner(",", "[", "]"); for (ArrayList<Integer> port : ports) { StringJoiner in = new StringJoiner(",", "[", "]"); for (Integer v : new TreeSet<Integer>(port)) { // 这里使用TreeSet是为了实现:组内相同端口仅保留一个,从小到达排序。 in.add(v + ""); } out.add(in.toString()); } return out.toString(); } // 如果端口组间存在2个及以上不同端口相同,则认为这2个端口组互相关联,可以合并。 // 下面方法实现中:对于“不同端口”的理解是:端口位置不同,端口值可以相同,即以不同位置的端口视为不同端口 public static boolean canUnion(ArrayList<Integer> port1, ArrayList<Integer> port2) { port1.sort((a, b) -> a - b); port2.sort((a, b) -> a - b); int same = 0; int i = 0; int j = 0; while (i < port1.size() && j < port2.size()) { if (port1.get(i) - port2.get(j) == 0) { i++; j++; if (++same >= 2) return true; } else if (port1.get(i) > port2.get(j)) { j++; } else { i++; } } return false; } }
Python算法源码
import re # 如果端口组间存在2个及以上不同端口相同,则认为这2个端口组互相关联,可以合并。 # 下面方法实现中:对于“不同端口”的理解是:端口位置不同,端口值可以相同,即以不同位置的端口视为不同端口 def canUnion(port1, port2): port1.sort() port2.sort() same = 0 i = 0 j = 0 while i < len(port1) and j < len(port2): if port1[i] == port2[j]: i += 1 j += 1 same += 1 if same >= 2: return True elif port1[i] > port2[j]: j += 1 else: i += 1 return False # 从头开始尝试合并端口组 def forPorts(ports): # 这里倒序遍历端口组是为了实现:组外顺序保持输入顺序 for i in range(len(ports) - 1, -1, -1): for j in range(i - 1, -1, -1): # 判断两个端口是否可以合并 if canUnion(ports[i], ports[j]): # 将后面的端口组,并入前面的端口组,这样就不会破坏组外顺序 ports[j].extend(ports[i]) ports.pop(i) return True # 继续尝试合并 return False # 合并尝试结束 # 组内相同端口仅保留一个,从小到达排序 def distinctAndSort(port): tmp = list(set(port)) tmp.sort() return tmp # 算法入口 def getResult(ports): while True: if not forPorts(ports): break # return list(map(distinctAndSort, ports)) # 如果输出内容不去除空格,可得83.33%通过率 return re.sub(f"\\s", "", str(list(map(distinctAndSort, ports)))) # 输入获取 m = int(input()) if m < 1 or m > 10: print("[[]]") else: ports = [list(map(int, input().split(","))) for _ in range(m)] if len(list(filter(lambda p: len(p) < 1 or len(p) > 100, ports))) > 0: print("[[]]") else: print(getResult(ports))

只有形成2对端口值不同的端口对,那么才可以合并

Java算法源码
import java.util.*; public class Main { public static void main(String[] args) { Scanner sc = new Scanner(System.in); int m = Integer.parseInt(sc.nextLine()); // M,N不在限定范围内,统一输出一组空数组[[]] if (m > 10 || m < 1) { System.out.println("[[]]"); return; } // 这里使用ArrayList接收端口组,是为了后面更方便进行端口组之间的合并 ArrayList<ArrayList<Integer>> ports = new ArrayList<>(); for (int i = 0; i < m; i++) { Integer[] tmp = Arrays.stream(sc.nextLine().split(",")).map(Integer::parseInt).toArray(Integer[]::new); // M,N不在限定范围内,统一输出一组空数组[[]] int n = tmp.length; if (n < 1 || n > 100) { System.out.println("[[]]"); return; } ArrayList<Integer> tmpList = new ArrayList<>(Arrays.asList(tmp)); ports.add(tmpList); } System.out.println(getResult(ports)); } // 算法入口 public static String getResult(ArrayList<ArrayList<Integer>> ports) { outer: while (true) { // 这里倒序遍历端口组是为了实现:组外顺序保持输入顺序 for (int i = ports.size() - 1; i >= 0; i--) { for (int j = i - 1; j >= 0; j--) { // 判断两个端口是否可以合并 if (canUnion(ports.get(i), ports.get(j))) { // 将后面的端口组,并入前面的端口组,这样就不会破坏组外顺序 ports.get(j).addAll(ports.get(i)); ports.remove(i); continue outer; } } } break; } StringJoiner out = new StringJoiner(",", "[", "]"); for (ArrayList<Integer> port : ports) { StringJoiner in = new StringJoiner(",", "[", "]"); for (Integer v : new TreeSet<Integer>(port)) { // 这里使用TreeSet是为了实现:组内相同端口仅保留一个,从小到达排序。 in.add(v + ""); } out.add(in.toString()); } return out.toString(); } // 如果端口组间存在2个及以上不同端口相同,则认为这2个端口组互相关联,可以合并。 // 下面方法实现中:要形成两对“端口值不同的端口对”,即 a = [1,2,3],b=[2,3,4]可以合并,但是a = [1,3,3],b=[3,3,4]不可以合并 public static boolean canUnion(ArrayList<Integer> port1, ArrayList<Integer> port2) { HashSet<Integer> set1 = new HashSet<>(port1); HashSet<Integer> set2 = new HashSet<>(port2); int same = 0; for (Integer v1 : set1) { if (set2.contains(v1)) { if (++same >= 2) return true; } } return false; } }
JavaScript算法源码
/* JavaScript Node ACM模式 控制台输入获取 */ const readline = require("readline"); const rl = readline.createInterface({ input: process.stdin, output: process.stdout, }); const lines = []; let m; rl.on("line", (line) => { lines.push(line); if (lines.length === 1) { m = lines[0] - 0; // M,N不在限定范围内,统一输出一组空数组[[]] if (m > 10 || m < 1) { console.log("[[]]"); lines.length = 0; return; } } if (m && lines.length === m + 1) { lines.shift(); const ports = lines.map((line) => line.split(",").map(Number)); for (let port of ports) { const n = port.length; // M,N不在限定范围内,统一输出一组空数组[[]] if (n < 1 || n > 100) { console.log("[[]]"); lines.length = 0; return; } } console.log(getResult(ports)); lines.length = 0; } }); // 算法入口 function getResult(ports) { outer: while (true) { // 这里倒序遍历端口组是为了实现:组外顺序保持输入顺序 for (let i = ports.length - 1; i >= 0; i--) { for (let j = i - 1; j >= 0; j--) { // 判断两个端口是否可以合并 if (canUnion(ports[i], ports[j])) { // 将后面的端口组,并入前面的端口组,这样就不会破坏组外顺序 ports[j].push(...ports[i]); ports.splice(i, 1); continue outer; } } } break; } const ans = ports.map((port) => [...new Set(port)].sort((a, b) => a - b)); return JSON.stringify(ans); } // 如果端口组间存在2个及以上不同端口相同,则认为这2个端口组互相关联,可以合并。 // 下面方法实现中:要形成两对“端口值不同的端口对”,即 a = [1,2,3],b=[2,3,4]可以合并,但是a = [1,3,3],b=[3,3,4]不可以合并 function canUnion(port1, port2) { const set1 = new Set(port1); const set2 = new Set(port2); let same = 0; for (let v1 of set1) { if (set2.has(v1)) { if (++same >= 2) return true; } } return false; }
Python算法源码
import re # 如果端口组间存在2个及以上不同端口相同,则认为这2个端口组互相关联,可以合并。 # 下面方法实现中:要形成两对“端口值不同的端口对”,即 a = [1,2,3],b=[2,3,4]可以合并,但是a = [1,3,3],b=[3,3,4]不可以合并 def canUnion(port1, port2): set1 = set(port1) set2 = set(port2) same = 0 for v in set1: if v in set2: same += 1 if same >= 2: return True return False # 从头开始尝试合并端口组 def forPorts(ports): # 这里倒序遍历端口组是为了实现:组外顺序保持输入顺序 for i in range(len(ports) - 1, -1, -1): for j in range(i - 1, -1, -1): # 判断两个端口是否可以合并 if canUnion(ports[i], ports[j]): # 将后面的端口组,并入前面的端口组,这样就不会破坏组外顺序 ports[j].extend(ports[i]) ports.pop(i) return True # 继续尝试合并 return False # 合并尝试结束 # 组内相同端口仅保留一个,从小到达排序 def distinctAndSort(port): tmp = list(set(port)) tmp.sort() return tmp # 算法入口 def getResult(ports): while True: if not forPorts(ports): break # return list(map(distinctAndSort, ports)) return re.sub(f"\\s", "", str(list(map(distinctAndSort, ports)))) # 输入获取 m = int(input()) if m < 1 or m > 10: print("[[]]") else: ports = [list(map(int, input().split(","))) for _ in range(m)] if len(list(filter(lambda p: len(p) < 1 or len(p) > 100, ports))) > 0: print("[[]]") else: print(getResult(ports))
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/20 13:01:12

《深入理解Java虚拟机》| 运行时数据区与OOM异常

摘要&#xff1a;本文系统解析《深入理解Java虚拟机》中的运行时数据区与OOM异常&#xff0c;包括程序计数器、虚拟机栈、堆内存、方法区与直接内存&#xff0c;同时讲解OOM异常等解决方案。 书摘内容 运行时数据区域 运行时数据区是 JVM 的内存核心&#xff0c;分为线程共享区…

作者头像 李华
网站建设 2026/5/21 14:51:34

leetcode 925. Long Pressed Name 长按键入-耗时100

Problem: 925. Long Pressed Name 长按键入 耗时100%&#xff0c;双指针&#xff0c;若左右字符相等l; r&#xff0c;若r > 0 && typed[r-1]typed[r]则r&#xff0c;否则false&#xff0c;最后若while(r < n2 && typed[r-1]typed[r]) r;&#xff0c;if(l…

作者头像 李华
网站建设 2026/5/23 6:46:08

如何获得Agentic AI提示工程架构师认证?备考与实战经验

Agentic AI提示工程架构师认证全攻略&#xff1a;备考计划实战经验核心技巧 1. 标题 (Title) 从入门到持证&#xff1a;Agentic AI提示工程架构师认证备考实战指南Agentic AI提示工程架构师认证之路&#xff1a;我如何3个月从零基础到通过考试&#xff1f;成为AI架构师的敲门…

作者头像 李华
网站建设 2026/5/23 10:22:47

14.僵尸孤儿-进程状态

一个pcb既属于全局链表又属于这个队列这个队列也是双链表&#xff0c;只不过先进先出FIFO运行状态就是正在被cpu运行&#xff0c;或者准备好了随时等待被调度。 包括运行和就绪。一个进程要去读键盘就要转去另一个队列&#xff0c;如果这个设备没有活跃&#xff0c;就没有读到键…

作者头像 李华
网站建设 2026/5/23 12:17:23

MATLAB鸟鸣识别系统截图](https://example.com/gui_screenshot.png

基于MATLAB的鸟鸣识别系统gui 传统声音特征&#xff0c;如MFCC机器学习分类器 分类器有支持向量积svm&#xff0c;邻近knn&#xff0c;分类树tree等 深度学习方法主要是先提取语谱图&#xff0c;有短时傅立叶时频图&#xff0c;和梅尔时频图 然后用googlenet进行深度学习训练 结…

作者头像 李华