1. 程式人生 > >二分法求解平方根注意點:

二分法求解平方根注意點:


  • 對於一個整數求解其平方根可以使用“二分法”和“牛頓法”。
  • 所謂“二分法”就是不斷地縮小平方根所在的範圍,直到收斂到一個數。例如求解數k的平方根t,首先設定t的範圍為[left, right](其中left和right分別初始化為1, k),然後判斷m=(l+k)/2與k的平方根t的關係,如果m比t小,則t的範圍為[m+1, right],否則為[left, m-1],然後依次迴圈,直到left>=right終止。
int mySqrt(int x) {
        if(x == 0)
        {
            return 0;
        }
        int left  = 1;
        int right = x;
        int ret = 0;
        while(left <= right)
        {
            int mid = (left + right) / 2;
            if(mid == x / mid)
            {
                return mid;
            }
            else if(mid > x/mid)
            {
                 right = mid - 1;
            }
            else
            {
                left = mid + 1;   
                ret = mid;       //在 left 需要後移前,就要注意 平方根整數部分,相反 right 前移則不需要注意  
            }
        }
        
        return ret;
    }
  • 通過觀察程式碼,我們可以發現其中有兩處地方值得考慮,對於第一處判斷可能很多人潛意識的會寫成“mid * mid == k”,而第二處寫成“mid * mid > k”,初看,這個貌似的確沒有什麼問題,但是在執行程式時可能會發現出現死迴圈現象。(我第一次寫程式碼就出現了這樣的問題)

  • 為什麼會出現這種情況呢?
    主要是因為在計算機中整型資料(int)是有位數限制的,一般是4個位元組(32bits),這就可能出現“mid * mid”溢位的情況,這樣在程式執行過程中就可能出現無限迴圈的情況。

  • 因此,以後在程式設計過程中一定要特別注意不同型別數的位數的限制,避免因為溢位造成的邏輯錯誤,而且在能夠同時使用乘法或者除法(注意考慮除數不能為0)時,儘量使用除法計算。

在做運算時,不僅要避免乘法可能會帶來的問題,還需要考慮到加法可能或造成的溢位問題,對於“二分法”演算法中求解"mid=left+right"就需要考慮右邊可能因為溢位造成的結果錯誤,因此應該改成"mid=left+(right-left)/2".

二分法標準模板

int binarySearch(vector<int>& nums, int target){
  if(nums.size() == 0)
    return -1;

  int left = 0, right = nums.size() - 1;
  while(left <= right)
  {
    // Prevent (left + right) overflow
    int mid = left + (right - left) / 2;
    if(nums[mid] == target)
    {
     	return mid; 
     }
    else if(nums[mid] < target) 
    {
    	 left = mid + 1;
    }
    else 
    { 
    	  right = mid - 1; 
    }
  }

  // End Condition: left > right
  return -1;
}