能否成环
题目描述
Description
Given an array of strings A[ ], determine if the strings can be chained together to form a circle. A string X can be chained together with another string Y if the last character of X is same as first character of Y. If every string of the array can be chained, it will form a circle. For example, for the array arr[] = {“for”, “geek”, “rig”, “kaf”} the answer will be Yes as the given strings can be chained as “for”, “rig”, “geek” and “kaf”.
Input
The first line of input contains an integer T denoting the number of test cases. Then T test cases follow.
The first line of each test case contains a positive integer N, denoting the size of the array.
The second line of each test case contains a N space seprated strings, denoting the elements of the array A[ ].
1 <= T
0 < N
0 < A[i]
Output
If chain can be formed, then print 1, else print 0.
Sample Input 1
2
3
abc bcd cdf
4
ab bc cd da
Sample Output 1
0
1
题目解析
任意选择一个字符串数组中的元素,并按照首尾字母是否相同将元素首尾相连,如果可以刚刚好形成一个环则返回1,否则返回0
测试用例
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
注意:
- 有单独一个字符串成环的情况
- 也有局部成环的情况
- 多个环连接在一起的情况
对于以上几点注意分别有几种常见的错误思路
错误思路:
-
统计首尾字符数量
对首尾字符的数量进行分别统计,若每个字符的开头数量等于结尾数量则认为满足条件,对于可以单独成环的如"a",“b”,单独做判断
错误原因,无法判别出局部成环的情况,如[“ijk”, “kji”, “abc”, “cba”]
错误代码
from collections import defaultdict if __name__ == '__main__': for _ in range(int(input())): _ = int(input()) arr = input().strip().split(" ") dict1 = defaultdict(lambda: [0, 0]) # 默认值设为0 key_set = set() # 创建一个set,收集单独成环的字符 for x in arr: # 统计每个字符的开头结尾的数量 if x[0] == x[-1]: key_set.add(x[0]) else: dict1[x[0]][0] += 1 dict1[x[-1]][-1] += 1 if len(dict1) == 0 and len(key_set) == 1: # 若只有一个重复的 a print(1) else: if key_set.issubset(dict1.keys()): # 若单独成环的字符全都出现过 for k, v in dict1.items(): if v[0] != v[1]: print(0) break else: print(1) else: print(0)
-
用两个list遍历
list1储存输入数组,list2储存结果,每次从list1中取出一个元素放入list2中,并继续在list1中寻找符合开头字母等于上一个放进去的元素结尾字母的元素,直到列表为空或者无法选择为止.但这种方法也有问题,具体问题如下
如:l = [“axb”, “bxc”, “cxd”, “dxa”, “dxe”, “exd”] 和l =[“axb”, “bxc”, “cxd”, “dxe”, “dxa”, “exd”]
同样的字符序列,如果采用这种方法会得到不同的结果
错误代码
注意:这里代码虽然错误,但依然可以AC,因为用例是不全面的.使用两个list的时,重点在 target_char = res_l[-1][-1]这行,一定要写到for循环里面则正好符合了用例输出,否则不对
这种思路一定是有问题的,只是可以ACif __name__ == '__main__': for _ in range(int(input())): _ = int(input()) l = input().strip().split(" ") # l = ["axb", "bxc", "cxd", "dxa", "dxe", "exd"] res_l = l[0:1] l = l[1:] flag = True while len(l) > 0 and flag: flag = False for x in l: target_char = res_l[-1][-1] # 每次寻找最后一个字符串的最后一个字符 if x[0] == target_char: res_l.append(x) l.remove(x) flag = True if flag and res_l[0][0] == res_l[-1][-1]: # 如果数组的第一个字符等于最后一个字符,就成环了,否则就是链 print(1) else: print(0)
思路解析
-
这道题的正确方法是使用图的结构
如果存在欧拉回路,则可以形成链,否则不能。
注意,有向图只有在每个顶点的入度和出度相同时才具有欧拉回路,并且所有非零度顶点都形成一个强连通分量。
下面是算法的详细步骤。
1)创建顶点数等于字母表大小的有向图g。我们在下面的程序中创建了一个有26个顶点的图。
2)对给定字符串数组中的每个字符串执行以下操作。
……a)在给定图形的第一个字符到最后一个字符之间添加一条边。
3)如果创建的图具有欧拉回路,则返回true,否则返回false。
这里什么欧拉回路我也没看懂
代码实现
Java
import java.util.*;
class Main {
public static void main(String[] args) {
Scanner s = new Scanner(System.in);
int t = s.nextInt();
s.nextLine();
while (t-- > 0) {
int n = Integer.parseInt(s.nextLine());
String[] str = s.nextLine().trim().split(" ");
Graph g = new Graph(26);
for (int i = 0; i < str.length; i++) {
char start = str[i].charAt(0);
char end = str[i].charAt(str[i].length() - 1);
g.addEdge(start - 'a', end - 'a');
}
boolean res = g.isEulerian();
if (res) {
System.out.println(1);
} else {
System.out.println(0);
}
}
}
}
class Graph {
ArrayList<ArrayList<Integer>> list = new ArrayList<>();
int[] count = new int[26];
int V;
Graph(int v) {
this.V = v;
for (int i = 0; i < v; i++) {
list.add(new ArrayList<Integer>());
}
}
public void addEdge(int i, int j) {
ArrayList<Integer> temp = list.get(i);
temp.add(j);
list.add(temp);
count[j]++;
}
public boolean isEulerian() {
if (!isSc()) {
return false;
}
for (int i = 0; i < V; i++) {
if (list.get(i).size() != count[i]) {
return false;
}
}
return true;
}
public boolean isSc() {
boolean[] visited = new boolean[V];
for (int i = 0; i < V; i++) {
visited[i] = false;
}
int i = 0;
int start = 0;
for (i = 0; i < V; i++) {
if (list.get(i).size() > 0) {
start = i;
break;
}
}
DFS(visited, start);
for (i = 0; i < V; i++) {
if (list.get(i).size() > 0 && !visited[i]) {
return false;
}
}
Graph gr = getTranspose();
for (i = 0; i < V; i++) {
visited[i] = false;
}
gr.DFS(visited, start);
for (i = 0; i < V; i++) {
if (list.get(i).size() > 0 && !visited[i]) {
return false;
}
}
return true;
}
public Graph getTranspose() {
Graph gr = new Graph(V);
for (int i = 0; i < V; i++) {
ArrayList<Integer> temp = list.get(i);
for (int j = 0; j < temp.size(); j++) {
gr.addEdge(temp.get(j), i);
}
}
return gr;
}
public void DFS(boolean[] visited, int n) {
visited[n] = true;
for (int i = 0; i < list.get(n).size(); i++) {
int node = list.get(n).get(i);
if (!visited[node]) {
DFS(visited, node);
}
}
}
}
python
from collections import defaultdict
def dfs(graph, start, visited, stack):
visited.add(start)
for node in graph[start]:
if node not in visited:
dfs(graph, node, visited, stack)
stack.append(start)
def reverse_graph(graph):
edges = []
for k, val in graph.items():
for node in val:
edges.append((k, node))
rev = defaultdict(list)
for u, v in edges:
rev[v].append(u)
return rev
def dfs_r(graph, start, visited, store):
visited.add(start)
store.append(start)
for node in graph[start]:
if node not in visited:
dfs(graph, node, visited, store)
def kosaraju(graph, n):
visited = set()
stack = []
for i in range(n):
if i not in visited:
dfs(graph, i, visited, stack)
rev = reverse_graph(graph)
visited = set()
out = []
while stack:
node = stack.pop()
temp = []
if node not in visited:
dfs_r(rev, node, visited, temp)
out.append(temp)
return out
T = int(input())
for _ in range(T):
n = int(input())
arr = input().strip().split(' ')
if n == 1:
st = arr[0]
if st[0] == st[-1]:
print(1)
else:
print(0)
else:
graph = defaultdict(list)
for i in range(n):
for j in range(n):
if i == j:
continue
if arr[i][-1] == arr[j][0]:
graph[i].append(j)
scc = kosaraju(graph, n)
if len(scc) == 1:
print(1)
else:
print(0)