查找字符串数组是否可以链接形成一个圆圈 |设置 2
给定一个字符串数组,找出给定的字符串是否可以链接成一个圆圈。如果 X 的最后一个字符与 Y 的第一个字符相同,则一个字符串X 可以放在另一个字符串Y 之前的圆圈中。
例子:
Input: arr[] = {"geek", "king"}
Output: Yes, the given strings can be chained.
Note that the last character of first string is same
as first character of second string and vice versa is
also true.
Input: arr[] = {"for", "geek", "rig", "kaf"}
Output: Yes, the given strings can be chained.
The strings can be chained as "for", "rig", "geek"
and "kaf"
Input: arr[] = {"aab", "bac", "aaa", "cda"}
Output: Yes, the given strings can be chained.
The strings can be chained as "aaa", "aab", "bac"
and "cda"
Input: arr[] = {"aaa", "bbb", "baa", "aab"};
Output: Yes, the given strings can be chained.
The strings can be chained as "aaa", "aab", "bbb"
and "baa"
Input: arr[] = {"aaa"};
Output: Yes
Input: arr[] = {"aaa", "bbb"};
Output: No
Input : arr[] = ["abc", "efg", "cde", "ghi", "ija"]
Output : Yes
These strings can be reordered as, “abc”, “cde”, “efg”,
“ghi”, “ija”
Input : arr[] = [“ijk”, “kji”, “abc”, “cba”]
Output : No
我们强烈建议您单击此处并进行练习,然后再继续使用解决方案。
我们在下面的帖子中讨论了解决这个问题的一种方法。
查找字符串数组是否可以链接形成一个圆圈 |设置 1
在这篇文章中,讨论了另一种方法。我们通过将其视为图问题来解决这个问题,其中顶点将是字符串的第一个和最后一个字符,如果它们是同一字符串的第一个和最后一个字符,我们将在两个顶点之间绘制一条边,所以有图中的边将与数组中的字符串数相同。
下图给出了一些字符串数组的图形表示,
现在可以在图形表示之后清楚地看到,如果图形顶点之间的循环是可能的,那么我们可以对字符串重新排序,否则就不行。如上图示例所示,可以在字符串的第一个和第三个数组中找到循环,但在字符串的第二个数组中找不到循环。现在要检查这个图是否可以有一个遍历所有顶点的循环,我们将检查两个条件,
- 每个顶点的入度和出度应该相同。
- 图应该是强连接的。
第一个条件可以通过保留两个数组来轻松检查,每个字符的输入和输出。检查一个图是否有一个穿过所有顶点的循环与检查完整的有向图是否强连接是一样的,因为如果它有一个穿过所有顶点的循环,那么我们可以从任何其他顶点到达任何顶点也就是说,该图将是强连接的,并且对于反向语句也可以给出相同的参数。
现在为了检查第二个条件,我们将只从任何字符运行 DFS 并从中访问所有可到达的顶点,现在如果图有一个循环,那么在这个 DFS 之后应该访问所有顶点,如果所有顶点都被访问,那么我们将返回true 否则 false 因此访问单个 DFS 中的所有顶点标记字符串之间可能的排序。
C++
// C++ code to check if cyclic order is possible among strings
// under given constraints
#include
using namespace std;
#define M 26
// Utility method for a depth first search among vertices
void dfs(vector g[], int u, vector &visit)
{
visit[u] = true;
for (int i = 0; i < g[u].size(); ++i)
if(!visit[g[u][i]])
dfs(g, g[u][i], visit);
}
// Returns true if all vertices are strongly connected
// i.e. can be made as loop
bool isConnected(vector g[], vector &mark, int s)
{
// Initialize all vertices as not visited
vector visit(M, false);
// perform a dfs from s
dfs(g, s, visit);
// now loop through all characters
for (int i = 0; i < M; i++)
{
/* I character is marked (i.e. it was first or last
character of some string) then it should be
visited in last dfs (as for looping, graph
should be strongly connected) */
if (mark[i] && !visit[i])
return false;
}
// If we reach that means graph is connected
return true;
}
// return true if an order among strings is possible
bool possibleOrderAmongString(string arr[], int N)
{
// Create an empty graph
vector g[M];
// Initialize all vertices as not marked
vector mark(M, false);
// Initialize indegree and outdegree of every
// vertex as 0.
vector in(M, 0), out(M, 0);
// Process all strings one by one
for (int i = 0; i < N; i++)
{
// Find first and last characters
int f = arr[i].front() - 'a';
int l = arr[i].back() - 'a';
// Mark the characters
mark[f] = mark[l] = true;
// increase indegree and outdegree count
in[l]++;
out[f]++;
// Add an edge in graph
g[f].push_back(l);
}
// If for any character indegree is not equal to
// outdegree then ordering is not possible
for (int i = 0; i < M; i++)
if (in[i] != out[i])
return false;
return isConnected(g, mark, arr[0].front() - 'a');
}
// Driver code to test above methods
int main()
{
// string arr[] = {"abc", "efg", "cde", "ghi", "ija"};
string arr[] = {"ab", "bc", "cd", "de", "ed", "da"};
int N = sizeof(arr) / sizeof(arr[0]);
if (possibleOrderAmongString(arr, N) == false)
cout << "Ordering not possible\n";
else
cout << "Ordering is possible\n";
return 0;
}
Java
// Java code to check if cyclic order is
// possible among strings under given constraints
import java.io.*;
import java.util.*;
class GFG{
// Return true if an order among strings is possible
public static boolean possibleOrderAmongString(
String s[], int n)
{
int m = 26;
boolean mark[] = new boolean[m];
int in[] = new int[26];
int out[] = new int[26];
ArrayList<
ArrayList> adj = new ArrayList<
ArrayList>();
for(int i = 0; i < m; i++)
adj.add(new ArrayList<>());
// Process all strings one by one
for(int i = 0; i < n; i++)
{
// Find first and last characters
int f = (int)(s[i].charAt(0) - 'a');
int l = (int)(s[i].charAt(
s[i].length() - 1) - 'a');
// Mark the characters
mark[f] = mark[l] = true;
// Increase indegree and outdegree count
in[l]++;
out[f]++;
// Add an edge in graph
adj.get(f).add(l);
}
// If for any character indegree is not equal to
// outdegree then ordering is not possible
for(int i = 0; i < m; i++)
{
if (in[i] != out[i])
return false;
}
return isConnected(adj, mark,
s[0].charAt(0) - 'a');
}
// Returns true if all vertices are strongly
// connected i.e. can be made as loop
public static boolean isConnected(
ArrayList> adj,
boolean mark[], int src)
{
boolean visited[] = new boolean[26];
// Perform a dfs from src
dfs(adj, visited, src);
for(int i = 0; i < 26; i++)
{
/* I character is marked (i.e. it was first or
last character of some string) then it should
be visited in last dfs (as for looping, graph
should be strongly connected) */
if (mark[i] && !visited[i])
return false;
}
// If we reach that means graph is connected
return true;
}
// Utility method for a depth first
// search among vertices
public static void dfs(ArrayList> adj,
boolean visited[], int src)
{
visited[src] = true;
for(int i = 0; i < adj.get(src).size(); i++)
if (!visited[adj.get(src).get(i)])
dfs(adj, visited, adj.get(src).get(i));
}
// Driver code
public static void main(String[] args)
{
String s[] = { "ab", "bc", "cd", "de", "ed", "da" };
int n = s.length;
if (possibleOrderAmongString(s, n))
System.out.println("Ordering is possible");
else
System.out.println("Ordering is not possible");
}
}
// This code is contributed by parascoding
Python3
# Python3 code to check if
# cyclic order is possible
# among strings under given
# constraints
M = 26
# Utility method for a depth
# first search among vertices
def dfs(g, u, visit):
visit[u] = True
for i in range(len(g[u])):
if(not visit[g[u][i]]):
dfs(g, g[u][i], visit)
# Returns true if all vertices
# are strongly connected i.e.
# can be made as loop
def isConnected(g, mark, s):
# Initialize all vertices
# as not visited
visit = [False for i in range(M)]
# Perform a dfs from s
dfs(g, s, visit)
# Now loop through
# all characters
for i in range(M):
# I character is marked
# (i.e. it was first or last
# character of some string)
# then it should be visited
# in last dfs (as for looping,
# graph should be strongly
# connected) */
if(mark[i] and (not visit[i])):
return False
# If we reach that means
# graph is connected
return True
# return true if an order among
# strings is possible
def possibleOrderAmongString(arr, N):
# Create an empty graph
g = {}
# Initialize all vertices
# as not marked
mark = [False for i in range(M)]
# Initialize indegree and
# outdegree of every
# vertex as 0.
In = [0 for i in range(M)]
out = [0 for i in range(M)]
# Process all strings
# one by one
for i in range(N):
# Find first and last
# characters
f = (ord(arr[i][0]) -
ord('a'))
l = (ord(arr[i][-1]) -
ord('a'))
# Mark the characters
mark[f] = True
mark[l] = True
# Increase indegree
# and outdegree count
In[l] += 1
out[f] += 1
if f not in g:
g[f] = []
# Add an edge in graph
g[f].append(l)
# If for any character
# indegree is not equal to
# outdegree then ordering
# is not possible
for i in range(M):
if(In[i] != out[i]):
return False
return isConnected(g, mark,
ord(arr[0][0]) -
ord('a'))
# Driver code
arr = ["ab", "bc",
"cd", "de",
"ed", "da"]
N = len(arr)
if(possibleOrderAmongString(arr, N) ==
False):
print("Ordering not possible")
else:
print("Ordering is possible")
# This code is contributed by avanitrachhadiya2155
C#
// C# code to check if cyclic order is
// possible among strings under given constraints
using System;
using System.Collections.Generic;
class GFG {
// Return true if an order among strings is possible
static bool possibleOrderAmongString(string[] s, int n)
{
int m = 26;
bool[] mark = new bool[m];
int[] In = new int[26];
int[] Out = new int[26];
List> adj = new List>();
for(int i = 0; i < m; i++)
adj.Add(new List());
// Process all strings one by one
for(int i = 0; i < n; i++)
{
// Find first and last characters
int f = (int)(s[i][0] - 'a');
int l = (int)(s[i][s[i].Length - 1] - 'a');
// Mark the characters
mark[f] = mark[l] = true;
// Increase indegree and outdegree count
In[l]++;
Out[f]++;
// Add an edge in graph
adj[f].Add(l);
}
// If for any character indegree is not equal to
// outdegree then ordering is not possible
for(int i = 0; i < m; i++)
{
if (In[i] != Out[i])
return false;
}
return isConnected(adj, mark,
s[0][0] - 'a');
}
// Returns true if all vertices are strongly
// connected i.e. can be made as loop
public static bool isConnected(
List> adj,
bool[] mark, int src)
{
bool[] visited = new bool[26];
// Perform a dfs from src
dfs(adj, visited, src);
for(int i = 0; i < 26; i++)
{
/* I character is marked (i.e. it was first or
last character of some string) then it should
be visited in last dfs (as for looping, graph
should be strongly connected) */
if (mark[i] && !visited[i])
return false;
}
// If we reach that means graph is connected
return true;
}
// Utility method for a depth first
// search among vertices
public static void dfs(List> adj,
bool[] visited, int src)
{
visited[src] = true;
for(int i = 0; i < adj[src].Count; i++)
if (!visited[adj[src][i]])
dfs(adj, visited, adj[src][i]);
}
static void Main() {
string[] s = { "ab", "bc", "cd", "de", "ed", "da" };
int n = s.Length;
if (possibleOrderAmongString(s, n))
Console.Write("Ordering is possible");
else
Console.Write("Ordering is not possible");
}
}
// This code is contributed by divyesh072019.
Javascript
输出:
Ordering is possible