Given a array arr[] of n integers. For every value arr[i], we can move to arr[i] + 1 clockwise
considering array elements in cycle. We need to count cyclic elements in the array. An element is cyclic if starting from it and moving to arr[i] + 1 leads to same element.
Examples:
Input : arr[] = {1, 1, 1, 1} Output : 4 All 4 elements are cyclic elements. 1 -> 3 -> 1 2 -> 4 -> 2 3 -> 1 -> 3 4 -> 2 -> 4 Input : arr[] = {3, 0, 0, 0} Output : 1 There is one cyclic point 1, 1 -> 1 The path covered starting from 2 is 2 -> 3 -> 4 -> 1 -> 1. The path covered starting from 3 is 2 -> 3 -> 4 -> 1 -> 1. The path covered starting from 4 is 4 -> 1 -> 1
One simple solution is to check all elements one by one. We follow simple path starting from every element arr[i], we go to arr[i] + 1. If we come back to a visited element other than arr[i], we do not count arr[i]. Time complexity of this solution is O(n2)
An efficient solution is based on below steps.
1) Create a directed graph using array indexes as nodes. We add an edge from i to node (arr[i] + 1)%n.
2) Once a graph is created we find all strongly connected components using Kosaraju’s Algorithm
3) We finally return sum of counts of nodes in individual strongly connected component.
C++
// C++ program to count cyclic points // in an array using Kosaraju's Algorithm #include <bits/stdc++.h> using namespace std; // Most of the code is taken from below link class Graph { int V; list< int >* adj; void fillOrder( int v, bool visited[], stack< int >& Stack); int DFSUtil( int v, bool visited[]); public : Graph( int V); void addEdge( int v, int w); int countSCCNodes(); Graph getTranspose(); }; Graph::Graph( int V) { this ->V = V; adj = new list< int >[V]; } // Counts number of nodes reachable // from v int Graph::DFSUtil( int v, bool visited[]) { visited[v] = true ; int ans = 1; list< int >::iterator i; for (i = adj[v].begin(); i != adj[v].end(); ++i) if (!visited[*i]) ans += DFSUtil(*i, visited); return ans; } Graph Graph::getTranspose() { Graph g(V); for ( int v = 0; v < V; v++) { list< int >::iterator i; for (i = adj[v].begin(); i != adj[v].end(); ++i) g.adj[*i].push_back(v); } return g; } void Graph::addEdge( int v, int w) { adj[v].push_back(w); } void Graph::fillOrder( int v, bool visited[], stack< int >& Stack) { visited[v] = true ; list< int >::iterator i; for (i = adj[v].begin(); i != adj[v].end(); ++i) if (!visited[*i]) fillOrder(*i, visited, Stack); Stack.push(v); } // This function mainly returns total count of // nodes in individual SCCs using Kosaraju's // algorithm. int Graph::countSCCNodes() { int res = 0; stack< int > Stack; bool * visited = new bool [V]; for ( int i = 0; i < V; i++) visited[i] = false ; for ( int i = 0; i < V; i++) if (visited[i] == false ) fillOrder(i, visited, Stack); Graph gr = getTranspose(); for ( int i = 0; i < V; i++) visited[i] = false ; while (Stack.empty() == false ) { int v = Stack.top(); Stack.pop(); if (visited[v] == false ) { int ans = gr.DFSUtil(v, visited); if (ans > 1) res += ans; } } return res; } // Returns count of cyclic elements in arr[] int countCyclic( int arr[], int n) { int res = 0; // Create a graph of array elements Graph g(n + 1); for ( int i = 1; i <= n; i++) { int x = arr[i-1]; // If i + arr[i-1] jumps beyond last // element, we take mod considering // cyclic array int v = (x + i) % n + 1; // If there is a self loop, we // increment count of cyclic points. if (i == v) res++; g.addEdge(i, v); } // Add nodes of strongly connected components // of size more than 1. res += g.countSCCNodes(); return res; } // Driver code int main() { int arr[] = {1, 1, 1, 1}; int n = sizeof (arr)/ sizeof (arr[0]); cout << countCyclic(arr, n); return 0; } |
Java
// Python3 program to count cyclic points // in an array using Kosaraju's Algorithm // Counts number of nodes reachable // from v import java.io.*; import java.util.*; class GFG { static boolean [] visited = new boolean [ 100 ]; static Stack<Integer> stack = new Stack<Integer>(); static ArrayList<ArrayList<Integer>> adj = new ArrayList<ArrayList<Integer>>(); static int DFSUtil( int v) { visited[v] = true ; int ans = 1 ; for ( int i: adj.get(v)) { if (!visited[i]) { ans += DFSUtil(i); } } return ans; } static void getTranspose() { for ( int v = 0 ; v < 5 ; v++) { for ( int i : adj.get(v)) { adj.get(i).add(v); } } } static void addEdge( int v, int w) { adj.get(v).add(w); } static void fillOrder( int v) { visited[v] = true ; for ( int i: adj.get(v)) { if (!visited[i]) { fillOrder(i); } } stack.add(v); } // This function mainly returns total count of // nodes in individual SCCs using Kosaraju's // algorithm. static int countSCCNodes() { int res = 0 ; // stack<int> Stack; // bool* visited = new bool[V]; for ( int i = 0 ; i < 5 ; i++) { if (visited[i] == false ) { fillOrder(i); } } getTranspose(); for ( int i = 0 ; i < 5 ; i++) { visited[i] = false ; } while (stack.size() > 0 ) { int v = stack.get(stack.size() - 1 ); stack.remove(stack.size() - 1 ); if (visited[v] == false ) { int ans = DFSUtil(v); if (ans > 1 ) { res += ans; } } } return res; } // Returns count of cyclic elements in arr[] static int countCyclic( int [] arr, int n) { int res = 0 ; // Create a graph of array elements for ( int i = 1 ; i < n + 1 ; i++) { int x = arr[i - 1 ]; // If i + arr[i-1] jumps beyond last // element, we take mod considering // cyclic array int v = (x + i) % n + 1 ; // If there is a self loop, we // increment count of cyclic points. if (i == v) res++; addEdge(i, v); } // Add nodes of strongly connected components // of size more than 1. res += countSCCNodes(); return res; } // Driver code public static void main (String[] args) { int arr[] = { 1 , 1 , 1 , 1 }; int n = arr.length; for ( int i = 0 ; i < 100 ; i++) { adj.add( new ArrayList<Integer>()); } System.out.println(countCyclic(arr, n)); } } // This code is contributed by avanitrachhadiya2155 |
Python3
# Python3 program to count cyclic points # in an array using Kosaraju's Algorithm # Counts number of nodes reachable # from v def DFSUtil(v): global visited, adj visited[v] = True ans = 1 for i in adj[v]: if ( not visited[i]): ans + = DFSUtil(i) return ans def getTranspose(): global visited, adj for v in range ( 5 ): for i in adj[v]: adj[i].append(v) def addEdge(v, w): global visited, adj adj[v].append(w) def fillOrder(v): global Stack, adj, visited visited[v] = True for i in adj[v]: if ( not visited[i]): fillOrder(i) Stack.append(v) # This function mainly returns total count of # nodes in individual SCCs using Kosaraju's # algorithm. def countSCCNodes(): global adj, visited, S res = 0 #stack<int> Stack; #bool* visited = new bool[V]; for i in range ( 5 ): if (visited[i] = = False ): fillOrder(i) getTranspose() for i in range ( 5 ): visited[i] = False while ( len (Stack) > 0 ): v = Stack[ - 1 ] del Stack[ - 1 ] if (visited[v] = = False ): ans = DFSUtil(v) if (ans > 1 ): res + = ans return res # Returns count of cyclic elements in arr[] def countCyclic(arr, n): global adj res = 0 # Create a graph of array elements for i in range ( 1 , n + 1 ): x = arr[i - 1 ] # If i + arr[i-1] jumps beyond last # element, we take mod considering # cyclic array v = (x + i) % n + 1 # If there is a self loop, we # increment count of cyclic points. if (i = = v): res + = 1 addEdge(i, v) # Add nodes of strongly connected components # of size more than 1. res + = countSCCNodes() return res # Driver code if __name__ = = '__main__' : adj = [[] for i in range ( 100 )] visited = [ False for i in range ( 100 )] arr = [ 1 , 1 , 1 , 1 ] Stack = [] n = len (arr) print (countCyclic(arr, n)) # This code is contributed by mohit kumar 29 |
C#
// C# program to count cyclic points // in an array using Kosaraju's Algorithm // Counts number of nodes reachable // from v using System; using System.Collections.Generic; public class GFG { static bool [] visited = new bool [100]; static List< int > stack = new List< int >(); static List<List< int >> adj = new List<List< int >>(); static int DFSUtil( int v) { visited[v] = true ; int ans = 1; foreach ( int i in adj[v]) { if (!visited[i]) { ans += DFSUtil(i); } } return ans; } static void getTranspose() { for ( int v = 0; v < 5; v++) { foreach ( int i in adj[v]) { adj[i].Add(v); } } } static void addEdge( int v, int w) { adj[v].Add(w); } static void fillOrder( int v) { visited[v] = true ; foreach ( int i in adj[v]) { if (!visited[i]) { fillOrder(i); } } stack.Add(v); } // This function mainly returns total count of // nodes in individual SCCs using Kosaraju's // algorithm. static int countSCCNodes() { int res = 0; // stack<int> Stack; // bool* visited = new bool[V]; for ( int i = 0; i < 5; i++) { if (visited[i] == false ) { fillOrder(i); } } getTranspose(); for ( int i = 0; i < 5; i++) { visited[i] = false ; } while (stack.Count > 0) { int v=stack[stack.Count - 1]; stack.Remove(stack.Count - 1); if (visited[v] == false ) { int ans = DFSUtil(v); if (ans > 1) { res += ans; } } } return res; } // Returns count of cyclic elements in arr[] static int countCyclic( int [] arr, int n) { int res = 0; // Create a graph of array elements for ( int i = 1; i < n + 1; i++) { int x = arr[i - 1]; // If i + arr[i-1] jumps beyond last // element, we take mod considering //cyclic array int v = (x + i) % n + 1; // If there is a self loop, we // increment count of cyclic points. if (i == v) res++; addEdge(i, v); } // Add nodes of strongly connected components // of size more than 1. res += countSCCNodes(); return res; } // Driver code static public void Main () { int [] arr = {1, 1, 1, 1}; int n = arr.Length; for ( int i = 0; i < 100; i++) { adj.Add( new List< int >()); } Console.WriteLine(countCyclic(arr, n)); } } // This code is contributed by rag2127 |
Output:
4
Time Complexity : O(n)
Auxiliary space : O(n) Note that there are only O(n) edges.
This article is contributed by Mohak Agrawal. If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.
Please write comments if you find anything incorrect, or you want to share more information about the topic discussed above.
Attention reader! Don’t stop learning now. Get hold of all the important DSA concepts with the DSA Self Paced Course at a student-friendly price and become industry ready.