Konvertieren von C ++ - Karten in Java-Karten
Betrachten Sie den folgenden CPP-Code
string ans = "NO";
map<int,vi> idv ; //vi is vector of int
for(int i=1;i<=n;i++)
idv.[arr[i]].push_back(i);
//frequecy >= 3
for(auto el:idv){
if(el.ss.size() >= 3){
ans = "YES";}
}
//non adjecent equal elements
for(auto el:idv)
{
if(el.ss.size() == 2 && el.ss[0] != el.ss[1]-1)
{
ans = "YES";
}
}
cout<<ans<<endl;
Mein Java-Übersetzungscode
String ans = "NO";
Map<Integer,List<Integer>> map = new HashMap<>();
for (int i : arr) {
// map.merge(i,1,Integer::sum);
// map.put(i, )
List<Integer> temp = map.getOrDefault(i, new ArrayList<>());
temp.add(i);
map.put(i,temp);
}
//check for freq 3
for (Map.Entry<Integer,List<Integer>> e : map.entrySet())
{
if(e.getValue().size() == 3)
ans ="YES";
}
//freq 2 and pos change
for (Map.Entry<Integer,List<Integer>> i : map.entrySet())
{
if(i.getValue().size() == 2 && i.getValue().get(0) != i.getValue().get(1) - 1)
ans = "YES";
}
System.out.println(ans);
Eingabe arr []
1 2 1
1 2 2 3 2
1 1 2
1 2 2 1
1 1 2 2 3 3 4 4 5 5
Ausgabe
YES
YES
NO
YES
NO
Aber es funktioniert nicht richtig wie beabsichtigt. Kann mir bitte jemand sagen, wie ich es effizienter machen kann? Auch für die erste Schleife könnte ich map.merge verwenden. Wenn jemand weiß, wie es geht, lass es mich wissen. Danke ✌️
Zunächst werden die Indizes durch das folgende Snippet an das Ende des Vektors verschoben, und Sie müssen sich in Java dem gleichen Ansatz nähern, ohne für jede Schleife eine Verbesserung vorzunehmen:
// C++
for (int i=1;i<=n;i++)
idv.[arr[i]].push_back(i);
// Java
Map<Integer, List<Integer>> map = new HashMap<>();
for (int i=0; i<arr.length; i++) {
List<Integer> temp = map.getOrDefault(arr[i], new ArrayList<>());
temp.add(i);
map.put(arr[i],temp);
// or shorter:
// map.computeIfAbsent(arr[i], key->new ArrayList<>()).add(i);
}
Als nächstes iterieren Sie die Karte in Java und C ++ zweimal, was nicht erforderlich ist. Verwenden Sie dieselbe logische Disjunktion. In Java können Sie nur Werte iterieren. Sie müssen die tatsächlichen Einträge nicht durchlaufen, wenn Sie keine Schlüssel benötigen:
for (List<Integer> list: map.values()) {
if (list.size() == 3 || (list.size() == 2 && list.get(0) != list.get(1) - 1)) {
ans = "YES";
break; // no need to continue iteration, you have the answer
}
}
Das Ganze kann noch einfacher vereinfacht werden, indem Sie den Vorteil eines Java-Streams nutzen, der Ihnen hilft, Folgendes zu erstellen Map<Integer, List<Integer>>
:
Map<Integer, List<Integer>> map1 = IntStream.range(0, arr.length)
.boxed()
.collect(Collectors.groupingBy(i -> arr[i]));
String ans = "NO";
for (List<Integer> list: map.values()){
if (list.size() == 3 || (list.size() == 2 && list.get(0) != list.get(1) - 1)) {
ans = "YES";
break;
}
}
Dank @ Holger kann dies noch einfacher sein Collectors.collectingAndThen
:
String ans = IntStream.range(0, arr.length)
.boxed()
.collect(Collectors.collectingAndThen(
Collectors.groupingBy(i -> arr[i]),
map -> map.values().stream()
.filter(l -> l.size() == 3 || (l.size() == 2 && l.get(0) != l.get(1) - 1))
.findAny().map(x -> "YES").orElse("NO")));