(题目大致意思)
寻找输入中有几个死锁,首先输入总共有多少条数据。然后一行输入的信息中第一列代表数据id,第二列代表正在占用的资源id(如果有多个,则用逗号分割,没有则为空格),第三列代表申请占用的资源id(如果有多个,则用逗号分割,没有则为空格)。每列之间用制表符分割。判断其中有多少个死锁。
输入(
为了避免分不清制表符和空格,我在原题的基础上加上了[制表符]和[空格
]来区分制表符(tab键)和空格(space键))
7
125[制表符]1001,1002[制表符]1003
126[制表符]1003[制表符]1004
127[制表符][空格][制表符][空格]
128[制表符][空格]1005
129[制表符]1004[制表符]1002
130[制表符]1006[制表符][空格]
131[制表符]1007[制表符]1005
输出
1
思路分析:
1006——>null
1007——>1005
1001
\
> 1003——>1004
/ |
1002 <—————— |
以上存在一个环,所以只有一个死锁
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Scanner;
/**
* 思路:
* 1、读取解析所有输入
* 2、依次将这些数值以链表的形式连接起来
* 3、然后遍历(一步两步看是否重合的形式)判断是否有环
* 4、如果有环,将环中的节点放到Set中,最后看有多少个不同的环,就有多少个死锁现象
*/
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int len = in.nextInt();
in.nextLine();
// 用来存储值和其相应节点
HashMap<Integer,ListNode> map = new HashMap<Integer,ListNode>();
// 遍历所有输入
for(int i=0;i<len;i++){
// 读取输入的数据
String str = in.nextLine();
String[] newstr = parserString(str);
// 正在占用的资源
ArrayList<Integer> left = new ArrayList<Integer>();
// 申请占用的资源
ArrayList<Integer> right = new ArrayList<Integer>();
// 如果正在占用资源中有值,不为null,也不为空格
if(newstr[1]!=null&&!newstr[1].equals(" ")){
left = parserToint(newstr[1]);
}
else{
continue;
}
// 如果申请占用资源中有值,不为null,也不为空格
if(newstr[2]!=null&&!newstr[2].equals(" ")){
right = parserToint(newstr[2]);
}
else{
continue;
}
// 将正在占用的资源与申请占用的资源,链接起来
for(int j=0;j<right.size();j++){
ListNode nodeRight = null;
if(!map.containsKey(right.get(j))){
nodeRight = new ListNode(right.get(j));
nodeRight.next = null;
map.put(right.get(j), nodeRight);
}
else{
nodeRight = map.get(right.get(j));
}
for(int x=0;x<left.size();x++){
ListNode nodeLeft = null;
if(!map.containsKey(left.get(x))){
nodeLeft = new ListNode(left.get(x));
}
else{
nodeLeft = map.get(left.get(x));
}
nodeLeft.next = nodeRight;
map.put(left.get(x), nodeLeft);
}
}
}
// set用来存储有循环的节点集合,set中有多少个这样的集合,就有多少次死锁发生
HashSet<HashSet<ListNode>> set = new HashSet<HashSet<ListNode>>();
for(int key : map.keySet()){
if(returnLoopSet(map.get(key))!=null){
set.add(returnLoopSet(map.get(key)));
}
}
System.out.println(set.size());
in.close();
}
// 以制表符为分割符来分割输入的一组数据
public static String[] parserString(String str){
return str.split("\t");
}
// 以逗号为分割符,来解析其中的数值
public static ArrayList<Integer> parserToint(String str){
String[] strArray = str.split(",");
ArrayList<Integer> list = new ArrayList<Integer>();
for(int i=0;i<strArray.length;i++){
list.add(Integer.valueOf(strArray[i]));
}
return list;
}
// 找到有环的所有节点的集合
public static HashSet<ListNode> returnLoopSet(ListNode node){
ListNode node1 = node;
ListNode node2 = node;
HashSet<ListNode> hashSet = new HashSet<ListNode>();
// 通过一步两步遍历的方式来判断是否有环
while(node1!=null&&node2!=null&&node1.next!=null&&node2.next.next!=null){
node1 = node1.next;
hashSet.add(node1);
node2 = node2.next.next;
if(node1.equals(node2)){
return hashSet;
}
}
return null;
}
}
// 自定义链表类
class ListNode{
int value;
ListNode next;
public ListNode(int value){
this.value = value;
}
}