题目
解答
方案一
class Solution {
public int mySqrt(int x) {
if (x == 0) {
return 0;
}
if (x < 4) {
return 1;
}
for (int i = 2, length = Math.min(46342, x / 2 + 2); i < length; ++i) {
int value = i * i;
if (value == x) {
return i;
}
if (value > x || value < 0) {
return i - 1;
}
}
return 0;
}
}
方案二
class Solution {
public int mySqrt(int x) {
if (x == 0) {
return 0;
}
if (x < 4) {
return 1;
}
for (int i = Math.min(46340, x / 4 + 1); i > 1; --i) {
long value = i * i;
if (value == x) {
return i;
}
if (value > 0 && value < x) {
return i;
}
}
return 0;
}
}
方案三
class Solution {
public int mySqrt(int x) {
if (x == 0) {
return 0;
}
if (x < 4) {
return 1;
}
for (int length = Math.min(46342, x / 2 + 2); true;) {
int value = length * length;
if (value == x) {
return length;
}
if (value < x && value > 0) {
return length;
}
length = (length + x / length) / 2;
}
}
}
方案四
class Solution {
public int mySqrt(int x) {
if (x == 0) {
return 0;
}
if (x < 4) {
return 1;
}
for (int start = 1, end = Math.min(46342, x / 2 + 2); true;) {
int mid = (start + end) / 2;
if (mid == start || mid == end) {
return mid;
}
int value = mid * mid;
if (value == x) {
return mid;
}
if (value < 0 || value > x) {
end = mid;
} else {
start = mid;
}
}
}
}
方案五
class Solution {
public int mySqrt(int x) {
if (x == 0) {
return 0;
}
if (x < 4) {
return 1;
}
int min = 0;
int max = x;
while (max - min > 1) {
int m = (max + min) / 2;
if (x / m < m) {
max = m;
} else {
min = m;
}
}
return min;
}
}
要点
方案一和方案二是直接求解。
方案三,使用牛顿迭代法,不过实现并不优雅。
方案四,使用二分查找或者折半查找,不过实现并不优雅,使用除法来协助判定当前迭代的值是否满足要求,应该可以规避溢出的问题。
方案五,同样使用了二分查找,相对要优雅一点。
在实现时,需要注意边界值,比如从0,1,2,3,4以及46342、46340。
整型最大值的平方根,取整之后为46340,因此可以作为迭代的上限值。
准备的用例,如下
@Before
public void before() {
t = new Solution();
}
@Test
public void test001() {
assertEquals(2, t.mySqrt(8));
}
@Test
public void test002() {
assertEquals(2, t.mySqrt(4));
}
@Test
public void test003() {
assertEquals(1, t.mySqrt(3));
}
@Test
public void test004() {
assertEquals(1, t.mySqrt(2));
}
@Test
public void test005() {
assertEquals(2, t.mySqrt(5));
}
@Test
public void test006() {
assertEquals(46340, t.mySqrt(2147483647));
}