英文版

582. Kill Process
Given n processes, each process has a unique PID (process id) and its PPID (parent process id).

Each process only has one parent process, but may have one or more children processes. This is just like a tree structure. Only one process has PPID that is 0, which means this process has no parent process. All the PIDs will be distinct positive integers.

We use two list of integers to represent a list of processes, where the first list contains PID for each process and the second list contains the corresponding PPID.

Now given the two lists, and a PID representing a process you want to kill, return a list of PIDs of processes that will be killed in the end. You should assume that when a process is killed, all its children processes will be killed. No order is required for
the final answer.

Example 1:

Input:
pid = [, , , ]
ppid = [, , , ]
kill =
Output: [,]
Explanation: / \ / Kill will also kill .

Note:

  • - The given kill id is guaranteed to be one of the given PIDs.
  • - n >= 1.

中文版
给你n个进程,每个进程都有一个唯一的PID(process id)和PPID(parent process id)。每个进程最多只有一个父进程,但可能有多个子进程。如果一个进程的PPID为0,表示它没有父进程。如果一个进程被杀死,那么它的子进程也会被杀死。输入两个相同长度的整数链表,第一个链表是每个进程的PID,第二个链表是对应位置进程的PPID,再输入一个将被杀死的进程的PID,请输出所有将被杀死的进程的PID。

例如,输入的PID链表为[1, 3, 10, 5],PPID链表为[3, 0, 5, 3],将被杀死的进程的PID为5,那么最终被杀死的进程有两个,PID分别为5和10。这是因为PID为10的进程是PID为5的进程的子进程。

分析

由于每个进程最多只有一个父进程,但可能有多个子进程,因此进程之间的关系可以用一棵树来表示。父进程对应树中的父节点,而子进程对应树中的子节点。如果进程[1, 3, 10, 5]的父进程为[3, 0, 5, 3],那么这些进程可以构成如下的一棵树:如样例中的树结构

因此,解决这个问题的第一步是根据输入的PID和PPID两个链表构建出一个树。树是一种特殊的图(Graph)。图有两种常用的表示方法,一是基于邻接表,二是基于邻接矩阵。由于树是一类比较稀疏的图,一般用邻接表更为高效。

用邻接表来表示一棵树,我们可以把整棵树存到一个HashMap中。这个HashMap的Key为进程的PID,Value为对应进程的所有子进程的PID,也就是树中对应节点的所有子节点。下面是根据PID和PPID链表构建树的参考代码:

 private Map<Integer, List<Integer>> buildTree(List<Integer> pid, List<Integer> ppid) {
Map<Integer, List<Integer>> processTree = new HashMap<>();
Iterator<Integer> iterator1 = pid.iterator();
Iterator<Integer> iterator2 = ppid.iterator();
while (iterator1.hasNext() && iterator2.hasNext()) {
int p = iterator1.next();
int pp = iterator2.next();
if (!processTree.containsKey(pp)) {
processTree.put(pp, new LinkedList<>());
}
processTree.get(pp).add(p);
}
return processTree;
}

由于杀死一个进程会杀死它的所有子进程,那么对应到树中,杀死某个节点对应的进程,也就会杀死以该节点为根节点的子树中所有节点对应的所有进程。因此,我们可以把问题转化为:如何遍历以某节点为根节点的子树。

虽然这棵由进程构成的树不一定是二叉树(因为节点的子节点数目可能大于2),但遍历算法大同小异,仍然可以按照广度优先或者深度优先的顺序遍历。下面分别介绍两种方法的代码。

深度优先解

树的深度优先搜索的代码有递归和非递归两种写法。通常基于递归的代码更为简洁,深度优先算法需要定义一个递归函数用来杀死某个进程,如下面的辅助函数kill。在函数kill中,每当杀死进程target,如果它有子进程,则递归调用函数kill去杀死它的每一个子进程child。

 public List<Integer> killProcess(List<Integer> pid, List<Integer> ppid, int target){
Map<Integer, List<Integer>> processTree = buildTree(pid, ppid);
List<Integer> result = new LinkedList<>();
kill(processTree, target, result);
return result;
} private void kill(Map<Integer, List<Integer>> processTree, int target, List<Integer> result) {
result.add(target);
if (!processTree.containsKey(target)) {
return ;
}
for (int child : processTree.get(target)) {
kill(processTree, child, result);
}
}

也可以不构建树结构直接,利用这两个数组进行递归杀死进程。

 public List<Integer> killProcess(List<Integer> pid, List<Integer> ppid, int kill) {
ArrayList<Integer> ans = new ArrayList<Integer>();
ans.add(kill);
for (int i = 0; i < ppid.size(); i++) {
if (ppid.get(i) == kill) {
ans.addAll(killProcess(pid, ppid, pid.get(i)));
}
}
return ans;
}

广度优先解

基于广度优先的代码通常会用到队列(queue)。我们首先把第一个待杀死的进程的PID放入队列中,接下来只要队列中还有待杀死的进程,就重复执行如下步骤:首先从队列中去除一个进程,杀死它(即添加到输出的链表中);接着,如果该进程有子进程则把子进程添加到队列中。

 public List<Integer> killProcess(List<Integer> pid, List<Integer> ppid, int target) {
Map<Integer, List<Integer>> processTree = buildTree(pid, ppid));
List<Integer> result = new LinkedList<>();
Queue<Integer> queue = new LinkedList<>();
queue.add(target);
while (!queue.isEmpty()) {
int process = queue.remove();
result.add(process);
if (processTree.containsKey(process)) {
for (int child : processTree.get(process)) {
queue.add(child);
}
}
}
return result;
}

杀死进程-LeetCode-582的更多相关文章

  1. 奇安信集团笔试题:二叉树的最近公共祖先(leetcode236),杀死进程(leetcode582)

    1. 二叉树最近公共祖先     奇安信集团 2020校招 服务端开发-应用开发方向在线考试 编程题|20分2/2 寻祖问宗 时间限制:C/C++语言 1000MS:其他语言 3000MS 内存限制: ...

  2. sql杀死进程

    查询SQL所有的链接  并可以查看连接当前正在做什么操作..使用的什么语句.. SELECT spid, blocked, DB_NAME(sp.dbid) AS DBName, program_na ...

  3. Window通过cmd查看端口占用、相应进程、杀死进程

       在windows下启动程序时候经常出现端口占用, 修改本程序端口是一种解决思路,但是更多时候希望直接杀掉占用端口的程序: 一. 查看所有进程占用的端口 在开始-运行-cmd,输入: netsta ...

  4. Linux Shell脚本实现根据进程名杀死进程

    Shell脚本源码如下: #!/bin/sh #根据进程名杀死进程 if [ $# -lt 1 ] then echo "缺少参数:procedure_name" exit 1 f ...

  5. Linux如何查看进程、杀死进程、启动进程等常用命令

    Linux如何查看进程.杀死进程.启动进程等常用命令 关键字: linux 查进程.杀进程.起进程1.查进程    ps命令查找与进程相关的PID号:    ps a 显示现行终端机下的所有程序,包括 ...

  6. Window 通过cmd查看端口占用、相应进程、杀死进程等的命令【转】

    一. 查看所有进程占用的端口  在开始-运行-cmd,输入:netstat –ano可以查看所有进程 二.查看占用指定端口的程序  当你在用tomcat发布程序时,经常会遇到端口被占用的情况,我们想知 ...

  7. windows下根据端口号杀死进程

    Windows不像Linux,Unix那样,ps -ef 查出端口和进程号,然后根据进程号直接kill进程. Windows根据端口号杀死进程要分三步: 第一步 根据端口号寻找进程号 C:\>n ...

  8. linux 杀死进程的方法

    # kill -pid 注释:标准的kill命令通常都能达到目的.终止有问题的进程,并把进程的资源释放给系统.然而,如果进程启动了子进程,只杀死父进程,子进程仍在运行,因此仍消耗资源.为了防止这些所谓 ...

  9. centos(linux) 下如何查看端口占用情况及杀死进程

    使用这个命令:netstat -nap [root@Jaosn sphinx]# netstat -nap Active Internet connections (servers and estab ...

随机推荐

  1. SQL与NOSQL

    一:关系型数据库 1.概念: 采用了关系模型来组织数据的数据库.简单讲,关系模型就是二维表格模型.二维表格在              数据库中我们称之为记录,列在数据库中我们成为字段. 2举例: M ...

  2. sublime text ubuntu

    { "color_scheme": "Packages/User/SublimeLinter/Dawn (SL).tmTheme", "font_fa ...

  3. spring websocket 和socketjs实现单聊群聊,广播的消息推送详解

    spring websocket 和socketjs实现单聊群聊,广播的消息推送详解 WebSocket简单介绍 随着互联网的发展,传统的HTTP协议已经很难满足Web应用日益复杂的需求了.近年来,随 ...

  4. 实用的百度下载神奇-proxyee-down

    项目地址: https://github.com/monkeyWie/proxyee-down 一.下载适合你的版本 二.运行软件 三.安装证书 四.重启软件和浏览器(注意是浏览器不是客户端),就能看 ...

  5. getCurrentSession 与 openSession() 的区别

    1 getCurrentSession创建的session会和绑定到当前线程,而openSession不会. 2 getCurrentSession创建的线程会在事务回滚或事物提交后自动关闭,而ope ...

  6. nlp 总结 分词,词义消歧,词性标注,命名体识别,依存句法分析,语义角色标注

    分词 中文分词 (Word Segmentation, WS) 指的是将汉字序列切分成词序列. 因为在汉语中,词是承载语义的最基本的单元.分词是信息检索.文本分类.情感分析等多项中文自然语言处理任务的 ...

  7. fail2ban的使用以及防暴力破解与邮件预警

    fail2ban可以监视你的系统日志,然后匹配日志的错误信息(正则式匹配)执行相应的屏蔽动作(一般情况下是防火墙),而且可以发送e-mail通知系统管理员! fail2ban运行机制:简单来说其功能就 ...

  8. Ceph 块设备 - 命令,快照,镜像

    目录 一.Ceph 块设备 二.块设备 rbd 命令 三.操作内核模块 四.快照基础 rbd snap 五.分层快照 六.镜像 rbd mirror 七.QEMU 八.libvirt 九.Openst ...

  9. Linux C 遍历指定目录

    #include<stdio.h> //标准输入输出 #include<unistd.h> //各种系统调用 #include<dirent.h> //与目录有关的 ...

  10. Nodejs学习笔记(十五)—Node.js + Koa2 构建网站简单示例

    前言 前面一有写到一篇Node.js+Express构建网站简单示例:http://www.cnblogs.com/zhongweiv/p/nodejs_express_webapp.html 这篇还 ...