【问题标题】:Find all integers in a string of digits which meet a criteria查找一串数字中满足条件的所有整数
【发布时间】:2015-05-18 01:22:16
【问题描述】:

我正在尝试在 Java 中提出一种算法,当给定一串数字时,它可以识别满足以下条件的整数组合

  • N = N1 + N2
  • N >= N1 >= N2
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.

我已经写了一个函数,它可以接受一个整数数组列表,并告诉你数组是否符合要求。

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);
}

我正在努力寻找一种优雅的方法来识别我可以通过上述函数运行的所有可能的整数组合。

【问题讨论】:

  • @AdrianLeonhard 我不会说这是重复的......因为对于这种情况有提出新想法的空间,但仍然是一个很好的参考!
  • 两个问题:您是否希望整个列表符合要求,或者列表的某些部分是否符合规则。另外,您给出的示例是升序列表,是否必须如此? (如果第一个问题的答案是整个列表,我想这意味着是)
  • 由于整数是数字(非负数),如果 n = n1 + n2 则 n >= n1 且 n >= n2。所以你只需要检查 n = n1 + n2 和 n1 >= n2。
  • @snickers10m 是的,整个列表需要满足要求,是的,它必须是升序列表才能满足您指出的第二个要求。

标签: java string algorithm


【解决方案1】:

我想到了你问的问题,本质上是如何按照给定数字的顺序找到一组数字的所有组合,并意识到这可以递归解决。您所要做的就是将第一个数字添加到可以与其余数字组成的所有组合中,并将该数字放在所有组合的第一项前面。基本情况是只有一位数字,这意味着当然只有一种组合。

让我举个例子。首先使用数字 123,我们找到 23 的所有组合,并且由于 23 有多个数字,我们找到 3 的所有组合,即 3。然后将 2 添加到该组合中,即 2、3 并将 2 放在前面该组合的第一项,即 23。现在将 1 添加到所有组合,即 1、2、3 和 1、23,并将 1 放在第一项的前面,即 12、3 和 123。

所以我做了这个方法来找到所有的组合。它返回一个二维数组列表,其中每个单独的数组列表都是唯一的组合。前提条件是您必须只给它一个数字字符串,而不是空字符串。如果我犯了一个错误或者它对您的应用程序不起作用,请说些什么。我很确定你可以通过二维 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;
    }
}

【讨论】:

    【解决方案2】:

    下面的代码适用于所有 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.
    

    【讨论】:

      【解决方案3】:

      根据 Pham 的上述解决方案,我可以修改代码以排除边缘情况并为上述问题创建一个解决方案。如果它符合模式,则此方法将始终返回 true,否则为 false,是的,我们必须找到使其工作的前两个元素。检查所有测试用例:

      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;
      }
      

      【讨论】:

        猜你喜欢
        • 2021-11-18
        • 2016-04-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-01-22
        相关资源
        最近更新 更多