我试图在Java中提出一种算法,当给定一串数字时,可以识别符合以下条件的整数组合
where:
N is the Nth element in the string or element at Nth position;
N1 is the (N-1) element in the string & N2 is the (N-2) element in the string.
Example 1: 224610
Elements in this string are 2, 2, 4, 6, 10.
First Set: 2+2=4 (N2=2; N1=2 & N= 4);
Second Set: 2+4=6 (N2=2; N1=4 & N=6);
Third Set: 4+6=10 (N2=4; N1=6 & N= 10)
Example 2: 11112233558
Elements in this string are 1, 11, 12, 23, 35, 58
Example 3: 1101102203
Elements in this string are 1, 101, 102, 203.
我已经编写了一个函数,可以获取整数的ArrayList,并告诉你该数组是否符合要求。
public static boolean complies(ArrayList<Integer> al)
{
boolean result = true;
int alsize = al.size();
for (int n = alsize-1; n > 1; n--)
{
int N1 = al.get(n-1);
int N2 = al.get(n-2);
int N = al.get(n);
if (N != ( N1 + N2))
result = false;
if ((N < N1) || (N1 < N2))
result = false;
}
return(result);
}
我正在努力寻找一种优雅的方法来识别我可以运行上述函数的所有可能的整数组合。
答案 0 :(得分:0)
我想到了你问的问题,本质上是如何按照给出数字的顺序找到一组数字的所有组合,并意识到这可以递归地解决。您所要做的就是将第一个数字添加到可以使用其余数字组成的所有组合中,并将该数字放在所有组合的第一个项目之前。基本情况是只有一个数字,这意味着当然只有一个组合。
让我举个例子。首先我们用数字123找到23的所有组合,因为23有一个以上的数字,我们找到3的所有组合,这只是3.然后在该组合中加2,使2,3和2放在前面这个组合的第一个术语,即23,现在为所有组合增加1,分别为1,2,3和1,23,并在第一个术语前面放1个,分别为12,3和123.
所以我用这个方法找到了所有的组合。它返回一个二维arrayList,每个arrayList都是唯一的组合。前提条件是你必须只给它一串数字而不是空字符串。如果我犯了错误,或者它没有为您的应用程序工作说些什么。我很确定你可以通过二维arrayList检查每个arrayList是否在你的布尔方法中工作。你可以测试它here。
public ArrayList<ArrayList<Integer>> findCombos(String input)
{
ArrayList<ArrayList<Integer>> answer = new ArrayList<ArrayList<Integer>>();
if(input.length()==1)
{
ArrayList<Integer> combo = new ArrayList<Integer>();
answer.add(combo);
combo.add(Integer.parseInt(input)); //this method converts from a string to an int
return answer;
}
else
{
answer = findCombos(input.substring(1));
int size = answer.size(); //you need to save this because when you add things to an arrayList the size changes
for(int i=0;i<size;i++) //this copies the arrayList back to itself
{
ArrayList<Integer> copy = new ArrayList<Integer>(answer.get(i));
answer.add(copy);
}
int digit = (char)(input.charAt(0)-'0');//this saves the current digit
for(int i=0;i<size;i++)//this adds the digit in front of all the previous combos
answer.get(i).add(0, digit);
for(int i=size;i<answer.size();i++)//this puts the digit in front of the first term of the previous combos
{
String copy = "" + answer.get(i).get(0);//I just did this to find the length of the first term easily
int append = (int)(digit*Math.pow(10, copy.length()));
answer.get(i).set(0, append+answer.get(i).get(0));
}
return answer;
}
}
答案 1 :(得分:0)
下面的代码适用于所有3个输入,并且足够稳定。
public class IntFinder
{
/**
* @param args the command line arguments
*/
private static String given = "444444889321420";
static N1N2 temp = new N1N2(given);
public static void main(String[] args) {
// TODO code application logic here
N1N2 n1 = new N1N2(given);
N1N2 n2 = new N1N2(given);
/*IntFinder.setGiven("224610");
n1 = new N(IntFinder.getGiven());
n2 = new N(IntFinder.getGiven());
n1.setValue(0, 0); // 2
n2.setValue(1, 1); // 2*/
/*IntFinder.setGiven("11112233558");
n1 = new N(IntFinder.getGiven());
n2 = new N(IntFinder.getGiven());
n1.setValue(0, 0); // 1
n2.setValue(1, 2); // 11*/
IntFinder.setGiven("1101102203");
n1 = new N1N2(IntFinder.getGiven());
n2 = new N1N2(IntFinder.getGiven());
n1.setValue(0, 0); // 1
n2.setValue(1, 3); // 101
System.out.println("string: " + n1.getValue());
System.out.println("string: " + n2.getValue());
System.out.println("result: " + ((IntFinder.findTillEndByN1N2(n1, n2) > -1) ? "found" : "NOT found"));
}
public static String setGiven(String givenString)
{
return IntFinder.given = givenString;
}
public static String getGiven()
{
return IntFinder.given;
}
public static int findTillEndByN1N2(N1N2 n1, N1N2 n2)
{
int retVal = -1, lenChange = n1.getLength() + n2.getLength() + n1.getStartIndex();
retVal = findNagainstN1N2(n1, n2, lenChange);
if (IntFinder.getGiven().length() == (n2.getEndIndex() + 1)) // base case 1 (last digit reached)
{
return 1;
}
else if (IntFinder.getGiven().length() < (n2.getEndIndex() + 1))
{
System.out.println("fatal err:");
System.exit(0);
}
if (retVal > -1) // recurse till end
{
if (!temp.getUsed())
{
temp = IntFinder.shallowCopy(n1);
temp.setUsed(true);
}
n1 = IntFinder.shallowCopy(n2);
n2.setValue(n2.getEndIndex() + 1 , retVal);
System.out.println("string: "+n2.getValue());
retVal = findTillEndByN1N2(n1, n2);
}
else
return retVal;
return retVal;
}
public static Integer findNagainstN1N2(N1N2 n1, N1N2 n2, Integer startIndex)
{
String remainingGiven = IntFinder.getGiven().substring(startIndex);
Integer i, n1n2Total = 0, retVal = -1;
n1n2Total = n1.getValue() + n2.getValue();
for (i = 0; i < remainingGiven.length(); i++)
{
try
{
int found = Integer.parseInt(remainingGiven.substring(0, (i+1)));
if (found == n1n2Total)
{
retVal = startIndex + i;
break;
}
else if (found > n1n2Total)
{
retVal = -1;
break;
}
}
catch (NumberFormatException e)
{
;
}
}
return retVal;
}
public static N1N2 shallowCopy(N1N2 from) {
N1N2 newN = new N1N2(IntFinder.getGiven());
newN.setValue(from.getStartIndex(), from.getEndIndex());
return newN;
}
}
>>N1N2.class
public class N1N2 {
private String givenString;
private int startIndex = 0;
private int endIndex = -1;
private int value = 0;
private int length = endIndex + 1;
private Boolean used = false;
public N1N2(String given) {
startIndex = 0;
endIndex = given.length() - 1;
givenString = given;
}
public int getValue() {
return value;
}
public int getLength() {
return length;
}
public Boolean getUsed()
{
return used;
}
public void setUsed(Boolean used)
{
this.used = used;
}
// public void outValues()
// {
// System.out.println("given:" + givenString + ", startIndex:"+ startIndex + ", endIndex: " + endIndex + ", length:" + length + ", value:" + value + "\n");
// }
public void setValue(int startIndex, int endIndex) {
this.value = Integer.parseInt(givenString.substring(startIndex, endIndex + 1));
this.startIndex = startIndex;
this.endIndex = endIndex;
this.length = (this.value + "").length();
// this.outValues();
}
public int getEndIndex() {
return this.endIndex;
}
public int getStartIndex() {
return this.startIndex;
}
}
在调用IntFinder.findTillEndByN1N2(n1,n2)之前,只需正确设置n1和n2。
观察我使用的例子。
因此,要完成程序,请使用两个循环填充
创建自己的算法n1.setValues和n2.setValues
实施例。
given = 1232447
//first loop
n1.setValues(0,0) // value = 1
n2.setValues(1,1) // value = 2
IntFinder.findTillEndByN1N2(n1, n2) // returns -1 // not found...
//next loop - increment n2 length
n1.setValues(0,0) // value = 1
n2.setValues(1,2) // value = 23
IntFinder.findTillEndByN1N2(n1, n2) // returns 1 // now found till end.
//ofcourse when n2 reached the last digit, increment n1 length by 1 and set n2 length back to 1.
//for given=444444889321420 // 44 444 488 932 1420
//all findTillEnd with n1 length 1 should fail so inc n1 length on outer loop
//n1.setValue(0, 1) // 2 digit number ( 44)
//n2.setValue(0, 0) // 4
//upon continuing loop, the desired result will be met.
答案 2 :(得分:0)
根据Pham的上述解决方案,我可以修改代码以排除边缘情况并为上述问题创建解决方案。如果符合模式,则此方法将始终返回true,否则我们必须找到前两个元素使它工作。检查所有测试用例:
public static boolean complies(String input){
// List<Long> firstTwo = new ArrayList<Long>();
for(int i = 1; i < input.length(); i++){
for(int j = 0; j < i; j++){
long first = Long.parseLong(input.substring(0, j + 1));//substring form 0 to j
long second = Long.parseLong(input.substring(j + 1, i + 1));//substring from j + 1 to i
if(second < first)
continue;
String last = "" + first + second;
System.out.println("first :"+first+" second :"+second);
if(last.length() == input.length()){
return false;
}
// firstTwo.add(first);
// firstTwo.add(second);
while(last.length() < input.length()){
long nxt = first + second;
last += nxt;
first = second;
second = nxt;
}
if(last.equals(input)){//Matched!
System.out.println("matched");
// dont go further return true
return true;
}
// firstTwo.clear();
}
}
return false;
}