@@ -112,28 +112,44 @@ public List<Integer> findEulerianPath() {
112112
113113 int [] inDegree = new int [n ];
114114 int [] outDegree = new int [n ];
115- int edgeCount = 0 ;
115+ int edgeCount = computeDegrees (inDegree , outDegree );
116+
117+ // no edges -> single vertex response requested by tests: [0]
118+ if (edgeCount == 0 ) {
119+ return Collections .singletonList (0 );
120+ }
121+
122+ int startNode = determineStartNode (inDegree , outDegree );
123+ if (startNode == -1 ) return new ArrayList <>();
124+
125+ if (!allNonZeroDegreeVerticesWeaklyConnected (startNode , n , outDegree , inDegree )) {
126+ return new ArrayList <>();
127+ }
128+
129+ List <Integer > path = buildHierholzerPath (startNode , n );
130+ if (path .size () != edgeCount + 1 ) return new ArrayList <>();
131+
132+ return rotateEulerianCircuitIfNeeded (path , outDegree , inDegree );
133+ }
116134
117- // compute degrees and total edges
118- for (int u = 0 ; u < n ; u ++) {
135+ private int computeDegrees (int [] inDegree , int [] outDegree ) {
136+ int edgeCount = 0 ;
137+ for (int u = 0 ; u < graph .getNumNodes (); u ++) {
119138 for (int v : graph .getEdges (u )) {
120139 outDegree [u ]++;
121140 inDegree [v ]++;
122141 edgeCount ++;
123142 }
124143 }
144+ return edgeCount ;
145+ }
125146
126- // no edges -> single vertex response requested by tests: [0]
127- if (edgeCount == 0 ) {
128- // If there is at least one vertex, tests expect [0] for single-node graphs with no edges.
129- // For n >= 1, return [0]. (Tests create Graph(1) for that case.)
130- return Collections .singletonList (0 );
131- }
132-
133- // Check degree differences to determine Eulerian path/circuit possibility
147+ private int determineStartNode (int [] inDegree , int [] outDegree ) {
148+ int n = graph .getNumNodes ();
134149 int startNode = -1 ;
135150 int startCount = 0 ;
136151 int endCount = 0 ;
152+
137153 for (int i = 0 ; i < n ; i ++) {
138154 int diff = outDegree [i ] - inDegree [i ];
139155 if (diff == 1 ) {
@@ -142,16 +158,14 @@ public List<Integer> findEulerianPath() {
142158 } else if (diff == -1 ) {
143159 endCount ++;
144160 } else if (Math .abs (diff ) > 1 ) {
145- return new ArrayList <>(); // invalid degree difference
161+ return - 1 ;
146162 }
147163 }
148164
149- // Must be either exactly one start and one end (path) or zero of both (circuit)
150165 if (!((startCount == 1 && endCount == 1 ) || (startCount == 0 && endCount == 0 ))) {
151- return new ArrayList <>() ;
166+ return - 1 ;
152167 }
153168
154- // If circuit, choose smallest-index vertex with outgoing edges (deterministic for tests)
155169 if (startNode == -1 ) {
156170 for (int i = 0 ; i < n ; i ++) {
157171 if (outDegree [i ] > 0 ) {
@@ -160,79 +174,67 @@ public List<Integer> findEulerianPath() {
160174 }
161175 }
162176 }
177+ return startNode ;
178+ }
163179
164- if (startNode == -1 ) {
165- return new ArrayList <>();
166- }
167-
168- // Weak connectivity check: every vertex with non-zero degree must be in the same weak component.
169- if (!allNonZeroDegreeVerticesWeaklyConnected (startNode , n , outDegree , inDegree )) {
170- return new ArrayList <>();
171- }
172-
173- // Create modifiable adjacency structure for traversal
180+ private List <Integer > buildHierholzerPath (int startNode , int n ) {
174181 List <Deque <Integer >> tempAdj = new ArrayList <>();
175182 for (int i = 0 ; i < n ; i ++) {
176183 tempAdj .add (new ArrayDeque <>(graph .getEdges (i )));
177184 }
178185
179- // Hierholzer's traversal using stack
180186 Deque <Integer > stack = new ArrayDeque <>();
181187 List <Integer > path = new ArrayList <>();
182188 stack .push (startNode );
183189
184190 while (!stack .isEmpty ()) {
185191 int u = stack .peek ();
186192 if (!tempAdj .get (u ).isEmpty ()) {
187- int v = tempAdj .get (u ).pollFirst ();
188- stack .push (v );
193+ stack .push (tempAdj .get (u ).pollFirst ());
189194 } else {
190195 path .add (stack .pop ());
191196 }
192197 }
193198
194- // Path is recorded in reverse
195199 Collections .reverse (path );
200+ return path ;
201+ }
196202
197- // Ensure all edges were used
198- if (path .size () != edgeCount + 1 ) {
199- return new ArrayList <>();
203+ private List <Integer > rotateEulerianCircuitIfNeeded (List <Integer > path , int [] outDegree , int [] inDegree ) {
204+ int startCount = 0 ;
205+ int endCount = 0 ;
206+ for (int i = 0 ; i < outDegree .length ; i ++) {
207+ int diff = outDegree [i ] - inDegree [i ];
208+ if (diff == 1 )
209+ startCount ++;
210+ else if (diff == -1 )
211+ endCount ++;
200212 }
201213
202- // If Eulerian circuit (startCount==0 && endCount==0), rotate path so it starts at
203- // the smallest-index vertex that has outgoing edges (deterministic expected by tests)
204- if (startCount == 0 && endCount == 0 ) {
214+ if (startCount == 0 && endCount == 0 && !path .isEmpty ()) {
205215 int preferredStart = -1 ;
206- for (int i = 0 ; i < n ; i ++) {
216+ for (int i = 0 ; i < outDegree . length ; i ++) {
207217 if (outDegree [i ] > 0 ) {
208218 preferredStart = i ;
209219 break ;
210220 }
211221 }
212- if (preferredStart != -1 && !path .isEmpty ()) {
213- if (path .get (0 ) != preferredStart ) {
214- // find index where preferredStart occurs and rotate
215- int idx = -1 ;
216- for (int i = 0 ; i < path .size (); i ++) {
217- if (path .get (i ) == preferredStart ) {
218- idx = i ;
219- break ;
220- }
221- }
222- if (idx > 0 ) {
223- List <Integer > rotated = new ArrayList <>();
224- for (int i = idx ; i < path .size (); i ++) {
225- rotated .add (path .get (i ));
226- }
227- for (int i = 1 ; i <= idx ; i ++) {
228- rotated .add (path .get (i % path .size ()));
229- }
230- path = rotated ;
231- }
222+
223+ if (preferredStart != -1 && path .get (0 ) != preferredStart ) {
224+ int idx = 0 ;
225+ for (int node : path ) {
226+ if (node == preferredStart ) break ;
227+ idx ++;
228+ }
229+
230+ if (idx > 0 ) {
231+ List <Integer > rotated = new ArrayList <>();
232+ for (int i = idx ; i < path .size (); i ++) rotated .add (path .get (i ));
233+ for (int i = 0 ; i < idx ; i ++) rotated .add (path .get (i ));
234+ path = rotated ;
232235 }
233236 }
234237 }
235-
236238 return path ;
237239 }
238240
@@ -251,17 +253,14 @@ private boolean allNonZeroDegreeVerticesWeaklyConnected(int startNode, int n, in
251253 stack .push (startNode );
252254 visited [startNode ] = true ;
253255
254- // Build undirected adjacency on the fly: for each u -> v, consider u - v
255256 while (!stack .isEmpty ()) {
256257 int u = stack .pop ();
257- // neighbors: outgoing edges
258258 for (int v : graph .getEdges (u )) {
259259 if (!visited [v ]) {
260260 visited [v ] = true ;
261261 stack .push (v );
262262 }
263263 }
264- // neighbors: incoming edges (we must scan all vertices to find incoming edges)
265264 for (int x = 0 ; x < n ; x ++) {
266265 if (!visited [x ]) {
267266 for (int y : graph .getEdges (x )) {
@@ -275,7 +274,6 @@ private boolean allNonZeroDegreeVerticesWeaklyConnected(int startNode, int n, in
275274 }
276275 }
277276
278- // check all vertices with non-zero degree are visited
279277 for (int i = 0 ; i < n ; i ++) {
280278 if (outDegree [i ] + inDegree [i ] > 0 && !visited [i ]) {
281279 return false ;
0 commit comments