題目來源:2020年2月某國企校招其中一道編程筆試題回憶。
備註:筆試的時候並沒有做出來,現在的代碼不能保證沒有邏輯錯誤,請各位大佬批評指正,感謝!
題目回憶
Pi代表股東,Ej代表公司(其中 i 和 j 代表正整數),Pi可以投資不同的Ej,這樣就導致Pi和Ej之間是多對多的關係。 股東之間有關聯 的定義如下:
①Pi與其本身有關聯;
②如果Px投資了Ej,並且Py也投資了Ej,則Px和Py有關聯。
輸入樣例
P2;P1,E1;P2,E1,E2;P3,E3
其中第一個分號之前只有一個Pi,是目標股東;
我們要做的就是找出所有和Pi有關聯的股東;
之後的每一個分號,分割了每個股東及其投資的公司。
對輸入樣例就可以解釋爲:
已知P1投資了E1;P2投資了E1、E2;P3投資了E3;
求所有和股東P2有關聯的股東。
輸出結果:
P1,P2
輸出結果要按照字典序從小到大的順序輸出,相鄰兩個股東之間用逗號分隔。
思路
1. 藉助split方法對輸入的字符串按照分號進行分割,獲取目標股東以及每個股東和他投資的所有公司;
2. 計算一共有多少投資人;
3. 藉助HashMap<String, String> 來記錄每個股東人與他所投資的公司之間的對應關係,將每個投資人作爲key,這個投資人投資的所有公司的輸入順序子串作爲value存儲起來,如輸入樣例中有三組鍵值對,分別是 <key:“P1”,value:“E!”>,<key:“P2”,value:“E1,E2”>,<key:“P3”,value:“E3”> ;將這個Map命名爲result;
4. 確定目標股東在字符串的位置,並將他記錄下來;
5. 遍歷result的key,找到目標股東對應的那一組鍵值對,如樣例輸入中會找到<key:“P2”,value:“E1,E2”>,找到之後,把這一個鍵值對的value值,按照逗號 “,” 進行分割,這樣會得到目標股東投資的所有公司,把這些公司逐個記錄到列表listval中;
6. 雙重循環,外層遍歷列表listval,取出目標股東投資的所有公司名稱Ez ,挨個與之前創建的Map(即result)中的所有鍵值對的value值進行比對,如果result的某一個鍵值對的value值(是一個字符串)中包含Ez這個子串,那麼就把這個鍵值對的key值添加進listkey中記錄下來,listkey是用TreeSet定義的;
7. 之所以要用TreeSet是因爲我們要做到有序輸出,而且Set中不會包含重複元素的,重複元素添加是不被完成的;
8. 按照輸出要求對listkey進行遍歷輸出。
代碼
import java.util.HashMap;
import java.util.IdentityHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Scanner;
import java.util.TreeSet;
public class Main {
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner in = new Scanner(System.in);
String str = in.next();
// 藉助split方法對輸入的字符串按照分號進行分割,獲取目標股東以及每個股東和他投資的所有公司
String [] relation = str.split(";");
// 計算一共有多少投資人
int count = -1;
for (String s : relation) {
count ++;
}
// 藉助HashMap來記錄每個股東人與他所投資的公司之間的對應關係
Map<String, String> result = new HashMap<String, String>();
// 將每個投資人作爲key,這個投資人投資的所有公司的輸入順序子串作爲value存儲起來
for (int i = 1; i <= count; i++) {
// 定位投資人
String pp = relation[i].substring(0, 2);
// 定位該投資人投資的所有公司組成的字符串
result.put(pp, relation[i].substring(3, relation[i].length()));
}
// 確定目標股東在字符串的位置
int i = 0;
for (i = 0; i < str.length(); i++) {
if (str.charAt(i) == ';') {
break;
}
}
// 將目標股東target記錄下來
String target = str.substring(0, i);
// listval用來記錄目標股東投資的所有公司
List<String> listval = new LinkedList<String>();
// listkey用來記錄與目標股東有關聯的所有股東(包含他自己)
TreeSet<String> listkey = new TreeSet<String>();
for (String key : result.keySet()) {
// 輸出檢查有沒有出錯 : System.out.println(key + " " + result.get(key) + " ");
if (key.equals(target)) { // 找到目標股東對應的那一組鍵值對
// 把這一個鍵值對的value值,按逗號進行分割,這樣會得到目標股東投資的所有公司
String [] relationee = result.get(key).split(",");
// 把目標股東投資的所有公司都添加到listval列表中用於後期的對比
for (int index = 0; index < relationee.length; index++) {
listval.add(relationee[index]);
// 輸出檢查有沒有出錯 : System.out.print(relationee[index] + " " + index + '\n');
}
}
}
// 遍歷列表listval,取出目標股東投資的所有公司名稱
for(Object one : listval) {
// 輸出檢查有沒有出錯 : System.out.println(one.toString());
for (Map.Entry<String, String> entry : result.entrySet()) {
// 目標股東投資的所有公司名稱挨個與之前創建的Map(即result)中的所有鍵值對的value值進行比對,
// 如果result的某一個鍵值對的value值(是一個字符串)中包含Ez這個子串,
// 那麼就把這個鍵值對的key值添加進**listkey**中記錄下來
// 輸出檢查有沒有出錯 : System.out.println(entry.getValue() + " entry.getValue()");
if (entry.getValue().contains(one.toString())) {
listkey.add(entry.getKey().toString());
// 輸出檢查有沒有出錯 : System.out.println(entry.getKey() + " key ");
}
}
}
// 按照輸出要求對listkey進行遍歷輸出
System.out.print(listkey.pollFirst());
while(!listkey.isEmpty()) {
System.out.print("," + listkey.pollFirst());
}
//輸入樣例: P2;P1,E1;P2,E1,E2;P3,E3
//輸出樣例: P1,P2
}
}