【问题标题】:Binary string remainder 3二进制字符串余数 3
【发布时间】:2013-11-14 13:13:10
【问题描述】:

-当x是二进制数时如何找到x mod 3?不允许先转十进制再用%运算符。

-eg- 如果 x 为 1101,则输出应为 1 但不要将 1101 转换为 13 然后按 % 3 查找

【问题讨论】:

    标签: algorithm bit-manipulation modular-arithmetic


    【解决方案1】:

    既然你说的是“字符串”,我将添加以下技巧:

    请注意,如果您在二进制数的末尾附加0,则会将其值加倍。如果在末尾附加1,则将其加倍并加1。

    也就是说,如果你已经处理了直到某个数字的所有数字(调用这个数字直到那个数字a),并且你知道a % 3 = x对于一些x=1, 2 or 0,那么你可以告诉以下内容:

    a0 % 3 = (2 * a) % 3 = ((2 % 3) * (a % 3)) % 3 = (2 * (a % 3)) % 3
    a1 % 3 = (2 * a + 1) % 3 = ((2 % 3) * (a % 3) + (1 % 3)) % 3 = (2 * (a % 3) + 1) % 3
    

    这样,您可以轻松做出以下区分:

    Current mod | Next digit | New mod
    ------------+------------+---------
       0            0            0
       0            1            1
       1            0            2
       1            1            0
       2            0            1
       2            1            2
    

    也就是说,您可以从左到右遍历您的字符串(假设 msbf 表示法)并根据表格更新new mod。你从current mod = 0开始。

    【讨论】:

      【解决方案2】:

      它非常快速和创新。

      二进制中的 3 是 11,即以 10 为底的 11。所以我们知道一个数可以被 11 整除,如果奇数位的数字之和与其偶数位的数字之和之差为 0 或可整除到 11 点。

      所以添加偶数的1s 和奇数的1。拿差价。请检查下面的程序,我们正在做同样的事情。如果你有相同的字符串也适用。

      public static boolean isDivisible(int n){
          if(n<0){
              n=-n;
          }
          if(n==0)return true;
          if(n==1)return false;
          int even=0, odd=0;
          while(n!=0){
              if((n&1)==1){
                  odd++;
              }
              n=n>>1;
              if(n==0)break;
              if((n&1)==1){
                  even++;
              }
          }
          return isDivisible(even-odd);
      }
      

      更多信息你可以关注thisthis

      【讨论】:

      • 您能否简要解释一下为什么可以使用 11 可除性规则(以 10 为底)来确定二进制的 3 可除性?
      • 因为 3 只不过是二进制的 11。您计算的流将其视为以 10 为底的数字。您清除了吗?
      【解决方案3】:

      如果您注意到2^N mod 3 = 2 if N is odd &amp; 2^N mod 3 = 1 if N is even(可以通过归纳法证明)而且二进制否是 2 的幂和,那么只需检查 1 是否以奇数或偶数幂出现在字符串中,并对这些值进行运行总和。模算术中有定理为

      (a+b+c)%m = ((a)%m + (b)%m + (c)%m )%m
      

      例如。

      x = 1101 有 2 个偶数次方 (2^0,2^2) 和 1 个奇数次方 2 (2^3)

      因此 res = (2*1 + 2 )mod 3 = 4 mod 3 = 1

      Java 实现:-

      public class Modulus {
      
          public static int modulo3(String s) {
      
              int end = s.length()-1;
              int sum = 0;
              for(int i =0;i<s.length();i++) {
      
                 if(s.charAt(end)=='1') {
                     if(i%2==0)
                         sum = sum + 1;
                     else sum = sum + 2;
                 } 
      
                 end--; 
              }
             return(sum%3); 
          }
      
      
          public static void main(String[] args) {
      
              System.out.println(modulo3("1110"));
          }
      
      }
      

      【讨论】:

        【解决方案4】:

        A % B 等价于 A - (floor(A/B) * B)。如果您可以对二进制数执行减法、乘法和整数除法,则无需实际使用即可模拟% 运算符。

        【讨论】:

          【解决方案5】:

          要判断一个十进制数是否能以 10 为基数被 9 整除,只需将其数字相加并重复直到只有一个数字。如果该数字是 0、3、6 或 9,则它可以被 9 整除。

          这基于相同的原理,但对于在基数 4 中可被 3 整除的数字:

          int mod3 (int x) {
            if (x<0) x = -x;
            while (x & 0x7fff0000) x = ((x & 0x7fff0000)>>16) + (x & 0x0000ffff);
            while (x & 0xff00) x = ((x & 0xff00)>>8) + (x & 0x00ff);
            while (x & 0xf0) x = ((x & 0xf0)>>4) + (x & 0x0f);
            while (x & 0x0c) x = ((x & 0x0c)>>2) + (x & 0x03);
            while (x>=3) x -= 3;
            return x;
          }
          

          【讨论】:

            【解决方案6】:

            这里的概念是,如果您在任何二进制数的末尾添加 0 或 1,则数字将加倍加 0 或 1 基于是否设置下一个位,并且提醒也将变为 [previous_reminder*2 + (0 或 1) ]。 并在这一步之后计算提醒:提醒=提醒%3;

            这里是java代码:

            public static void main(String[] args) {
                int[] arr = { 1, 1, 0, 1, 1, 0, 0, 1, 1, 1};
                // Assumed first bit is always set therefore reminder will be 1.
                int reminder = 1;
            
                for (int i = 1; i < arr.length; i++) {
                    reminder = reminder * 2 + arr[i];
                    reminder = reminder % 3;
                }
                System.out.println(reminder);
            }
            

            【讨论】:

              猜你喜欢
              • 2017-08-08
              • 1970-01-01
              • 2011-02-16
              • 2011-07-11
              • 1970-01-01
              • 2021-11-09
              • 2017-03-22
              • 2016-02-26
              • 1970-01-01
              相关资源
              最近更新 更多