【发布时间】:2021-02-02 21:51:13
【问题描述】:
编写函数,给定一个整数 N,返回整数数组 1..N 以某种方式排列,因此每 2 个连续数字的总和是一个平方。
当且仅当满足以下两个条件时,解决方案才有效:
1..N 范围内的每个数字都使用一次且仅一次。
每两个连续数之和是一个完美平方(根平方)。
结果是按照上述规则按特定顺序排列的 1-n 个数字的列表!!!
示例 对于 N=15,解决方案可能如下所示:
[9、7、2、14、11、5、4、12、13、3、6、10、15、1、8]
检查-
16 16 16 16 16 16 16
/+\ /+\ /+\ /+\ /+\ /+\ /+\
[ 9, 7, 2, 14, 11, 5, 4, 12, 13, 3, 6, 10, 15, 1, 8 ]
\+/ \+/ \+/ \+/ \+/ \+/ \+/
9 25 9 25 9 25 9
9 = 3*3
16 = 4*4
25 = 5*5
length of the returned list is n=15 and uses numbers from 1-n(15)
如果没有解,返回null 例如如果 N=5,则数字 1,2,3,4,5 不能放入平方和行:1+3=4, 4+5=9,但是 2 没有对,不能链接 [1,3 ] 和 [4,5]。
解决方案列表返回必须使用不超过 n 的数字,并且长度必须等于 n
我的解决方案是使用递归方法,这是我的尝试:
import java.util.*;
public class SquareSums {
public static List<Integer> gg= new ArrayList<Integer>() ;
public static List<Integer> buildUpTo(int n) {
int checkCurrent=1,firstInList=1;
while(checkCurrent<=n+1){
boolean[] flag= new boolean[n+1];
List<Integer> l= new ArrayList<Integer>();
l=checker(n,checkCurrent,l,1,flag,firstInList, true);//n, prev, list, current, flag
checkCurrent++;
if(l.size()==n) {System.out.println("true "+ n);return l;}
}
return null;
}
public static List<Integer> checker(int num, int current,List<Integer> l,int prev, boolean[] flag,int k, boolean one){
if(l.size()==num) {return l;}
else if(prev>num+1 || current>num) {return l;}
if(one) {
flag[current]=true;
l.add(current);print(l);
l=checker(num,1,l,current,flag,1,false);
}
flag[prev]=true;
System.out.println("check if square root: "+" num1: "+prev+ " num2: "+current+" sum is: "+(prev+current)+" sqrt: "+Math.sqrt(prev+current)+ " sqrt int: "+Math.floor(Math.sqrt(prev+current)));
if(current<flag.length &&!flag[current] && Math.sqrt(prev+current)==Math.floor(Math.sqrt(prev+current))) {
l.add(current);print(l);
l=checker(num,1,l,current,flag,1,false);
}
else {
print(l);
l=checker(num,k++,l,prev,flag,k,false);
}
return l;
}
public static void main(String[] args) {
List<Integer> l= buildUpTo(15);
print(l);
}
static void print(List<Integer> l) {
System.out.println(" -------------------- ");
for(int i=0;i<l.size();i++) {
System.out.println(l.get(i));
}
System.out.println(" --------------------- ");
System.out.println(" ");
System.out.println(" ");
}
}
我如何解决/修复代码以使其正常工作(使用递归方法&没有流?)?
这里是测试代码:
import org.junit.Test;
import org.junit.runners.JUnit4;
import java.util.List;
public class Tests {
@Test
public void sampleTests() {
List.of(5,15,16,23,37).forEach(Check::isGood);
}
}
编辑:
然后在下面发布的代码解决方案的帮助下,我对此进行了一些编辑,但它仍然无法正常工作。
public class SquareSums {
public static List<Integer> gg= new ArrayList<Integer>() ;
public static List<Integer> buildUpTo(int n) {
int checkCurrent=1;
while(checkCurrent<=n+1){
List<Integer> l=checker(n,checkCurrent,new ArrayList<Integer>(),1,new boolean[n+1],1);//n, prev, list, current, flag
checkCurrent++;
if(l.size()==n) {System.out.println("true "+ n);return l;}
}
return gg;
}
static boolean checkPerfectSquare(double x)
{
double sq = Math.sqrt(x);
return ((sq - Math.floor(sq)) == 0);
}
public static List<Integer> checker(int num, int current,List<Integer> l,int prev, boolean[] flag,int k){
if(l.size()==num) {return l;}
else if(prev>num+1 || current>num) {return l;}
if(l.size()==0) {
flag[current]=true;
l.add(current);System.out.println(l);
l=checker(num,1,l,current,flag,1);
}
flag[prev]=true;
if(current<flag.length &&!flag[current] && checkPerfectSquare(prev+current)) {
l.add(current);System.out.println(l);
l=checker(num,1,l,current,flag,1);
l.remove(l.size()-1);
flag[l.size()-1]=false;
}
else {
System.out.println(l);
l=checker(num,k++,l,prev,flag,k);
}
return l;
}
public static void main(String[] args) {
List<Integer> l= buildUpTo(15);
System.out.println("\n"+"Answer is: ");
System.out.println(" -------------------- ");
System.out.println(l);
System.out.println(" -------------------- ");
}
}
我运行了代码,当我在示例 n=15 上运行它时,它假设返回一个以 9 开头的列表,在我的调试器上/在 9 上打印它打印
[9, 7, 2, 14, 11, 5, 4, 12, 13, 3, **1, 8**]
而预期的实际结果是:(不是我的代码,n=15时的真正解决方案)
[9, 7, 2, 14, 11, 5, 4, 12, 13, 3, **6, 10, 15, 1, 8**]
如果我们仔细观察,我们会发现我的代码哪里出错了。似乎我需要在递归中添加一些东西来尝试每个选项。我该怎么做?
【问题讨论】: