Medium
题目描述
给定一个字符串 s,找出可以由其任意子串形成的 3 个最大的不同质数的和。
返回可以形成的三个最大不同质数的和。如果少于三个质数,则返回所有可用质数的和。如果无法形成质数,则返回 0。
注意:每个质数只应计算一次,即使它出现在多个子串中。此外,将子串转换为整数时,任何前导零都会被忽略。
示例 1:
输入:s = "12234"
输出:1469
解释:
从 "12234" 的子串中形成的不同质数有 2, 3, 23, 223, 和 1223。
3 个最大的质数是 1223, 223, 和 23。它们的和是 1469。
示例 2:
输入:s = "111"
输出:11
解释:
从 "111" 的子串中形成的不同质数是 11。
由于只有一个质数,所以和是 11。
约束:
1 <= s.length <= 10s只包含数字。
解题思路
这道题需要我们找出字符串中所有可能子串形成的质数,然后返回最大的三个质数之和。
解题思路:
生成所有子串:遍历字符串的所有可能子串,将其转换为整数。需要注意处理前导零的情况。
质数判断:对每个生成的数字进行质数判断。可以使用经典的质数判断算法:检查从2到√n的所有数字是否能整除n。
去重存储:使用集合(Set)来存储所有找到的质数,自动去重。
排序取最大值:将所有质数排序,取最大的三个(如果不足三个则取全部)求和。
算法步骤:
- 双重循环生成所有子串
- 将子串转换为整数(自动处理前导零)
- 对每个整数进行质数检测
- 将质数存入集合去重
- 对质数集合排序,取前3个最大值求和
时间复杂度优化: 由于字符串长度最大为10,所以最多有55个子串,每个子串最大值不超过10^10,质数判断的时间复杂度为O(√n),总体复杂度是可接受的。
代码实现
class Solution {
public:
bool isPrime(long long n) {
if (n < 2) return false;
if (n == 2) return true;
if (n % 2 == 0) return false;
for (long long i = 3; i * i <= n; i += 2) {
if (n % i == 0) return false;
}
return true;
}
long long sumOfLargestPrimes(string s) {
set<long long> primes;
int n = s.length();
for (int i = 0; i < n; i++) {
for (int j = i; j < n; j++) {
string substr = s.substr(i, j - i + 1);
long long num = stoll(substr);
if (isPrime(num)) {
primes.insert(num);
}
}
}
vector<long long> primeList(primes.rbegin(), primes.rend());
long long sum = 0;
for (int i = 0; i < min(3, (int)primeList.size()); i++) {
sum += primeList[i];
}
return sum;
}
};
class Solution:
def isPrime(self, n):
if n < 2:
return False
if n == 2:
return True
if n % 2 == 0:
return False
for i in range(3, int(n**0.5) + 1, 2):
if n % i == 0:
return False
return True
def sumOfLargestPrimes(self, s: str) -> int:
primes = set()
n = len(s)
for i in range(n):
for j in range(i, n):
substr = s[i:j+1]
num = int(substr)
if self.isPrime(num):
primes.add(num)
prime_list = sorted(primes, reverse=True)
return sum(prime_list[:3])
public class Solution {
private bool IsPrime(long n) {
if (n < 2) return false;
if (n == 2) return true;
if (n % 2 == 0) return false;
for (long i = 3; i * i <= n; i += 2) {
if (n % i == 0) return false;
}
return true;
}
public long SumOfLargestPrimes(string s) {
HashSet<long> primes = new HashSet<long>();
int n = s.Length;
for (int i = 0; i < n; i++) {
for (int j = i; j < n; j++) {
string substr = s.Substring(i, j - i + 1);
long num = long.Parse(substr);
if (IsPrime(num)) {
primes.Add(num);
}
}
}
var primeList = primes.OrderByDescending(x => x).ToList();
long sum = 0;
for (int i = 0; i < Math.Min(3, primeList.Count); i++) {
sum += primeList[i];
}
return sum;
}
}
/**
* @param {string} s
* @return {number}
*/
var sumOfLargestPrimes = function(s) {
function isPrime(n) {
if (n < 2) return false;
if (n === 2) return true;
if (n % 2 === 0) return false;
for (let i = 3; i * i <= n; i += 2) {
if (n % i === 0) return false;
}
return true;
}
const primes = new Set();
for (let i = 0; i < s.length; i++) {
for (let j = i; j < s.length; j++) {
const substring = s.slice(i, j + 1);
const num = parseInt(substring);
if (isPrime(num)) {
primes.add(num);
}
}
}
const sortedPrimes = Array.from(primes).sort((a, b) => b - a);
return sortedPrimes.slice(0, 3).reduce((sum, prime) => sum + prime, 0);
};
复杂度分析
| 复杂度类型 | 复杂度 | 说明 |
|---|---|---|
| 时间复杂度 | O(n² × √m) | n为字符串长度,m为子串对应的最大数值,需要生成O(n²)个子串,每个子串需要O(√m)时间判断质数 |
| 空间复杂度 | O(k) | k为不同质数的个数,用于存储质数集合 |