[LeetCode]-Mathematics-1

Preface

Record the math-related questions encountered in LeetCode quizzes, Part 1

204. Counting Prime Numbers

Prime numbers are a very important part of number theory, and should be the first knowledge point that most people come into contact with when they first come into contact with number theory. The following summarizes several methods of judging prime numbers or sieving prime numbers based on the official solution:

  1. The most primitive way. The definition of a prime number is that among the natural numbers greater than 1, there are no other natural numbers except 1 and itself. So for each number x, we can enumerate each number y in [2,x−1] from small to large, and determine whether y is a factor of x. As long as one of the enumerations is yes, it means that x is not a prime number. . This method, for the case of judging how many prime numbers there are in n numbers, the time complexity is O(n²). An optimization of this method is that there is no need to judge [2,x−1], judge [ 2 , x ] [2,\sqrt{x}][2,x ] to
  2. Sieve of Ehrlich : If x is a prime number, then the multiples of x 2x, 3x,... that are greater than x must not be prime numbers, so you can traverse each number from small to large. If this number is a prime number, mark all its multiples as composite numbers (except the prime number itself). This method can also be optimized: if x is a prime number, just start from x * x and mark it as a composite number , because the composite numbers starting from 2x to x * x must be enumerated to a smaller prime number than x already sifted
  3. Linear sieve : Compared with the Ehrlich sieve, one more set of currently obtained prime numbers is maintained during enumeration. Different from the Sieve of Ehrlich, the composite number labeling process is no longer performed only when x is a prime number , but is performed for every integer x. For the integer x, we no longer mark all its multiples, but only mark the number obtained by multiplying the number in the prime number set with The product label of x is a composite number, and the labeling process ends when it is found that x can be divided by a certain prime number.

Here is how a linear screen is done:

public int countPrimes(int n) {
    
    
    List<Integer> primes = new ArrayList<Integer>(); //质数集合
    int[] isPrime = new int[n];                      //标记质数
    Arrays.fill(isPrime, 1);
    for (int i = 2; i < n; ++i) {
    
    
        if (isPrime[i] == 1) {
    
    
            primes.add(i);
        }
        //注意如果 i * primes.get(j) >= n 直接跳出循环
        for (int j = 0; j < primes.size() && i * primes.get(j) < n; ++j) {
    
    
            isPrime[i * primes.get(j)] = 0;
            //遇到能整除的质数结束标记过程
            if (i % primes.get(j) == 0) {
    
    
                break;
            }
        }
    }
    return primes.size();
}

326. Powers of 3

According to the data range, the maximum value of n not greater than 2 31 - 1 is 3 19 = 1162261467. Then if n is the power of 3, that is, n = 3 x , then n * 3 k = 3 19 must be satisfied , where 0 <= k <= 19, that is, 3 19 % n = 0, so you only need to judge whether this equation is true. Also determine whether n is greater than 0:

public boolean isPowerOfThree(int n) {
    
    
    return n > 0 && 1162261467 % n == 0;
}

1262. The largest sum divisible by three

In the remain array, remain[0] records the maximum sum of the elements that have been divided by three, leaving 0; remain[[1] records the maximum sum of the elements that have left 1, after dividing by three; remain[2] records the maximum sum of the elements that have been divided by three, leaving 1 The largest sum of elements that leaves 2 after division by three. After traversing all elements, remain[0] is the answer to this question

public int maxSumDivThree(int[] nums) {
    
    
    int len = nums.length;
    int[] remain = new int[3];
    int a,b,c;
    for(int i = 0; i < len; i++){
    
    
        a = remain[0] + nums[i];
        b = remain[1] + nums[i];
        c = remain[2] + nums[i];
        remain[a % 3] = Math.max(remain[a % 3], a);
        remain[b % 3] = Math.max(remain[b % 3], b);
        remain[c % 3] = Math.max(remain[c % 3], c);
    }
    return remain[0];
}

171. Excel column serial number

Converting a string to a number is equivalent to converting hexadecimal to decimal.
But there is no 0 in decimal, and 'A' corresponds to 1 instead of 0, so when converting letters into numbers, you need to add one, that is, letter - 'A' + 1 instead of letter - 'A'

public int titleToNumber(String columnTitle) {
    
    
    int len = columnTitle.length();
    int ans = 0;
    for(int i = 0; i < len; i++){
    
    
        ans = ans * 26 + (columnTitle.charAt(i) - 'A' + 1);
    }
    return ans;
}

168. Excel table column names

The idea of ​​question 171 can be reversed. At the beginning, I did 168 questions without doing 171 questions. I couldn't understand the "cn–" sentence. Then I did question 171 first, the "columnTitle.charAt(i) - 'A' + 1" in 171 is quite easy to understand

After subtracting one from cn each time, the remainder of 26 is obtained, which is "columnTitle.charAt(i) - 'A'" in 171, so adding 'A' is the letter in the corresponding position. By analogy, connect all letters using StringBuilder. The order of connection is from low to high, and reverse becomes high to low.

public String convertToTitle(int cn) {
    
    
    StringBuilder sb = new StringBuilder();
    while (cn > 0) {
    
    
        cn--;
        sb.append((char)(cn % 26 + 'A'));
        cn /= 26;
    }
    return sb.reverse().toString();
}

292. Nim Game

If there are 0 stones left when it is my turn, then I will lose; if there are 1 stones left, then I can take 1, and when the other side has no stones to take, they must lose; if there are 2 stones left, then I can If you take 2 stones, the other side will lose if there are no stones; if there are 3 left, then I can take 3, and if there are no stones on the other side, you will lose; if there are 4 stones left, then I don’t care if I take 1 Whether it is 2 or 3, the remaining stones can be taken all at once. If it is my turn to take no stones again, I will lose; On the opposite side, it is the same as giving me the remaining 4. The opposite side must lose... You can find the law, if n takes the remainder 4 as 0, then I will lose

public boolean canWinNim(int n) {
    
    
    return n % 4 != 0;
}

470. Implement Rand10() with Rand7()

randX() can get [1,X], then randX() - 1 is [0,X - 1], (randX() - 1) * Y is [0,(X - 1)Y], then (randX () - 1) * Y + randY() is [1,X*Y]

Therefore, there are randX() and randY(), and randX*Y can be obtained by (randX() - 1) * Y + randY()

So for this question, if there is rand7 at the beginning, we can get rand49. If the result is in [1,40], we can take the remainder 10 and add 1 to get rand10. If the result is in [41,49], you can subtract 40 to get [1,9], which is rand9, which can be followed by rand7 to get rand63. In the same way, if the result is in [1,60], you can get rand10. Otherwise, you get rand3, which can be followed by rand7 to get rand21. At this time, if the result is in [1,20], you can get rand10, otherwise there is only one result left, 1, and you cannot continue to get new rand, and you can only cycle from the beginning.

public int rand10() {
    
    
    while(true) {
    
    
        int rand7_1 = rand7();
        int rand7_2 = rand7();
        int r1 = (rand7_1 - 1) * 7 + rand7_2; //rand 49
        if(r1 <= 40) return r1 % 10 + 1; //rand 10

        r1 -= 40; //rand 9
        int rand7_3 = rand7();
        int r2 = (r1 - 1) * 7 + rand7_3; //rand 63
        if(r2 <= 60) return r2 % 10 + 1; //rand 10

        r2 -= 10; //rand 3
        int rand7_4 = rand7();
        int r3 = (r2 - 1) * 7 + rand7_4; //rand 21
        if(r3 <= 20) return r3 % 10 + 1; 
        
        //此时r3 - 20是1,说明后续无法继续去找rand X*Y了,只能重新开始循环
    }
}

50. Pow(x, n)

To calculate x n , if we follow the idea of ​​multiplying n x, the complexity is O(n); while fast power is based on the idea of ​​divide and conquer, x n will be equal to the square of x n/2 , so we can calculate x n first /2 and then perform a square operation to get x n . In the same way, x n/2 is equal to x n/4 . Therefore, we can first calculate x n/4 and then perform a square operation to get x n/2 , and so on. Therefore, The total complexity is O(logn), thus reducing the calculation time

It should be noted that if n is an odd number, then x n should be equal to x n/2 * x n/2 * x, so it is necessary to determine whether it is necessary to multiply by one more x when performing the square root operation.

class Solution {
    
    
    public double myPow(double x, int n) {
    
    
        return n >= 0 ? quickPow(x, n) : 1.0 / quickPow(x, -n);
    }
    public double quickPow(double x, long n) {
    
    
        if (n == 0) {
    
    
            return 1.0;
        }
        //计算平方根
        double tmp = quickPow(x,n / 2);
        return n % 2 == 0 ? tmp * tmp : tmp * tmp * x;
    }
}

Guess you like

Origin blog.csdn.net/Pacifica_/article/details/125566556