使用递归将数字转换为不同的数字

时间:2011-05-27 20:34:53

标签: java algorithm recursion

我正在尝试为以下任务制作算法:

  • 我有两个整数a≤b
  • 算法必须通过添加1并乘以2运算将 a 转换为 b 。例如,如果 a = 5且 b = 23,程序应输出类似23 =((5 * 2 + 1)* 2 + 1)
  • 我必须使用递归

我已经多次使用Google搜索,但我能找到的只是关于如何转换矩阵,如何进行几何变换,如何将字符串转换为另一个字符串以及类似内容的想法。

有人有什么想法吗?

7 个答案:

答案 0 :(得分:3)

这是使用最小数量操作找到转换的方法:

(编辑:添加括号)

public static void main (String [] args)
{
    int a = 5, b = 23;
    System.out.println (transform (a, b) + " = " + b);
}

public static String transform (int a, int b)
{
    if (a == b) return "" + a;
    if (b % 2 == 0 && 2 * a <= b)
    {
        b = b / 2;
        return transform (a, b) + " * 2";
    }
    else
    {
        b = b - 1;
        return "(" + transform (a, b) + " + 1)";
    }
}

答案 1 :(得分:2)

以下方法对我有用:我想:

int transform(int a, int b) {
   if (a>= b)
      return a;
   else if (a*2 <= b)
      return transform(2*a, b);
   else
      return transform(a + 1, b);
}

答案 2 :(得分:2)

这实际上打印了它,但它可能不是你想要的我不确定。

private static String doDo(int a, int b, StringBuilder sb) {
    if (a == b) {
      String ret = sb.toString();
      int charCount = ret.replaceAll("[^)]", "").length();
      for (int i = 0; i < charCount; i++)
        ret = "(" + ret;
      return ret;
    }
    if (a < (b/2f)) {
      sb.append(")*2+1");
      return doDo(a*2 + 1, b, sb);
    } else {
      sb.append("+1");
      return doDo(a+1, b, sb);
    }
  }

System.out.println(doDo(5, 23, new StringBuilder().append("5")));

打印 - &gt; ((5)*2+1)*2+1

答案 3 :(得分:1)

这里有一些你可以使用的伪代码

transform(a, b)
start
   if a >= b
       return
   else
     print formatted progress 
     transform(a * 2 + 1, b)
end

答案 4 :(得分:1)

如果您不想过度拍摄,请使用此版本(@ anubhava解决方案的修改版本)。

int transform(int a, int b) {
   if (a >= b){
      return a;
   } else {
      int c = a*2 + 1;
      if (c>b){
          return a;
      } else {
          return transform(c, b);
      }
  }
}

答案 5 :(得分:1)

这是一个使用递归来确定在最少数量的操作中进行转换的最佳策略的版本。我假设你每次加倍,就算作一次操作;每次添加1时,计为一次操作,目标是最小化操作总数。

在5&gt; 23示例中对其进行测试得出:

((((5)*2)+1)*2)+1=23

你可能对语法更加苛刻,但希望有点冗长有助于显示代码的意图。

当我使用他关于如何进行字符串格式化的想法时,给了josh.trow提示。

import java.util.ArrayList;
import java.util.List;

public class DoubleAndAddAlgorithm {
    public enum Op {
        DOUBLE, ADD_ONE
    }

    private static List<Op> getOptimalTransform(int a, int b) throws IllegalArgumentException {
        // Returns the list of operations that comprises the optimal way to get from a to b

        // If a is already bigger than b, we have a problem
        if (a > b) {
            throw new IllegalArgumentException("a cannot be greater than b");
        }

        List<Op> result = new ArrayList<Op>();

        // If we can get there in one operation, do so
        if (2*a == b) {
            result.add(Op.DOUBLE);
        } else if (a+1 == b) {
            result.add(Op.ADD_ONE);
        }

        // If doubling would cause us to overshoot, all we can do is add 1
        // and take it from there...
        else if (2*a > b) {
            result.add(Op.ADD_ONE);
            result.addAll(getOptimalTransform(a+1, b));
        }

        // Otherwise, let's try doubling, and let's try adding one, and use
        // recursion to see which gets us to the target quicker
        else {
            List<Op> trialResultDouble = getOptimalTransform(2*a, b);
            List<Op> trialResultAddOne = getOptimalTransform(a+1, b);

            // Let's say (arbitrarily), that if neither operation results in us
            // getting to the target any quicker than the other, we choose to add 1
            if (trialResultDouble.size() < trialResultAddOne.size()) {
                result.add(Op.DOUBLE);
                result.addAll(trialResultDouble);
            } else {
                result.add(Op.ADD_ONE);
                result.addAll(trialResultAddOne);
            }
        }
        return result;
    }

    public static String getFormattedResult(int a, int b) {
        try {
            List<Op> ops = getOptimalTransform(a, b);

            StringBuilder sb = new StringBuilder();
            sb.append(Integer.toString(a));

            for (Op op: ops) {
                if (op == Op.DOUBLE) {
                    sb.insert(0, "(");
                    sb.append(")*2");
                } else if (op == Op.ADD_ONE) {
                    sb.insert(0, "(");
                    sb.append(")+1");
                }
            }

            sb.append("=");
            sb.append(Integer.toString(b));

            return sb.toString();
        } catch (IllegalArgumentException e) {
            return "Illegal arguments supplied";
        }
    }

    public static void main(String[] args) {
        System.out.println( getFormattedResult(5, 23) );
    }
}

答案 6 :(得分:0)

搜索名为double&amp; add的算法,它是square&amp; multip one的双重...我很抱歉,但我不知道细节。