⭐️前面的话⭐️
本篇文章介绍【1073. 负二进制数相加】题解,算法标签:【数学】,【思维】,【模拟算术】,展示语言c++/java。
📒博客主页:未见花闻的博客主页
🎉欢迎关注🔎点赞👍收藏⭐️留言📝
📌本文由未见花闻原创,CSDN首发!
📆首发时间:🌴2022年5月18日(于19日补发)🌴
✉️坚持和努力一定能换来诗与远方!
💭推荐书籍:📚《算法》,📚《算法导论》
💬参考在线编程网站:🌐牛客网🌐力扣
博主的码云gitee,平常博主写的程序代码都在里面。
博主的github,平常博主写的程序代码都在里面。
🍭作者水平很有限,如果发现错误,一定要及时告知作者哦!感谢感谢!
📌导航小助手📌
- ⭐️1073. 负二进制数相加⭐️
- 🔐题目详情
- 💡解题思路
- 🔑源代码
 
- 🌱总结

⭐️1073. 负二进制数相加⭐️
🔐题目详情
1073. 负二进制数相加
难度中等
给出基数为 -2 的两个数 arr1 和 arr2,返回两数相加的结果。
数字以 数组形式 给出:数组由若干 0 和 1 组成,按最高有效位到最低有效位的顺序排列。例如,arr = [1,1,0,1] 表示数字 (-2)^3 + (-2)^2 + (-2)^0 = -3。数组形式 中的数字 arr 也同样不含前导零:即 arr == [0] 或 arr[0] == 1。
返回相同表示形式的 arr1 和 arr2 相加的结果。两数的表示形式为:不含前导零、由若干 0 和 1 组成的数组。
示例 1:
输入:arr1 = [1,1,1,1,1], arr2 = [1,0,1]
输出:[1,0,0,0,0]
解释:arr1 表示 11,arr2 表示 5,输出表示 16 。
示例 2:
输入:arr1 = [0], arr2 = [0]
输出:[0]
示例 3:
输入:arr1 = [0], arr2 = [1]
输出:[1]
提示:
- 1 <= arr1.length, arr2.length <= 1000
- arr1[i]和- arr2[i]都是- 0或- 1
- arr1和- arr2都没有前导0
💡解题思路
解题思路
思路1:最简单的方案就是,将数转换为十进制,进行计算后,将得到的结果转换为二级制数组,但是数组长度最大为  
     
      
       
       
         1000 
        
       
      
        1000 
       
      
    1000,必然会爆int,因此该方案不可取。
思路2:模拟加减计算,我们可以先将两个数组对应相加,得到一个新数组,新数组长度大于原来俩数组中最大长度 
     
      
       
       
         10 
        
       
      
        10 
       
      
    10个大小肯定够了,进位也不可能进10位。
加减计算后,由于原来数组只有0或1,进行加法后,可能取值为0,1,-1,因为是基础权重是负数,由于相邻的俩位,是少乘以一个负数的关系,所以相邻位正负号一定相反,所以当需要进位时,其实就是在前一位减去对应的进位权重即可,如当前位为2,则可进位,进位本质上就是加上 
     
      
       
       
         2 
        
       
         × 
        
       
         ( 
        
       
         − 
        
       
         2 
        
        
        
          ) 
         
        
          x 
         
        
       
         = 
        
       
         − 
        
       
         ( 
        
       
         − 
        
       
         2 
        
        
        
          ) 
         
         
         
           x 
          
         
           + 
          
         
           1 
          
         
        
       
      
        2 \times(-2)^{x}=-(-2)^{x+1} 
       
      
    2×(−2)x=−(−2)x+1,即在前一位需要减去1,由于“减位”机制的存在,数组取值可能还会出现-1。
那如果当前位取值为-1时,如何处理呢?其实我们不难列出如下一个等式:
  
      
       
        
        
          ( 
         
        
          − 
         
        
          1 
         
        
          ) 
         
        
          × 
         
        
          ( 
         
        
          − 
         
        
          2 
         
         
         
           ) 
          
         
           x 
          
         
        
          = 
         
        
          ( 
         
        
          − 
         
        
          2 
         
         
         
           ) 
          
         
           x 
          
         
        
          + 
         
        
          ( 
         
        
          − 
         
        
          2 
         
         
         
           ) 
          
          
          
            x 
           
          
            + 
           
          
            1 
           
          
         
        
       
         (-1) \times(-2)^{x}=(-2)^{x}+(-2)^{x+1} 
        
       
     (−1)×(−2)x=(−2)x+(−2)x+1
 因此我们只需将该位处理成 
     
      
       
       
         1 
        
       
      
        1 
       
      
    1,前一位加上 
     
      
       
       
         1 
        
       
      
        1 
       
      
    1即可。在这里会将前一位加上 
     
      
       
       
         1 
        
       
      
        1 
       
      
    1,因此数组可能取值又多了3。
综上所述,数组取值可能为-1,0,1,2,3,处理情况如下:
- 数组元素大于1,将前一位减去1,当前位取2的模。
- 数组元素为1或0,无需处理。
- 数组元素为-1,将当前位处理为1,前一位加1。
🔑源代码
C++代码:
class Solution 
{
public:
    vector<int> addNegabinary(vector<int>& arr1, vector<int>& arr2) 
    {
        //第一步,统一调整数组,使得第一个数组长度更加大
        int size1 = arr1.size();
        int size2 = arr2.size();
    
        if (size2 > size1) 
        {
            vector<int> tmp(arr1);
            arr1 = arr2;
            arr2 = tmp;
        } 
        size1 = arr1.size();
        size2 = arr2.size();
        //第二步,进行两个数组的加减法
        int cur1 = size1 - 1;
        int cur2 = size2 - 1;
        vector<int> sum(size1 + 10);
        int i = sum.size() - 1;
        while (cur2 >= 0) sum[i--] = arr1[cur1--] + arr2[cur2--];
        //处理剩余数字
        while (cur1 >= 0) sum[i--] = arr1[cur1--];
        //第三步,调整非法数字,由于初始数组值为0或1,进行加减法进行借位运算,最大值为3,最小值为-1
        i = sum.size() - 1;
        while (i >= 0) 
        {
            if (sum[i] >= 2) 
            {
                //情况1,数值大于2,因为前一位符号相反,所以等价前位减去对应借位数
                sum[i - 1] -= sum[i] / 2;
                sum[i] = sum[i] % 2;
            } else if (sum[i] == -1) 
            {
                //情况2,数值为-1,借位造成,可以将当前位设置为1,前位加1等价解决
                sum[i - 1] += 1;
                sum[i] = 1;
            }
            i--;
        }
        // 去除前导0,但是至少保留一位
        if (sum[0] != 0) return sum;
        else 
        {
            //最终长度
            int finalLen = sum.size() - 1;
            //与sum数组长度差值(前导0个数)
            int k = 1;
            //求前导0个数,并求对应结果数组长度
            int j = 1;
            while (j < sum.size() && sum[j] == 0) 
            {
                j++;
                finalLen--;
                k++;
            }
            if (finalLen <= 0) finalLen = 1;
            vector<int> ans(finalLen);
            //拷贝数组
            for (j = 0; j < finalLen && j + k < sum.size(); j++) 
            {
                ans[j] = sum[j + k];
            }
            return ans;
        }
    }
};
Java代码:
class Solution {
    public int[] addNegabinary(int[] arr1, int[] arr2) {
        //使得第一个数组长度更长,如果短,则交换
        int len1 = arr1.length;
        int len2 = arr2.length;
        if (len2 > len1) {
            int[] tmp = arr1;
            arr1 = arr2;
            arr2 = tmp;
        }
        len1 = arr1.length;
        len2 = arr2.length;
        //首先进行对应位的加减法
        int cur1 = len1 - 1;
        int cur2 = len2 - 1;
        int[] sum = new int[len1 + 10];
        int i = sum.length - 1;
        //两个数组的加减法
        while (cur2 >= 0) {
            sum[i--] = arr1[cur1--] + arr2[cur2--];
        }
        while (cur1 >= 0) {
            sum[i--] = arr1[cur1--];
        }
        // 处理非0非1的数,最极限情况进2位
        i = sum.length - 1;
        while (i >= 0) {
            if (sum[i] > 1) {
                sum[i - 1] -= sum[i] / 2;
                sum[i] = sum[i] % 2;
            } else if (sum[i] == -1) {
                sum[i] = 1;
                sum[i - 1] += 1;
            }
            i--;
        }
        //处理前导0,最少留一个
        if (sum[0] != 0) return sum;
        else {
            int finalLen = sum.length - 1;
            int k = 1;
            int j = 1;
            //处理后续前导0
            while (j < sum.length && sum[j] == 0) {
                finalLen--;
                k++;
                j++;
            }
            //保证最少有一个前导0
            if (finalLen == 0) finalLen = 1;
            int[] ans = new int[finalLen];
            for (j = 0; j < finalLen && j + k < sum.length; j++) {
                ans[j] = sum[j + k];
            }
            return ans;
        }
    }
}
🌱总结
进位规律探索,进位模拟。














