周赛326总结
感谢力扣,第一次全部做完,耗时43分37秒,很满足了,虽然是题比较简单,新的一年继续努力呀!!
计能整除数字的位数
Given an integer
num
, return the number of digits innum
that dividenum
.An integer
val
dividesnums
ifnums % val == 0
.
-
思路:通过整除和取余的运算将
num
的每个数位取出,判断是否能整除num
,统计能够整除的数位个数返回即可 -
实现
class Solution { public int countDigits(int num) { int ans = 0; int cur = num; while(cur / 10 != 0){ int x = cur % 10; if (num % x == 0){ ans++; } cur /= 10; } if (num % cur == 0){ ans++; } return ans; } }
- 复杂度
- 时间复杂度: O ( n ) O(n) O(n), n n n为 n u m num num的数位个数
- 空间复杂度: O ( 1 ) O(1) O(1)
- 复杂度
-
别人的代码就是好看
// arignote class Solution { public int countDigits(int num) { int count = 0; for (int i = num; i > 0; i /= 10) { count += num % (i % 10) > 0 ? 0 : 1; } return count; } }
数组乘积中的不同质因数数目
Given an array of positive integers
nums
, return the number of distinct prime factors in the product of the elements ofnums
.Note that:
- A number greater than
1
is called prime if it is divisible by only1
and itself.- An integer
val1
is a factor of another integerval2
ifval2 / val1
is an integer.
-
思路:求出数组
nums
中每个数的质因数,并存储在set集合中,最终返回set集合的大小 -
实现
class Solution { public int distinctPrimeFactors(int[] nums) { Set<Integer> set = new HashSet<>(); for (int num : nums){ for (int i = 2; i <= num; i++){ while (num >= i && num % i == 0 && isPrime(i)){ set.add(i); num /= i; } } } return set.size(); } public boolean isPrime (int x){ if (x <= 1){ return false; } for (int i = 2; i * i <= x; i++){ if (x % i == 0){ return false; } } return true; } }
- 复杂度
- 时间复杂度: O ( n U ) O(nU) O(nU), n n n为 n u m s nums nums的长度, U = m a x ( n u m s ) U=max(nums) U=max(nums)
- 空间复杂度: O ( U l o g U ) O(\frac {U}{logU}) O(logUU),最多有 U l o g U \frac {U}{logU} logUU个质因数
- 复杂度
-
优化:不需要判断 i i i是否是质因数,因为 n u m num num已经用前面的 i i i分解了,所以从小到大用 i i i能够整除 n u m num num时, i i i一定是 n u m num num的质因数
class Solution { public int distinctPrimeFactors(int[] nums) { Set<Integer> set = new HashSet<>(); for (int num : nums){ for (int i = 2; i <= num; i++){ while (num >= i && num % i == 0){ set.add(i); num /= i; } } } return set.size(); } }
- 复杂度
- 时间复杂度: O ( n U ) O(n\sqrt U) O(nU), n n n为 n u m s nums nums的长度, U = m a x ( n u m s ) U=max(nums) U=max(nums)
- 空间复杂度: O ( U l o g U ) O(\frac {U}{logU}) O(logUU),最多有 U l o g U \frac {U}{logU} logUU个质因数
- 复杂度
将字符串分割成值不超过 K 的子字符串
You are given a string
s
consisting of digits from1
to9
and an integerk
.A partition of a string
s
is called good if:
- Each digit of
s
is part of exactly one substring.- The value of each substring is less than or equal to
k
.Return the minimum number of substrings in a good partition of
s
. If no good partition ofs
exists, return-1
.Note that:
- The value of a string is its result when interpreted as an integer. For example, the value of
"123"
is123
and the value of"1"
is1
.- A substring is a contiguous sequence of characters within a string.
-
思路:贪心划分子字符串,保证每个子字符串的长度为所能够到达的最大长度,假设
k
的位数为n
,子字符串的左边界为 l l l,如果s.substring(l, l+n)对应的整数大小小于等于k
,那么该子字符串即为最优子字符串;反之,s.substring(l, l+n - 1)为最优子字符串- 局部最优:每个子字符串的长度为最大长度
- 全局最优:子字符串个数最少
-
实现
注意右边界的处理和 k k k小于10的处理
- 保证右边界小于等于字符串长度,如果右边界超出字符串长度,那么直接取最大值
- 如果k小于10时,可能出现不能划分好字符串的情况,即字符串中的单个数值大于k时,此时返回-1
class Solution { public int minimumPartition(String s, int k) { int n = 1; int temp = k; while (temp / 10 > 0){ temp /= 10; n++; } int l = 0, m = s.length(), ans = 0; while (l < m){ int r = l + n <= m ? l + n : m; if (Integer.parseInt(s.substring(l,r)) <= k){ l += n; ans++; }else if(n == 1){ return -1; }else{ l += n - 1; ans++; } } return ans; } }
- 复杂度
- 时间复杂度:
O
(
m
+
l
o
g
k
)
O(m+logk)
O(m+logk),
n
n
n为
k
k
k的数位数量,
m
m
m为
s
的长度 - 空间复杂度: O ( 1 ) O(1) O(1)
- 时间复杂度:
O
(
m
+
l
o
g
k
)
O(m+logk)
O(m+logk),
n
n
n为
k
k
k的数位数量,
m
m
m为
-
在遍历的过程中计算子字符串的整数值,不使用Integer.parseInt
// arignote class Solution { public int minimumPartition(String s, int k) { int count = 0; for (int i = 0; i < s.length(); count++) { if (s.charAt(i) - '0' > k) { return -1; } for (long curr = 0; i < s.length() && (curr = curr * 10 + s.charAt(i) - '0') <= k; i++) { } } return count; } }
- 复杂度
- 时间复杂度:
O
(
m
)
O(m)
O(m),
n
n
n为
k
k
k的数位数量,
m
m
m为
s
的长度 - 空间复杂度: O ( 1 ) O(1) O(1)
- 时间复杂度:
O
(
m
)
O(m)
O(m),
n
n
n为
k
k
k的数位数量,
m
m
m为
- 复杂度
范围内最接近的两个质数
Given two positive integers
left
andright
, find the two integersnum1
andnum2
such that:
left <= nums1 < nums2 <= right
.nums1
andnums2
are both prime numbers.nums2 - nums1
is the minimum amongst all other pairs satisfying the above conditions.Return the positive integer array
ans = [nums1, nums2]
. If there are multiple pairs satisfying these conditions, return the one with the minimumnums1
value or[-1, -1]
if such numbers do not exist.A number greater than
1
is called prime if it is only divisible by1
and itself.
-
思路:求出区间 [ l e f t , r i g h t ] [left,right] [left,right]范围的所有质数,并使用变量
pre
记录前一个质数的大小,dis
记录最小质数距离,如果当前质数与前一个质数的距离小于当前最小距离,那么更新结果集。 -
实现
class Solution { public int[] closestPrimes(int left, int right) { int[] res = {-1, -1}; int pre = -1; int dis = Integer.MAX_VALUE; for (int i = left; i <= right; i++){ if (isPrime(i)){ if (pre != -1 && i - pre < dis){ dis = i - pre; res[0] = pre; res[1] = i; } pre = i; } } return res; } public boolean isPrime(int x){ if (x == 1){ return false; } for (int i = 2; i * i <= x; i++){ if (x % i == 0){ return false; } } return true; } }
- 复杂度
- 时间复杂度: O ( n l o g n ) O(nlogn) O(nlogn)
- 空间复杂度: O ( 1 ) O(1) O(1)
- 复杂度
-
优化:避免重复判断一个数是否是质数,可以提前打表,由于整数范围为 [ 2 , 100000 ] [2,100000] [2,100000],可以将该范围内的数进行预处理,然后找到 [ l e f t , r i g h t ] [left,right] [left,right]范围内的质数,找到相邻的距离最小的两个质数进行返回
// arignote class Solution { private static ArrayList<Integer> list = new ArrayList<>() { { Boolean[] prime = new Boolean[1000000]; for (int i = 2; i < 1000000; i++) { if (prime[i] == null) { add(i); for (int j = 2 * i; j < 1000000; j += i) { prime[j] = false; } } } } }; public int[] closestPrimes(int left, int right) { int[] result = { -1, -1 }; for (int i = 1; i < list.size(); i++) { if (list.get(i - 1) >= left && list.get(i) <= right && (result[0] < 0 || list.get(i) - list.get(i - 1) < result[1] - result[0])) { result = new int[] { list.get(i - 1), list.get(i) }; } } return result; } }