二分法求解平方根注意點:
阿新 • • 發佈:2018-11-26
- 對於一個整數求解其平方根可以使用“二分法”和“牛頓法”。
- 所謂“二分法”就是不斷地縮小平方根所在的範圍,直到收斂到一個數。例如求解數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; }