A+B的問題

問題描述:

  1. 方法一

     採用位運算符實現加法運算。位運算符運算的表格如下:

運算符

功能

用法

                             說明

  ~

位求反

~expr

二進制逐位求反後生成一個新值,0變1,1變0

<<

左移

expr1 << expr2

在右側插入值爲0的二進制位

>>

右移

expr1 >> expr2

在左側插入值爲0的二進制位

&

位與

expr1 & expr2

同爲1取1,否則取0

^

位異或

expr1 ^ expr2

相同取0,不同取1

|

位或

expr1 | expr2

至少有一個爲1,則爲1,否則爲0

 對於加法運算,先將加數(a)和被加數(b)化成二進制數,然後對 a 和 b 進行位異或(^)運算:異或運算又稱不進位加法、進行位與(&)運算,將這兩個結果相加即可實現加法運算。

例子:

 用到的語法:C++中的if....else語法:

if(boolean_expression)
{
   //如果不二表達式爲真,將執行此處語句
}
else
{
   //如果布爾表達式爲假,將執行此處的語句
}

 

方法一程序代碼:(遞歸版本)

class Solution {
public:
    /**
     * @param a: An integer
     * @param b: An integer
     * @return: The sum of a and b 
     */
    int aplusb(int a, int b) {
        // write your code here
        int sum = 0;
        int sum1 = a^b;  //異或操作,得到二進制原位對應相加之後的和
        int sum2 = (a&b)<<1;  //與運算和左移運算,得相加之後進位所在位得值
        if(sum2 != 0)
        {
            sum = aplusb(sum1,sum2);  //若進位不是0,則a+b的和爲原位和+進位和
        }
        else
        {
            sum = sum1;  //若進位和爲0,則a+b的和直接等於異或後的結果
        }
        return sum;  //返回加法運算後的結果
        
    }
};

運行時效: 

 

2.方法二(遞歸版本)

使用三目運算符替代if....else語句,提高運行效率。

三目運算符: c ? x : y

                      若條件c爲true,執行x的值;否則,執行y的值。

方法二的代碼:

class Solution {
public:
    /**
     * @param a: An integer
     * @param b: An integer
     * @return: The sum of a and b 
     */
    int aplusb(int a, int b) {
        // write your code here
        int sum = 0;
        int sum1 = a^b;  //異或操作,得到二進制原位對應相加之後的和
        int sum2 = (a&b)<<1;  //與運算和左移運算,得相加之後進位所在位得值
        
       //使用三目運算符c ? x:y,若條件爲true,則計算x的值,否則,計算y的值
        return sum2 == 0 ? sum1 : aplusb(sum1,sum2) ;  
        
    }
};

運行時效: 

3.方法三:(迭代版本)

class Solution {
public:
    /**
     * @param a: An integer
     * @param b: An integer
     * @return: The sum of a and b 
     */
     //加法運算迭代版
    int aplusb(int a, int b) {
        // write your code here
        int sum =a^b;
        int sum1 = (a&b)<<1;
        while(sum1 != 0)  //不斷迭代,直到爲0跳出循環
        {
            int a = sum;
            int b = sum1;
            sum = a^b;
            sum1 =(a&b)<<1;
        }
        return sum;
    }
};

運行時效: 

 

迭代和遞歸的區別:

從“編程之美”的角度看,可以借用一句非常經典的話:“迭代是人,遞歸是神!”來從宏觀上對二者進行把握。

  • 遞歸:重複調用函數自身實現循環稱爲遞歸;

       遞歸實際上不斷地深層調用函數,直到函數有返回纔會逐層的返回,遞歸是用機制實現的,每深入一層,都要佔去一塊棧數據區域,因此,遞歸涉及到運行時的堆棧開銷(參數必須壓入堆棧保存,直到該層函數調用返回爲止),所以有可能導致堆棧溢出的錯誤;但是遞歸編程所體現的思想正是人們追求簡潔、將問題交給計算機,以及將大問題分解爲相同小問題從而解決大問題的動機。

         例如:if else 調用自己,並在合適時機退出

 

  • 迭代:利用變量的原值推出新值稱爲迭代,或着說迭代是函數內某段代碼實現循環

        迭代大部分時候需要人爲的對問題進行剖析,分析問題的規律所在,將問題轉變爲一次次的迭代來逼近答案。迭代不像遞歸那樣對堆棧有一定的要求,另外一旦問題剖析完畢,就可以很容易的通過循環加以實現。迭代的效率高,但卻不太容易理解,當遇到數據結構的設計時,比如圖表、二叉樹、網格等問題時,使用就比較困難,而是用遞歸就能省掉人工思考解法的過程,只需要不斷的將問題分解直到返回就可以了。

         例如:for,while循環

  • 兩者關係:所有的迭代可以轉換爲遞歸,但遞歸不一定可以轉換成迭代。

 總結如下:

  定義 優點 缺點
遞歸 重複調用函數自身實現循環

a.用有限的循環語句實現無限集合;

b.代碼易讀;

c.大問題轉化成小問題,減少了代碼量。

a.遞歸不斷調用函數,浪費空間

b.容易造成堆棧溢出

迭代

利用變量的原值推出新值;

函數內某段代碼實現循環。

a.效率高,運行時間只隨循環的增加而增加;

b.無額外開銷。

a.代碼難理解;

b.代碼不如遞歸代碼簡潔;

c.編寫複雜問題時,代碼邏輯不易想出

兩者關係

a.遞歸中一定有迭代,但是迭代中不一定有遞歸;大部分可以相互轉換。

b.相對來說,能用迭代不用遞歸(因爲遞歸不斷調用函數,浪費空間,容易造成堆棧溢出)

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章