Matemáticas de la "Serie de algoritmos"

Introducción

  En las preguntas de tipo matemáticas, hay puntos simples de conocimiento de matemáticas de educación obligatoria de nueve años, como encontrar el área de un rectángulo y encontrar la pendiente. También hay puntos de conocimiento matemático más avanzados, como Bash Game, codificación Gray y otras preguntas, como preguntas que involucran puntos de conocimiento matemático avanzado. Mi sugerencia personal es comprender y hacer más, pero no enredarse . Si conoce este tipo de punto de conocimiento para este tipo de preguntas, el código es muy simple, pero no puede hacerlo si no sabe cómo hacerlo. De hecho, la prueba ya no es una cuestión de algoritmo de código, sino más bien de matemáticas. Si usted es un entrevistador, es posible que no se le ocurra este tipo de pregunta que memoriza la respuesta y no tiene importancia para la evaluación. Por supuesto, si tienes suficiente energía para aprender, podrás aprender más, comprender más y estar armado hasta los dientes.

bases teóricas

  Las matemáticas son una disciplina que utiliza el lenguaje simbólico para estudiar conceptos como cantidad, estructura, cambio y espacio, desde cierta perspectiva pertenece a un tipo de ciencia formal . Las matemáticas surgen del conteo, cálculo, medición y observación de la forma y movimiento de los objetos mediante el uso de la abstracción y el razonamiento lógico. Los matemáticos amplían estos conceptos para formular nuevas conjeturas y establecer teoremas rigurosamente derivados de axiomas y definiciones seleccionados.
  El conocimiento y la aplicación de las matemáticas fundamentales es una parte integral de la vida individual y grupal. La perfección de los conceptos básicos de las matemáticas se puede ver ya en textos de matemáticas antiguos en el antiguo Egipto, Mesopotamia y la antigua India, y existe un tratamiento más riguroso en la antigua Grecia. Desde entonces, el desarrollo de las matemáticas ha continuado en pequeños incrementos, hasta el Renacimiento en el siglo XVI, donde la interacción de nuevos descubrimientos científicos e innovaciones matemáticas condujo a un desarrollo acelerado de las matemáticas hasta nuestros días. Las matemáticas se han convertido en parte de la categoría educativa en muchos países y regiones.
  Hoy en día, las matemáticas se utilizan en una variedad de campos, incluidas las ciencias , la ingeniería , la medicina , la economía y las finanzas . La aplicación de las matemáticas a estos campos suele denominarse matemáticas aplicadas y, a veces, estimula nuevos descubrimientos matemáticos y conduce al desarrollo de disciplinas completamente nuevas. Por ejemplo, ciertas teorías establecidas en el desarrollo sustantivo de la física inspiran a los matemáticos a resolver ciertos problemas. desde diferentes ángulos. Los matemáticos también estudian matemáticas puras, es decir, la sustancia de las matemáticas mismas, sin aspirar a ninguna aplicación práctica. Si bien gran parte de la investigación comienza con las matemáticas puras, a lo largo del camino se encuentran muchas aplicaciones.
  El fin de la computadora son las matemáticas, el fin de las matemáticas es la filosofía y el fin de la filosofía es la teología .

Experiencia en resolución de problemas

  • Las matemáticas y la informática están estrechamente relacionadas y el uso de fórmulas matemáticas es de gran ayuda para mejorar la complejidad del tiempo.
  • En la categoría de matemáticas, no es necesario enredar demasiado la memorización de respuestas a preguntas que involucran puntos de conocimiento matemático avanzado, solo compréndalo y no se convertirá en el foco de la entrevista.
  • Aprenda a expresar fórmulas matemáticas en lenguaje informático.
  • Si tienes suficiente energía para aprender, puedes memorizar las preguntas que implican conocimientos matemáticos avanzados.

tema de algoritmo

7. Inversión de enteros

inserte la descripción de la imagen aquí
Análisis del problema: convierta directamente a largo con un rango mayor y luego fuerce la salida después de la inversión.
El código se muestra a continuación:

/**
 * 数学
 */
class Solution {
    public int reverse(int x) {
        long ret = 0;
        while (x != 0) {
            int pop = x % 10;
            x /= 10;
            ret = ret * 10 + pop;
        }
        if (ret > Integer.MAX_VALUE || ret < Integer.MIN_VALUE) return 0;
        return (int) ret;
    }
}

9. Número palíndromo

inserte la descripción de la imagen aquí
Análisis del tema: después de negar el número entero, compare si los dos valores son iguales.
El código se muestra a continuación:

/**
 * 数学
 */
class Solution {
    public boolean isPalindrome(int x) {
        // 如果为负数,刚一定不是回文,直接返回false
        if (x < 0) {
            return false;
        }
        int reverseVal = 0;
        int val = x;
        // 对值进行反转
        while (val != 0) {
            int pop = val % 10;
            val /= 10;
            reverseVal = reverseVal * 10 + pop;
        }
        if (reverseVal == x) {
            return true;
        } else {
            return false;
        }
    }
}

50. Potencia(x,n)

inserte la descripción de la imagen aquí
Análisis del tema: La mitad del cálculo x^n = (x 2) (n/2) reduce en gran medida la cantidad de cálculo.
El código se muestra a continuación:

/**
 * 数学
 */
class Solution {
    public double myPow(double x, int n) {
        double res = 1.0D;
        // i每次操作都除2,不用一直相乘
        // i = 1 时,i /= 2 就等于0了
        for (int i = n; i != 0; i /= 2) {
            if (i % 2 != 0) {
                res *= x;
            }
            x *= x;
        }
        // 根据n的正负性,返回正数,还是倒数
        return n < 0 ? 1 / res : res;
    }
}

60. Secuencia de permutación

inserte la descripción de la imagen aquí
Análisis del tema: el retroceso y la recursividad expirarán, lo que se optimiza principalmente mediante métodos matemáticos. Los números son números naturales continuos a partir de 1 y los resultados de la clasificación se pueden impulsar. La expresión es: índice = k / (n-1) En este momento, el índice es el índice de los números candidatos restantes.
El código se muestra a continuación:

/**
 * 数学
 */
class Solution {

    public String getPermutation(int n, int k) {

        // 用StringBuilder,比直接用String快1ms,多击败50%选手
        StringBuilder res = new StringBuilder();

        // n为0,直接返回
        if (n == 0) {
            return res.toString();
        }

        // 声明候选数字组
        LinkedList<Integer> nums = new LinkedList();
        for (int i = 1; i <= n; i++) {
            nums.add(i);
        }

        k = k - 1;
        // 查找候选数字
        while (n != 0) {
            // 计算需要第几个侯选值
            int index = k / helper(n - 1);
            res.append(nums.remove(index));
            // 计算k剩余值
            k %= helper(n - 1);
            n--;
        }
        return res.toString();
    }

    // 实现阶乘
    private int helper(int n) {
        int sum = 1;
        for (int i = n; i > 0; i--) {
            sum *= i;
        }
        return sum;
    }
}

66. Más uno

inserte la descripción de la imagen aquí
Análisis de tema: agregue recursivamente uno por turno.
El código se muestra a continuación:

/**
 * 数学
 */
class Solution {
    public int[] plusOne(int[] digits) {
        int[] res = helper(digits, digits.length - 1);
        return res;
    }

    // 递归加一
    public int[] helper(int[] digits, int index) {
        // 如果进位到首位,直接新建数组返回
        if (index == -1) {
            int[] temp = new int[digits.length + 1];
            temp[0] = 1;
            return temp;
        }
        // 不等于9就加1,等于9就进一位
        if (digits[index] != 9) {
            digits[index] = digits[index] + 1;
            return digits;
        } else {
            digits[index] = 0;
            digits = helper(digits, index - 1);
            return digits;
        }
    }
}

69. Raíz cuadrada de x

inserte la descripción de la imagen aquí
Análisis del Tema: Vestidos con el manto de las matemáticas, utilizando la dicotomía.
El código se muestra a continuación:

/**
 * 数学
 */
class Solution {
    public int mySqrt(int x) {
        // 特殊值处理
        if (x == 0 || x == 1) {
            return x;
        }
        int left = 0;
        int right = x;
        int mid = 0;

        // 二分法
        while (left <= right) {
            mid = left + (right - left) / 2;
            if (mid > x / mid) {
                right = mid - 1;
            } else if (mid < x / mid) {
                left = mid + 1;
            } else {
                return mid;
            }
        }
        // 否则返回r
        return right;
    }
}

149. La mayoría de los puntos en línea recta.

inserte la descripción de la imagen aquí
Análisis del problema: fijar un punto, encontrar otros puntos para formar una línea recta con este punto y contar sus pendientes, la pendiente con más veces es nuestra respuesta.
El código se muestra a continuación:

/**
 * 数学 + 哈希表
 */
class Solution {
    public int maxPoints(int[][] points) {
        int n = points.length;
        if (n <= 2) {
            return n;
        }
        int ret = 0;
        for (int i = 0; i < n; i++) {
            if (ret >= n - i || ret > n / 2) {
                break;
            }
            Map<Integer, Integer> map = new HashMap<Integer, Integer>();
            for (int j = i + 1; j < n; j++) {
                int x = points[i][0] - points[j][0];
                int y = points[i][1] - points[j][1];
                if (x == 0) {
                    y = 1;
                } else if (y == 0) {
                    x = 1;
                } else {
                    if (y < 0) {
                        x = -x;
                        y = -y;
                    }
                    int gcdXY = gcd(Math.abs(x), Math.abs(y));
                    x /= gcdXY;
                    y /= gcdXY;
                }
                int key = y + x * 20001;
                map.put(key, map.getOrDefault(key, 0) + 1);
            }
            int maxn = 0;
            for (Map.Entry<Integer, Integer> entry: map.entrySet()) {
                int num = entry.getValue();
                maxn = Math.max(maxn, num + 1);
            }
            ret = Math.max(ret, maxn);
        }
        return ret;
    }

    public int gcd(int a, int b) {
        return b != 0 ? gcd(b, a % b) : a;
    }
}

168. Nombres de columnas de la tabla de Excel

inserte la descripción de la imagen aquí
Análisis del tema: el número entero se resta por 1 y luego se procesa de acuerdo con el sistema hexadecimal, porque el sistema hexadecimal comienza desde 0.
El código se muestra a continuación:

/**
 * 数学
 */
class Solution {
    public String convertToTitle(int columnNumber) {
        StringBuffer sb = new StringBuffer();
        while (columnNumber != 0) {
            columnNumber--;
            sb.append((char)(columnNumber % 26 + 'A'));
            columnNumber /= 26;
        }
        return sb.reverse().toString();
    }
}

171. Número de columna de Excel

inserte la descripción de la imagen aquí
Análisis del tema: Convertir hexadecimal a decimal.
El código se muestra a continuación:

/**
 * 数学
 */
class Solution {
    public int titleToNumber(String columnTitle) {
        int number = 0;
        int multiple = 1;
        for (int i = columnTitle.length() - 1; i >= 0; i--) {
            int k = columnTitle.charAt(i) - 'A' + 1;
            number += k * multiple;
            multiple *= 26;
        }
        return number;
    }
}

172. Cero después del factorial

inserte la descripción de la imagen aquí
Análisis del tema: Se pueden sacar tres conclusiones: 1. Solo necesita encontrar el número de factores 2 y 5 para determinar el número de ceros. Dos, el número de 2 es mayor que 5, así que solo encuentra el número del factor 5. 3. Hay un número divisible por 5 en cada intervalo de 5 números, y luego, entre estos números divisibles por 5, hay otro número divisible por 25 en cada intervalo de 5 números, por lo que es necesario dividirlo nuevamente hasta que el resultado sea 0. lo que significa que no existe ningún número que pueda seguir siendo divisible por 5.
El código se muestra a continuación:

/**
 * 数学
 */
class Solution {
    public int trailingZeroes(int n) {
        int count = 0;
        while(n >= 5) {
            count += n / 5;
            n /= 5;
        }
        return count;
    }
}

204. Contar números primos

inserte la descripción de la imagen aquí
Análisis del tema: Método de detección: Si x es un número primo, entonces los múltiplos de x mayores que x 2x, 3x ... no deben ser números primos, así que márquelos.
El código se muestra a continuación:

/**
 * 数学
 */
class Solution {
    public int countPrimes(int n) {
        int[] isPrime = new int[n];
        // 初始化
        Arrays.fill(isPrime, 1);
        int res = 0;
        for (int i = 2; i < n; ++i) {
            if (isPrime[i] == 1) {
                res += 1;
                if ((long) i * i < n) {
                    for (int j = i * i; j < n; j += i) {
                        // 合数标记为 0 
                        isPrime[j] = 0;
                    }
                }
            }
        }
        return res;
    }
}

223. Área rectangular

inserte la descripción de la imagen aquí
Análisis del tema: Geometría: Área total = Área única 1 + Área única 2 - Área superpuesta.
El código se muestra a continuación:

/**
 * 数学
 */
class Solution {
    public int computeArea(int ax1, int ay1, int ax2, int ay2, int bx1, int by1, int bx2, int by2) {
        int area1 = (ax2 - ax1) * (ay2 - ay1), area2 = (bx2 - bx1) * (by2 - by1);
        int overlapWidth = Math.min(ax2, bx2) - Math.max(ax1, bx1), overlapHeight = Math.min(ay2, by2) - Math.max(ay1, by1);
        int overlapArea = Math.max(overlapWidth, 0) * Math.max(overlapHeight, 0);
        return area1 + area2 - overlapArea;
    }
}

233. Número de unos

inserte la descripción de la imagen aquí
Análisis del tema: Enumere el número de 11 en cada dígito.
El código se muestra a continuación:

/**
 * 数学
 */
class Solution {
    public int countDigitOne(int n) {
        // mulk 表示 10^k
        // 在下面的代码中,可以发现 k 并没有被直接使用到(都是使用 10^k)
        // 但为了让代码看起来更加直观,这里保留了 k
        long mulk = 1;
        int ans = 0;
        for (int k = 0; n >= mulk; ++k) {
            ans += (n / (mulk * 10)) * mulk + Math.min(Math.max(n % (mulk * 10) - mulk + 1, 0), mulk);
            mulk *= 10;
        }
        return ans;
    }
}

241. Prioridad de diseño para expresiones aritméticas.

inserte la descripción de la imagen aquí
Análisis del tema: primero, realice un preprocesamiento de la expresión, coloque todos los operandos (incluidos números y operadores) en la matriz de operaciones y use −1, −2, −3 para representar los operadores +, −, * respectivamente. Porque para un operador op en una expresión, representamos los posibles resultados de cálculo de su parte izquierda con el conjunto izquierdo y los posibles resultados de cálculo de su parte derecha con el conjunto derecho. Entonces, todos los resultados posibles del caso en el que el operador es la última operación de la expresión son el número de combinaciones de elementos en el conjunto izquierdo y derecho correspondientes correspondientes a la operación del operador. Luego enumeramos todos los operadores en la expresión como separadores izquierdo y derecho para obtener el conjunto correspondiente, luego el resultado final posible de la expresión es la unión de estos conjuntos.
El código se muestra a continuación:

/**
  * 记忆化搜索
  */
class Solution {
    static final int ADDITION = -1;
    static final int SUBTRACTION = -2;
    static final int MULTIPLICATION = -3;

    public List<Integer> diffWaysToCompute(String expression) {
        List<Integer> ops = new ArrayList<Integer>();
        for (int i = 0; i < expression.length();) {
            if (!Character.isDigit(expression.charAt(i))) {
                if (expression.charAt(i) == '+') {
                    ops.add(ADDITION);
                } else if (expression.charAt(i) == '-') {
                    ops.add(SUBTRACTION);
                } else {
                    ops.add(MULTIPLICATION);
                }
                i++;
            } else {
                int t = 0;
                while (i < expression.length() && Character.isDigit(expression.charAt(i))) {
                    t = t * 10 + expression.charAt(i) - '0';
                    i++;
                }
                ops.add(t);
            }
        }
        List<Integer>[][] dp = new List[ops.size()][ops.size()];
        for (int i = 0; i < ops.size(); i++) {
            for (int j = 0; j < ops.size(); j++) {
                dp[i][j] = new ArrayList<Integer>();
            }
        }
        return dfs(dp, 0, ops.size() - 1, ops);
    }

    public List<Integer> dfs(List<Integer>[][] dp, int l, int r, List<Integer> ops) {
        if (dp[l][r].isEmpty()) {
            if (l == r) {
                dp[l][r].add(ops.get(l));
            } else {
                for (int i = l; i < r; i += 2) {
                    List<Integer> left = dfs(dp, l, i, ops);
                    List<Integer> right = dfs(dp, i + 2, r, ops);
                    for (int lv : left) {
                        for (int rv : right) {
                            if (ops.get(i + 1) == ADDITION) {
                                dp[l][r].add(lv + rv);
                            } else if (ops.get(i + 1) == SUBTRACTION) {
                                dp[l][r].add(lv - rv);
                            } else {
                                dp[l][r].add(lv * rv);
                            }
                        }
                    }
                }
            }
        }
        return dp[l][r];
    }
}

258. Agregar los bits

inserte la descripción de la imagen aquí
Análisis del tema: encuentre una pregunta normal. Si un número de tres dígitos 'abc' tiene un valor de s1 = 100 * a + 10 * b + 1 * c, después de sumar los dígitos una vez, se convierte en s2 = a + b + c , la diferencia reducida es (s1 -s2) = 99 * a + 9 * b, después de cada ciclo, la reducción es múltiplo de 9, por lo que cuando el último es de un solo dígito, la reducción total es 9*n, De esto se puede ver que tomamos directamente el resto de 9. Si el último valor numérico no es cero, devuelve num directamente y devuelve 9 directamente si es cero.
El código se muestra a continuación:

/**
 * 数学
 */
class Solution {
    public int addDigits(int num) {
        // 为零直接返回
        if (num == 0) {
            return 0;
        }
        // 对9取余,相当于减去 9*n
        num %= 9;
        if (num == 0) {
            return 9;
        }
        return num;
    }
}

263. Números feos

inserte la descripción de la imagen aquí
Análisis del tema: divide por 2, 3 y 5 en un bucle, y cuando el resto es 1, es un número feo.
El código se muestra a continuación:

/**
 * 数学
 */
class Solution {
    public boolean isUgly(int n) {
        if (n < 1) {
            return false;
        }
        while (n % 2 == 0) {
            n /= 2;
        }
        while (n % 3 == 0) {
            n /= 3;
        }
        while (n % 5 == 0) {
            n /= 5;
        }
        return n == 1;
    }
}

273. Conversión de enteros a representación inglesa.

inserte la descripción de la imagen aquí
Análisis del tema: dado que se ha determinado el valor máximo del número entero no negativo, hay como máximo 10 dígitos. Al convertir un número entero a una representación en inglés, divida los números en grupos de 3 dígitos y concatene las representaciones en inglés de cada grupo para obtener la representación en inglés del número entero.
El código se muestra a continuación:

/**
 * 递归
 */
class Solution {
    String[] singles = {"", "One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine"};
    String[] teens = {"Ten", "Eleven", "Twelve", "Thirteen", "Fourteen", "Fifteen", "Sixteen", "Seventeen", "Eighteen", "Nineteen"};
    String[] tens = {"", "Ten", "Twenty", "Thirty", "Forty", "Fifty", "Sixty", "Seventy", "Eighty", "Ninety"};
    String[] thousands = {"", "Thousand", "Million", "Billion"};

    public String numberToWords(int num) {
        if (num == 0) {
            return "Zero";
        }
        StringBuffer sb = new StringBuffer();
        for (int i = 3, unit = 1000000000; i >= 0; i--, unit /= 1000) {
            int curNum = num / unit;
            if (curNum != 0) {
                num -= curNum * unit;
                StringBuffer curr = new StringBuffer();
                recursion(curr, curNum);
                curr.append(thousands[i]).append(" ");
                sb.append(curr);
            }
        }
        return sb.toString().trim();
    }

    public void recursion(StringBuffer curr, int num) {
        if (num == 0) {
            return;
        } else if (num < 10) {
            curr.append(singles[num]).append(" ");
        } else if (num < 20) {
            curr.append(teens[num - 10]).append(" ");
        } else if (num < 100) {
            curr.append(tens[num / 10]).append(" ");
            recursion(curr, num % 10);
        } else {
            curr.append(singles[num / 100]).append(" Hundred ");
            recursion(curr, num % 100);
        }
    }
}

278. La primera versión errónea

inserte la descripción de la imagen aquí
Análisis del tema: búsqueda de dicotomía. Tenga en cuenta que cuando el valor es demasiado grande, no puede usar (izquierda + derecha)/2, debe usar izquierda + (derecha -izquierda)/2 para evitar el desbordamiento.
El código se muestra a continuación:

/**
 * 二分法查找
 */
public class Solution extends VersionControl {
    public int firstBadVersion(int n) {
        int left = 1;
        int right = n;
        while(left <= right){
            int mid = left + (right -left)/2;
            if (isBadVersion(mid)){
                right = mid - 1;
            }else{
                left = mid + 1;
            }
        }
        return left;
    }
}

292. Juego de Nim

inserte la descripción de la imagen aquí
Análisis del tema: juego Bash, cuando n % (m+1)! = 0, el primer jugador siempre ganará. En el caso de que ambos jueguen, definitivamente perderá la primera mano con un número entero de 4. Siempre que a tome n primero y b tome 4-n, se garantiza que b definitivamente ganará, y si la primera mano no es una entero de 4, el resto se puede quitar para ganar. Por lo tanto: para comenzar primero, solo necesita juzgar si el número es múltiplo de 4 para juzgar si ganará.
El código es el siguiente:

/**
 * 巴什博奕
 */
class Solution {
    public boolean canWinNim(int n) {
        if(n%4 == 0) return false;
        return true;
    }
}

volver a la página de inicio

Algunos sentimientos sobre el cepillado Leetcode 500+ preguntas

Próximo

Árbol "Serie de algoritmos"

Supongo que te gusta

Origin blog.csdn.net/qq_22136439/article/details/126322883
Recomendado
Clasificación