[英]Find all Non-Prime Paths in a triangle
I'm trying to find routes that do not contain prime numbers in a triangle of integers leading from top to bottom.我试图在从上到下的整数三角形中找到不包含素数的路线。
What is wrong with my code?我的代码有什么问题?
For example ( int[][] input = {{1}, {8, 4}, {2, 6, 9}, {8, 5, 9, 3}}
),例如(
int[][] input = {{1}, {8, 4}, {2, 6, 9}, {8, 5, 9, 3}}
),
1
8 4
2 6 9
8 5 9 3
This triangle has three paths that meet these criteria:这个三角形有三个满足这些标准的路径:
1 - 8 - 6 - 9
1 - 4 - 6 - 9
1 - 4 - 9 - 9
How can I achieve this?我怎样才能做到这一点?
My code:我的代码:
private static void findPaths(int x, int y, int input[][])
{
if(x < input.length - 1)
{
if(!isPrime(input[x + 1][y]) & !isPrime(input[x + 1][y + 1]))
{
System.out.println(input[x + 1][y]);
findPaths(x + 1, y, input);
System.out.println(input[x + 1][y + 1]);
findPaths(x + 1, y + 1, input);
}
else if(!isPrime(input[x + 1][y]))
{
System.out.println(input[x + 1][y]);
findPaths(x + 1, y, input);
}
else if(!isPrime(input[x + 1][y + 1]))
{
System.out.println(input[x + 1][y + 1]);
findPaths(x + 1, y + 1, input);
}
}
}
public static boolean isPrime(int num)
{
if (num <= 1) {return false;}
for (int i = 2; i * i <= num; i++)
{
if ((num % i) == 0) {return false;}
}
return true;
}
Results for findPaths(0, 0, input)
(array input
initialized as shown above): findPaths(0, 0, input)
的结果(数组input
如上所示初始化):
8
6
9
4
6
9
9
9
This problem can be solved by modeling the relationships between the numbers in the given array as a Graph .这个问题可以通过将给定数组中的数字之间的关系建模为Graph来解决。
Note that although the elements form a structure which resembles a Binary Tree .请注意,尽管元素形成了类似于二叉树的结构。 It's certainly not a tree because each node of the tree by definition should have only one parent-node , but here it's not the case (remainder: Tree - is a particularization of a Graph, which has no circles, intersections between brunches and disjointed components).
它当然不是一棵树,因为根据定义,树的每个节点都应该只有一个 parent-node ,但在这里情况并非如此(其余:树 - 是 Graph 的一种特殊化,它没有圆圈、早午餐和不相交的组件之间的交叉点)。
1 <- root element
/ \
8 4 <- level
/ \ / \
2 6 9
/ \ / \ / \
8 5 9 3
Although it's not a tree, for simplicity I would use terminology which is usually used to describe a tree, like root - which the top vertex ( node ) of this tree-like structure and level - which is a group of vertices ( nodes ) having the same depth (distance from the root to a vertex ).虽然它不是一棵树,但为简单起见,我会使用通常用于描述树的术语,如根- 这种树状结构的顶部顶点( node ) 和级别- 它是一组顶点( nodes )相同的深度(从根到顶点的距离)。
And like in a Binary Tree , each element can be represented as a vertex having left and right children.就像在二叉树中一样,每个元素都可以表示为具有左右子节点的顶点。
To find all non-prime paths in a graph starting from the root , we need to traverse over the graph .要在图中从根开始找到所有非主路径,我们需要遍历图。 Each path would be represented as a separate
List
, ie every non-prime child of a non-prime vertex should spawn a new path .每条路径都将表示为一个单独的
List
,即非素数顶点的每个非素数子节点都应生成一条新路径。 And every encountered prime vertex would cause the path that leads to it to be discarded.并且每个遇到的素数顶点都会导致通往它的路径被丢弃。
To traverse the implement the graph , I've implemented Depth first search algorithm using recursion (because it's relatively easier to digest).为了遍历实现图,我使用递归实现了深度优先搜索算法(因为它相对更容易消化)。
We would have two base cases (conditions when recursion should terminate):我们将有两种基本情况(递归应该终止的条件):
And in case if current vertex has a non-prime value, and it doesn't belong to the last level (ie it has children), we need to fire the depth first search recursively for both left
and right
child-vertices .如果当前顶点有一个非质数,并且它不属于最后一层(即它有孩子),我们需要
right
left
顶点递归地触发深度优先搜索。 That would be the recursive case of the algorithm.那将是算法的递归情况。
Note: to avoid shifting the focus from the main goal of finding non-prime paths in the Graph to checking whether a particular value is a prime number, I've used built-in method BigInteger.isProbablePrime()
which expects an int
argument certainty , denoting the probability of getting correct result according to the formula 1-1/2 certainty .
注意:为了避免将焦点从在图中查找非素数路径的主要目标转移到检查特定值是否为素数,我使用了内置方法
BigInteger.isProbablePrime()
,它需要一个int
参数确定性, 表示根据公式1-1/2确定性得到正确结果的概率。 You're free to replace this check with any other logic.您可以随意用任何其他逻辑替换此检查。
Implementation might look like this:实现可能如下所示:
public class NonPrimeTriangle {
private final Vertex root;
private NonPrimeTriangle(Vertex root) {
this.root = root;
}
public List<List<Integer>> getNonPrimePaths() {
List<List<Integer>> paths = new ArrayList<>();
dfs(paths, new ArrayList<>(), root);
return paths;
}
private void dfs(List<List<Integer>> paths, List<Integer> path, Vertex root) {
if (BigInteger.valueOf(root.getValue()).isProbablePrime(100)) return; // base case - a prime number has been encountered, hence this path is invalidated
path.add(root.getValue()); // vertex is proved to be non-prime and should be added to the path
if (root.hasNoChildren()) { // base case - a non-prime path has been encountered found
paths.add(path);
return;
}
// recursive case
dfs(paths, new ArrayList<>(path), root.getLeft());
dfs(paths, new ArrayList<>(path), root.getRight());
}
// Not a part of the Algorithm - convenience-method for parsing the given Array into a Graph
public static NonPrimeTriangle parse(int[][] arr) {
if (arr.length == 0 || arr[0].length == 0) throw new IllegalArgumentException();
Vertex root = new Vertex(arr[0][0]);
NonPrimeTriangle triangle = new NonPrimeTriangle(root);
List<Vertex> prevLevel = List.of(root);
for (int row = 1; row < arr.length; row++) {
List<Vertex> nextLevel = new ArrayList<>(prevLevel.size() + 1); // next level of Vertices
for (int col = 0; col < arr[row].length; col++) {
Vertex newVertex = new Vertex(arr[row][col]);
// every vertex has two parents, except for the leftmost and the rightmost which have only one and the root which has none
if (col != 0) prevLevel.get(col - 1).setRight(newVertex);
if (col != prevLevel.size()) prevLevel.get(col).setLeft(newVertex);
nextLevel.add(newVertex); // updating the next level of Vertices
}
prevLevel = nextLevel;
}
return triangle;
}
public static class Vertex {
private final int value;
private Vertex left;
private Vertex right;
public Vertex(int value) {
this.value = value;
}
public boolean hasNoChildren() {
return left == null && right == null;
}
// getters & setters
}
}
main()
public static void main(String[] args) {
int[][] input = {{1}, {8, 4}, {2, 6, 9}, {8, 5, 9, 3}};
NonPrimeTriangle triangle = NonPrimeTriangle.parse(input);
triangle.getNonPrimePaths().forEach(System.out::println);
}
Output: Output:
[1, 8, 6, 9]
[1, 4, 6, 9]
[1, 4, 9, 9]
Alternative approach (don't miss comments in code):替代方法(不要错过代码中的注释):
private static void traverseNonPrimalAndPrintPaths(int row, int col, int[][] arr, String curPath){
int curNum = arr[row][col];
if (!isPrime(curNum)) {//we only want to handle non-prime values
//lets add value we are in to current path
if (row == 0){//first value shouldn't have "-" before it
curPath = String.valueOf(curNum);
} else {//later values need to also add "-" before them in path
curPath = curPath + "-" + curNum;
}
//If there are rows below check left and right "node" below current node
if (row < arr.length-1){//we are NOT in last row
traverseNonPrimalAndPrintPaths(row+1, col, arr, curPath);//check left node
traverseNonPrimalAndPrintPaths(row+1, col+1, arr, curPath);//check right node
} else {//here we know there are no more rows.
//So we all we need to do is print path we took to get here.
System.out.println(curPath);
}
}
}
Demo:演示:
int[][] input1 = {{1}, {8, 4}, {2, 6, 9}, {8, 5, 9, 3}};
traverseNonPrimalAndPrintPaths(0, 0, input1,"");
Output: Output:
1-8-6-9
1-4-6-9
1-4-9-9
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.