Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/381.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何优化此算法以处理大整数?_Java_Algorithm_Optimization - Fatal编程技术网

Java 如何优化此算法以处理大整数?

Java 如何优化此算法以处理大整数?,java,algorithm,optimization,Java,Algorithm,Optimization,我有两个整数x和y 规则: 如果x>y:x=x-y,y=2*y 如果y>x:y=y-x,x=2*x 如果y==x:非无限循环 问题是,这两个整数是不是一个无限循环 这是我的密码: private static boolean IsPairLoop(int first, int second) { boolean loop = false; HashMap<Integer, Integer> round_record = new HashMap<>();

我有两个整数x和y

规则:

  • 如果x>y:x=x-y,y=2*y
  • 如果y>x:y=y-x,x=2*x
  • 如果y==x:非无限循环
  • 问题是,这两个整数是不是一个无限循环

    这是我的密码:

    private static boolean IsPairLoop(int first, int second)
    {
        boolean loop = false;
        HashMap<Integer, Integer> round_record = new HashMap<>();
        int[] first_round = new int[]{first, second};
    
        while ((first_round[0] != -1 && first_round[1] != -1))
        {
            if (round_record.containsKey(first_round[0]))
            {
                loop = true;
                break;
            }
            round_record.put(first_round[0], first_round[1]);
            PlayRound(first_round);
        }
        return loop;
    }
    
    private static void PlayRound(int[] round)
    {
        if (round[0] > round[1])
        {
    
           round[0] -= round[1];
           round[1] += round[1];
    
        }
        else if (round[0] < round[1])
        {
    
           round[1] -= round[0];
           round[0] += round[0];
    
        }
        else
        {
            round[0]  = -1;
            round[1]  = -1;
        }
    }
    
    private静态布尔IsPairLoop(int-first,int-second)
    {
    布尔循环=假;
    HashMap round_record=新HashMap();
    int[]first_round=新int[]{first,second};
    while((第一轮[0]!=-1和第一轮[1]!=-1))
    {
    if(第一轮[0])(第二轮记录.containsKey)
    {
    循环=真;
    打破
    }
    第一轮记录。put(第一轮[0],第一轮[1]);
    游戏回合(第一轮);
    }
    回路;
    }
    专用静态无效播放回合(int[]回合)
    {
    if(第[0]轮>第[1]轮)
    {
    轮[0]=轮[1];
    轮[1]+=轮[1];
    }
    else if(第[0]轮<第[1]轮)
    {
    轮[1]=轮[0];
    四舍五入[0]+=四舍五入[0];
    }
    其他的
    {
    四舍五入[0]=-1;
    四舍五入[1]=-1;
    }
    }
    

    这适用于小整数。然而,当整数差真的很大时,这是非常缓慢的。x和y的整数范围均为1到2^30。即使在整数差很大的情况下,我该怎么做才能使这个速度更快?

    使用Floyd的循环检测算法,而不是使用hashmap。这不仅可以避免大量内存使用,还可以避免在
    int
    Integer
    之间进行昂贵的装箱和拆箱

    第二个优化是通过变量的变化重新写入递推关系:

    s = x+y
    t = x-y
    
    然后递归关系变成:

    if t=0, stop
    if t>0, s'=s, t'=2t-s
    if t<0, s'=s, t'=2t+s
    
    如果
    first+second
    可能溢出,您可能需要将
    int
    替换为
    long


    我认为,给定前提条件,你永远不会得到一个无限大的
    t
    (因为
    |t |
    总是正确的)。但是您可能希望进行双重检查,也许可以在代码中添加某种断言。

    使用Floyd的循环检测算法,而不是使用hashmap。这不仅可以避免大量内存使用,还可以避免在
    int
    Integer
    之间进行昂贵的装箱和拆箱

    第二个优化是通过变量的变化重新写入递推关系:

    s = x+y
    t = x-y
    
    然后递归关系变成:

    if t=0, stop
    if t>0, s'=s, t'=2t-s
    if t<0, s'=s, t'=2t+s
    
    如果
    first+second
    可能溢出,您可能需要将
    int
    替换为
    long


    我认为,给定前提条件,你永远不会得到一个无限大的
    t
    (因为
    |t |
    总是正确的)。但是,您可能希望进行双重检查,或许可以在代码中添加某种断言。

    让我们向后看一看。什么能产生x==y?前一个x和y之间的差值必须等于两者中较小者的两倍,即较大者必须是较小者的三倍。到目前为止没有无限循环的事物:

    • {n,n}
    • {n,3n}
    {n,3n}从哪里来?或者

    • n是不同的a− b对于某些a>b,且3n=2b
      3(a)− b) =2b
      3a− 3b=2b
      3a=5b
      a=5/3 b

      一对{m,5/3m}是在下一步产生{n,3n}的东西。(m必须能被3整除,但这没关系。)

    • 3n是一种差异a− 对于某些a>b,n=2b
      (一)− b) /3=2b
      A.− b=6b
      a=7b

      一对{m,7m}是下一步唯一能产生{n,3n}的东西

    最新名单:

    • {n,n}
    • {n,3n}
    • {n,7n}
    • {n,5/3 n}
    似乎是概括这些最后步骤的好时机

    {n,qn}发生在以下情况:

    • n是不同的a− 对于某些a>b,且qn=2b
      q(a)− b) =2b
      质量保证− qb=2b
      qa=(2+q)b
      a=(2+q)/qb

    • 或者qn是一个不同点− 对于某些a>b,n=2b
      (一)− b) /q=2b
      A.− b=2qb
      a=(2q+1)b

    因此,如果q=m/n在列表中,这些也在列表中:

    • (2n+m)/m
    • (2m+n)/n
    q=1生成:

    • (2+1)/1=3
    • 2×1+1=3
    q=3产生:

    • 三,
    • (2+3)/3=5/3
    • 2×3+1=7
    q=5/3产生:

    • 三,
    • 5/3
    • 七,
    • (2+5/3)/(5/3)=(6+5)/5=11/5
    • (2×5/3)+1=10/3+1=13/3
    q=7生成:

    • 三,
    • 5/3
    • 七,
    • 11/5
    • 13/3
    • (2+7)/7=9/7
    • 2×7+1=15
    嗯……那很有趣。让我们按分子对列表进行排序:

    • 3/1
    • 5/3
    • 7/1
    • 9/7
    • 11/5
    • 13/3
    • 15/1
    基于这种模式,我预计接下来将是17/15。使用计算机生成按分母排序的列表:

    3/1
    7/1
    15/1
    31/1
    63/1
    5/3
    13/3
    29/3
    61/3
    11/5
    27/5
    59/5
    9/7
    25/7
    57/7
    23/9
    55/9
    21/11
    53/11
    19/13
    51/13
    17/15
    49/15
    47/17
    45/19
    43/21
    41/23
    39/25
    37/27
    35/29
    33/31
    
    看起来非常像m/n,其中n是奇数,m>n,m+n是2的幂。因此,优化算法的一种方法是:

    private static boolean isPairLoop(int first, int second)
    {
        if (first == second) return false;
        if (first > second) return isPairLoop(second, first);
        if (first == 0) return true;
    
        int d = gcd(first, second);
        return Integer.bitCount(first / d + second / d) != 1;
    }
    
    private static int gcd(int a, int b)
    {
        return b == 0 ? a : gcd(b, a % b);
    }
    
    在bigint上的位数上花费二次时间


    现在你只需要证明它是有效的。我希望它能起作用。

    让我们倒过来看看。什么能产生x==y?前一个x和y之间的差值必须等于两者中较小者的两倍,即较大者必须是较小者的三倍。到目前为止没有无限循环的事物:

    • {n,n}
    • {n,3n}
    {n,3n}从哪里来?或者

    • n是不同的a− b对于某些a>b,且3n=2b
      3(a)− b) =2b
      3a− 3b=2b
      3a=5b
      a=5/3 b

      一对{m,5/3m}是在下一步产生{n,3n}的东西。(m必须能被3整除,但这没关系。)