给定一个包含N个整数的数组A ,任务是根据以下条件计算组成数组中一个循环的元素数。
开始从索引i遍历Array,并跳转到下一个连接的索引。如果j = GCD(i,A [i])%N,则有向边从A的索引i退出到索引j 。如果以所描述的顺序遍历数组,则再次访问索引i,然后称索引i在数组中形成一个循环。
例子:
Input: A = { 1, 1, 6, 2 }
Output: 2
Explanation:
Possible traversals with the given condition are:
0 -> 1 -> 1
1 -> 1
2 -> 2
3 -> 2 -> 2
Clearly, only vertices 1 and 2 forms a cycle.
Input: A = {0, 0, 0, 6}
Output: 4
Explanation:
Possible traversals with the given condition are:
0 -> 0
1 -> 1
2 -> 2
3 -> 3
Clearly, all the vertices forms a cycle.
方法:
为了解决上述问题,我们必须假设每个索引代表图的单个节点。
- 如果j = GCD(i,A [i])%n,则每个节点都有一个从A的索引i到索引j的有向边。如果遍历从节点i开始。
- 节点i将被称为该遍历的父节点,并且该父节点将被分配给遍历过程中访问的所有节点。
- 在遍历图形时,如果我们发现一个已经访问过的节点,并且该访问的节点的父节点与遍历的父节点相同,则将检测到一个新的周期。
- 现在,将在此循环中的每个节点都形成循环时对其进行计数。要计算此循环中的节点数,请从该节点启动另一个DFS,直到不再访问同一节点为止。
- 对图的每个节点i重复此过程。
在最坏的情况下,每个节点最多将遍历3次。因此,解决方案具有线性时间复杂度。
下面是上述方法的实现:
C++
// C++ program to number of elements
// which form a cycle in an array
#include
using namespace std;
#define mp make_pair
#define pb push_back
#define mod 1000000007
// Function to count number of
// elements forming a cycle
int solve(int A[], int n)
{
int i, cnt = 0, j;
// Array to store parent
// node of traversal.
int parent[n];
// Array to determine
// whether current node
// is already counted
// in the cycle.
int vis[n];
// Initialize the arrays.
memset(parent, -1, sizeof(parent));
memset(vis, 0, sizeof(vis));
for (i = 0; i < n; i++) {
j = i;
// Check if current node is already
// traversed or not. If node is not
// traversed yet then parent value
// will be -1.
if (parent[j] == -1) {
// Traverse the graph until an
// already visited node is not
// found.
while (parent[j] == -1) {
parent[j] = i;
j = __gcd(j, A[j]) % n;
}
// Check parent value to ensure
// a cycle is present.
if (parent[j] == i) {
// Count number of nodes in
// the cycle.
while (!vis[j]) {
vis[j] = 1;
cnt++;
j = __gcd(j, A[j]) % n;
}
}
}
}
return cnt;
}
int main()
{
int A[] = { 1, 1, 6, 2 };
int n = sizeof(A) / sizeof(A[0]);
cout << solve(A, n);
return 0;
}
Java
// Java program to number of elements
// which form a cycle in an array
import java.util.*;
class GFG{
static final int mod = 1000000007;
// Function to count number of
// elements forming a cycle
static int solve(int A[], int n)
{
int i, cnt = 0, j;
// Array to store parent
// node of traversal.
int []parent = new int[n];
// Array to determine
// whether current node
// is already counted
// in the cycle.
int []vis = new int[n];
// Initialize the arrays.
Arrays.fill(parent, -1);
Arrays.fill(vis, 0);
for(i = 0; i < n; i++)
{
j = i;
// Check if current node is already
// traversed or not. If node is not
// traversed yet then parent value
// will be -1.
if (parent[j] == -1)
{
// Traverse the graph until an
// already visited node is not
// found.
while (parent[j] == -1)
{
parent[j] = i;
j = __gcd(j, A[j]) % n;
}
// Check parent value to ensure
// a cycle is present.
if (parent[j] == i)
{
// Count number of nodes in
// the cycle.
while (vis[j] == 0)
{
vis[j] = 1;
cnt++;
j = __gcd(j, A[j]) % n;
}
}
}
}
return cnt;
}
static int __gcd(int a, int b)
{
return b == 0 ? a : __gcd(b, a % b);
}
// Driver code
public static void main(String[] args)
{
int A[] = { 1, 1, 6, 2 };
int n = A.length;
System.out.print(solve(A, n));
}
}
// This code is contributed by gauravrajput1
Python3
# Python3 program to number of elements
# which form a cycle in an array
import math
mod = 1000000007
# Function to count number of
# elements forming a cycle
def solve(A, n):
cnt = 0
# Array to store parent
# node of traversal.
parent = [-1] * n
# Array to determine
# whether current node
# is already counted
# in the cycle.
vis = [0] * n
for i in range(n):
j = i
# Check if current node is already
# traversed or not. If node is not
# traversed yet then parent value
# will be -1.
if (parent[j] == -1):
# Traverse the graph until an
# already visited node is not
# found.
while (parent[j] == -1):
parent[j] = i
j = math.gcd(j, A[j]) % n
# Check parent value to ensure
# a cycle is present.
if (parent[j] == i):
# Count number of nodes in
# the cycle.
while (vis[j] == 0):
vis[j] = 1
cnt += 1
j = math.gcd(j, A[j]) % n
return cnt
# Driver code
A = [ 1, 1, 6, 2 ]
n = len(A)
print(solve(A, n))
# This code is contributed by sanjoy_62
C#
// C# program to number of elements
// which form a cycle in an array
using System;
class GFG{
// Function to count number of
// elements forming a cycle
static int solve(int[] A, int n)
{
int i, cnt = 0, j;
// Array to store parent
// node of traversal.
int[] parent = new int[n];
// Array to determine
// whether current node
// is already counted
// in the cycle.
int[] vis = new int[n];
// Initialize the arrays.
Array.Fill(parent, -1);
Array.Fill(vis, 0);
for(i = 0; i < n; i++)
{
j = i;
// Check if current node is already
// traversed or not. If node is not
// traversed yet then parent value
// will be -1.
if (parent[j] == -1)
{
// Traverse the graph until an
// already visited node is not
// found.
while (parent[j] == -1)
{
parent[j] = i;
j = __gcd(j, A[j]) % n;
}
// Check parent value to ensure
// a cycle is present.
if (parent[j] == i)
{
// Count number of nodes in
// the cycle.
while (vis[j] == 0)
{
vis[j] = 1;
cnt++;
j = __gcd(j, A[j]) % n;
}
}
}
}
return cnt;
}
static int __gcd(int a, int b)
{
return b == 0 ? a : __gcd(b, a % b);
}
// Driver code
static void Main()
{
int[] A = { 1, 1, 6, 2 };
int n = A.Length;
Console.WriteLine(solve(A, n));
}
}
// This code is contributed by divyeshrabadiya07
输出:
2
时间复杂度: O(N)
空间复杂度: O(N)