日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

实现除法操作

發布時間:2025/3/19 编程问答 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 实现除法操作 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

前文

  • 一道算法題,涉及到了二進制的位操作,借這個機會整理一下相關的知識點,并且在這道算法題中進行了實踐
  • 本文的解法來自于該算法題的一篇討論。

  • 一、算法題介紹

    對除數和被除數實現除法運算,其中不使用乘法、除法和求余操作,返回對應的商。如,
    Input: dividend = 10, divisor = 3
    Output: 3

    解法1:暴力解法

    class Solution {public int divide(int dividend, int divisor){//定義除法,被除數是最小值,除以-1時,是最大值if(dividend == Integer.MIN_VALUE && divisor == -1)return Integer.MAX_VALUE;//^運算符,只有不同時,才為true ; sign定義商是否為負數 int sign = (dividend < 0) ^ (divisor < 0) ? -1 : 1;int result = 0;//取除數和被除數的正數形式long x = Math.abs((long)dividend);long y = Math.abs((long)divisor);//統計被除數共減去多少個除數,即為商while(x >= y){x -= y;result++;}return sign > 0 ? result : -result;} } 復制代碼
  • 暴力解法主要是通過不斷循環將y(除數)從x(被除數)中減去,直到x<y. x減去y的次數就是商,而最后剩下的小于y的部分就是余數。暴力解法的時間復雜度很高,比如說,當x=231-1,y=1時,需要循環231-1次。
    • 時間復雜度:O(x),x是被除數。
    • 空間復雜度:O(1)。

    解法2:除數左移位累加

    class Solution {public int divide(int dividend, int divisor){if(dividend == Integer.MIN_VALUE && divisor == -1)return Integer.MAX_VALUE;int sign = (dividend < 0) ^ (divisor < 0) ? -1 : 1;int result = 0;long x = Math.abs((long)dividend);long y = Math.abs((long)divisor);while(x >= y){int shift = 1;//將y持續向左移位,相當于y*2^(shift);//當y*2^(shift)< x <y*2^(shift+1)時,循環結束while(x >= (y << shift)){shift++;}x -= y << (shift - 1);//相當于x = y*2^(shift)+y*2^(shift-n)+.....+y*2^(0) + m;m是余數result += 1 << (shift - 1);}return sign > 0 ? result : -result;} } 復制代碼
  • 這個方法,是計算最大的k,使得y*2k<=x,然后將y*2k從x中減去,將2k加到商里面。比如說, 如果x= (1011)2,y=(10)2,那么因為2*22<= 11而且2*23>11 所以k=2。所以,我們將 (1011)2減去 (1000)2得到 (11)2,然后,將2k=22=(100)2加到商中,然后將x更新為(11)2繼續運算。
  • 使用y*2k的優勢在于,可以使用非常高效的移位操作,而且每次循環后,最差的情況下,x都會變為原來的一半。如果n是x/y的商的位數,那么總共需要n次循環。子循環中每次通過循環k次來找到y*2k的最大的k,因此:
    • 時間復雜度:O(n2),n是x/y的商的位數。
    • 空間復雜度:O(1)。

    解法3:除數左移位遞減

    class Solution {public int divide(int dividend, int divisor){if(dividend == Integer.MIN_VALUE && divisor == -1)return Integer.MAX_VALUE;int sign = (dividend < 0) ^ (divisor < 0) ? -1 : 1;int result = 0;int power = 32;//long是8字節,64位;int是4字節,32位long x = Math.abs((long)dividend);long y = Math.abs((long)divisor);while(x >= y){//將y*2^32增加到最大,然后逐步減小,靠近x//y*2^power<x時結束while((y << power) > x){//每次只需要執行有限步就能找到power,不像前面中的方法,是執行O(n)步才能找到power--;}x -= y << power;result += 1 << power;}return sign > 0 ? result : -result;} } 復制代碼

    1.在每次循環中找到最大的k的最好的方式就是認識到k其實是在不斷縮小的。因此,我們不需要在每次子循環的時候都檢驗一下21,22,23......是否小于或者等于x,我們可以在找到最大的k后,直接在后面的每次循環中檢驗x和2k-1,2k-2,2k-3....的關系。
    2. 我們可以繼續之前的例子。商為(100)2后,我們繼續計算(11)2。因為y*2k<=x的最大k是0,所以我們把20=(1)2加到商里,因此商就變成了(101)2。然后我們繼續算法,因此(1)2<y,所以算法結束。最后,我們可以得到,x= (1011)2,y=(10)2相除,商為(101)2,余數為(1)2

    • 時間復雜度:O(n),n是x/y的商的位數。
    • 空間復雜度:O(1)

    總結

    以上是生活随笔為你收集整理的实现除法操作的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。