326. Simple difficulty:
Requirement: do not use loops or recursion to complete the problem
Note: 0 times of 3 = 1, which also needs to be taken into account.
Method 1: Trial Division: time complexity: O(log n) space complexity: O(1)
We keep dividing n by 3 until n=1. If n cannot be divided by 3 in this process, it means that n is not a power of 3.
n in this question can be a negative number or 0. You can directly judge the situation in advance and return False, or you can try to divide it, because a negative number or 0 cannot be divided by 3 many times to get 1
class Solution { public boolean isPowerOfThree(int n) { while (n != 0 && n % 3 == 0) { n /= 3; } return n == 1; } }
Reason for adopting cyclic division by 3 instead of cyclic multiplication by 3: assuming that the incoming data is 2147483647, if multiplying by 3 is adopted, it will take a lot of time to multiply from 1.
When dividing by 3 for the first time, we get 715 827 882.33333 with decimals. At this time, n% 3= 0 directly leaves the loop and returns false.
Method 2: judge whether it is the divisor of the power of maximum 3: spatiotemporal complexity: O(1)
class Solution { public boolean isPowerOfThree(int n) { return n > 0 && 1162261467 % n == 0; } }
204. Medium difficulty:
Method 1: original, time-consuming:
Definition of prime number: prime number, also known as prime number, refers to the natural number that has no other factors except 1 and itself among the natural numbers greater than 1.
Within 10: numbers are divided into prime numbers 2, 3, 5 and 7 and non prime numbers that can be divided by these numbers
Within 20: numbers are divided into prime numbers 2, 3, 5, 7, 11, 13, 17 and 19 and non prime numbers that can be divided by these numbers
In other words, when we traverse the given number 0 ~ n, every time we get a prime number, we will store it in the list, and then take the remainder of the next number and all the numbers in the list. If it is equal to 0, it means that it is a non prime number (because the factor of the next number must be taken from all the numbers in front of it)
Because the number of n is uncertain, I select the list of prime numbers as a dynamic array, and the time-consuming code generated by this is much longer than that of method 2. jpg
class Solution { ArrayList List = new ArrayList(); public int countPrimes(int n) { if(n <= 2){ return 0; } if(n == 3){ return 1; } List.add(2); for(int i = 3; i < n; i++){ if(isPrimes(i)){ List.add(i); } } return List.size(); } public boolean isPrimes(int n){ for(int i = 0;i < List.size(); i ++){ if( n % (int)List.get(i) == 0){ return false; } } return true; } }
Method 2: Violence
Principle: considering that if y is the factor of X, x/y must also be the factor of X, so we just need to check y or x/y. If we choose to check the smaller fraction of the two each time, it is not difficult to find that the smaller fraction must fall in the interval of [2, root x]. Therefore, we only need to enumerate all the numbers in [2, root x], so that the time complexity of a single check is reduced from O(n) to o (root n)
class Solution { public int countPrimes(int n) { int ans = 0; for (int i = 2; i < n; ++i) { ans += isPrime(i) ? 1 : 0; } return ans; } public boolean isPrime(int x) { for (int i = 2; i * i <= x; ++i) { if (x % i == 0) { return false; } } return true; } }
Based on the principle of "only enumerating all numbers in [2, root x], method 1 is improved as follows: at this time, the time consumption of method 1 is shorter than that of method 2
class Solution { public int countPrimes(int n) { if(n <= 2){ return 0; } if(n == 3){ return 1; } ArrayList List = new ArrayList(); List.add(2); int count = 1; for(int i = 3; i < n; i++){ if(isPrimes(i,List)){ List.add(i); } } return List.size(); } public boolean isPrimes(int n,ArrayList List){ for(int i = 0;(int)List.get(i) * (int)List.get(i) <= n; i ++){ if( n % (int)List.get(i) == 0){ return false; } } return true; } }
Method 3: Ehrlich sieve:
Enumeration does not take into account the correlation between numbers, so it is difficult to continue to optimize the time complexity. Next, we introduce a common algorithm, which was proposed by the Greek mathematician Eratosthenes Eratosthenes, called the eratosthene sieve method, abbreviated as the Ehrlich sieve.
We consider the fact that if xx is a prime number, then the multiples of x greater than x 2x,3x,... Must not be prime numbers, so we can start here.
Let isPrime[i] indicate whether the number I is a prime number. If it is a prime number, it is 1, otherwise it is 0. Traverse each number from small to large. If the number is a prime number, mark all its multiples as composite numbers (except the prime number itself), that is, 0, so that we can know the number of prime numbers at the end of the run.
The correctness of this method is obvious: this method obviously does not mark the prime number as a composite number; on the other hand, when traversing the number x from small to large, if it is a composite number, it must be an integer multiple of a prime number y less than x. therefore, according to the steps of this method, when traversing y, we will mark X as isprime [x] at this time =0. Therefore, this method does not mark composite numbers as prime numbers.
Of course, we can continue to optimize here. For a prime number x, if we start marking from 2x as mentioned above, it is actually redundant. We should start marking directly from X ⋅ x, because 2x,3x... These numbers must have been marked by multiples of other numbers before x, such as all multiples of 2, all multiples of 3, etc.
class Solution { public int countPrimes(int n) { int[] isPrime = new int[n]; // Initialize isPrime, all elements are 1, that is, all are prime numbers Arrays.fill(isPrime, 1); int ans = 0; for (int i = 2; i < n; ++i) { // Start traversing from i=2, because 2 is a prime number, so judge directly by 1 // Because the internal if judges the sum of the current i multiples, the 1 and 0 of the next cycle are accurate and can be judged directly by 1 if (isPrime[i] == 1) { ans += 1; // If i*i is less than n, some composite numbers that have not been determined can be selected: // For example, 1*i and 2*i have been determined as composite numbers when i is 1 and 2, so judge directly from i*i, (i+1)*i if ((long) i * i < n) { for (int j = i * i; j < n; j += i) { isPrime[j] = 0; } } } } return ans; } }
Method 4: linear sieve:
This method does not belong to the scope of interview. See:
Author: leetcode solution
Link: https://leetcode-cn.com/problems/count-primes/solution/ji-shu-zhi-shu-by-leetcode-solution/