x al cuadrado
1. Tema
Enlace de Leetcode
Dado un número entero no negativo x, calcule y devuelva la raíz cuadrada aritmética de x.
Dado que el tipo de retorno es un número entero, solo se conserva la parte entera del resultado y se descarta la parte decimal.
Nota: No se permiten funciones exponenciales integradas ni operadores como pow(x, 0,5) o x ** 0,5.
Ejemplo 1:
Entrada: x = 4
Salida: 2
Ejemplo 2:
Entrada: x = 8
Salida: 2
Explicación: La raíz cuadrada aritmética de 8 es 2,82842…, como el tipo de retorno es un número entero, la parte decimal se redondeará.
pista:
0 <= x <= 2 31 - 1
2. Idea
Dado que solo se mantiene la parte entera, ans es el mayor valor de k que satisface k 2 ≤ x
Solución 1: encuentre la raíz cuadrada de la función logarítmica
[Nota: el valor devuelto es un número de punto flotante, lo que causará problemas de precisión]
Solución 2: búsqueda binaria k
Solución 3: método de iteración de Newton
- Transformar el problema en resolver el punto cero de la función
- La esencia del método iterativo de Newton es acercarse rápidamente a cero desde el valor inicial con la ayuda de la serie de Taylor.
- Proceso de implementación
- detalles de implementacion
3. Implementación del código
Solución 2: búsqueda binaria k
class Solution {
public:
int mySqrt(int x) {
int left = 0;
int right = x;
int ans = -1;
while(left <= right){
int middle = left + (right - left) / 2;
if((long long)middle*middle <= x){
ans = middle; // 满足条件的k, 最后更新得到ans
left = middle + 1;
}else{
right = middle - 1;
}
}
return ans;
}
};
Análisis de Complejidad
- Complejidad del tiempo: O ( logx ) O(logx)O ( l o g x ) es el número de veces necesario para la búsqueda binaria.
- Complejidad del espacio: O ( 1 ) O(1)O ( 1 )
Solución 3: método de iteración de Newton
class Solution {
public:
int mySqrt(int x) {
if (x == 0) return 0;
// 设置迭代初始值
double x0 = x;
double C = x;
while(true){
double x1 = 0.5 * (x0 + C/x0); // 根据公式得到下一个点x(i+1)
if(fabs(x1 - x0) < 1e-7) break;
x0 = x1; // 更新点xi
}
return int(x0);
}
};
Análisis de Complejidad
- Complejidad del tiempo: O ( logx ) O(logx)O ( log x ) , este método es cuadráticamente convergente, más rápido que la búsqueda binaria .
- Complejidad del espacio: O ( 1 ) O(1)O ( 1 )。
4. Resumen
1. Juicio de desbordamiento
(long long)middle*middle <= x
- Aquí el rango de valores de medio es 0 <= medio <= 2 31 - 1, luego 0 <= medio * medio < 2 62
- Y el rango de valores de la variable int es 2 31 <= medio <= 2 31
- Debido a que el tipo de variable debe convertirse en largo
2. Conociendo la pendiente de la recta y un punto de la recta, la fórmula de expresión de la ecuación de la recta
3. abs() y fabs()
- abs() se usa principalmente para encontrar el valor absoluto de un número entero, en el archivo de encabezado "stdlib.h" (o).
- Y fabs() es principalmente para buscar el valor absoluto de tipo doble y flotante con requisitos de mayor precisión, en el archivo de encabezado <cmath>.
- Ambos se pueden usar cuando solo #include <cmath>.
4. Corregir la escritura idiomática de las matemáticas
double x1 = 1/2 * (x0 + C/x0); // 根据公式得到下一个点x(i+1)
Escrito de esta forma, se repetirá para siempre, ¡porque 1/2 aquí obtendrá 0!