Quelqu'un peut-il me donner un exemple d'algorithme qui a une complexité temporelle racine carrée (n). Que signifie la complexité du temps de racine carrée?
O(N^(1/2))
où la taille de l'entrée est N.O(sqrt(n))
temps, l'algorithme de Grover est celui qui prend autant de temps. algorithme de Grover est un algorithme quantique pour rechercher une base de données non triée de n entrées en O(sqrt(n))
temps.Prenons un exemple pour comprendre comment arriver à la complexité d'exécution de O(sqrt(N))
, étant donné un problème. Cela va être élaboré, mais c'est intéressant à comprendre. (L'exemple suivant, dans le contexte de réponse à cette question, est tiré de Coding Contest Byte: The Square Root Trick , problème très intéressant et astuce intéressante pour arriver à la complexité de O(sqrt(n))
)
Étant donné A, contenant un tableau de n éléments, implémentez une structure de données pour les mises à jour de points et les requêtes de somme de plage.
La solution naïve utilise un tableau. Cela prend O(1)
temps pour une mise à jour (accès à l'index du tableau) et O(hi - lo) = O(n)
pour la somme de la plage (itération de l'index de début à l'index de fin et additionnement).
query(2, 14) = A[2] + A[3]+ (A[4] + A[5] + A[6] + A[7]) + (A[8] + A[9] + A[10] + A[11]) + A[12] + A[13] + A[14] ;
query(2, 14) = A[2] + A[3] + S[1] + S[2] + A[12] + A[13] + A[14] ;
query(2, 14) = 0 + 7 + 11 + 9 + 5 + 2 + 0;
query(2, 14) = 34;
def update(S, A, i, k, x):
S[i/k] = S[i/k] - A[i] + x
A[i] = x
def query(S, A, lo, hi, k):
s = 0
i = lo
//Section 1 (Getting sum from Array A itself, starting part)
while (i + 1) % k != 0 and i <= hi:
s += A[i]
i += 1
//Section 2 (Getting sum from Slices directly, intermediary part)
while i + k <= hi:
s += S[i/k]
i += k
//Section 3 (Getting sum from Array A itself, ending part)
while i <= hi:
s += A[i]
i += 1
return s
O(sqrt(n))
.Nombres premiers
Comme mentionné dans certaines autres réponses, certaines choses de base liées aux nombres premiers prennent O(sqrt(n)) fois:
Ci-dessous, je mentionne deux algorithmes avancés qui portent également le terme sqrt (n) dans leur complexité.
Algorithme de MO
essayez ce problème: Puissant tablea
Ma solution:
#include <bits/stdc++.h>
using namespace std;
const int N = 1E6 + 10, k = 500;
struct node {
int l, r, id;
bool operator<(const node &a) {
if(l / k == a.l / k) return r < a.r;
else return l < a.l;
}
} q[N];
long long a[N], cnt[N], ans[N], cur_count;
void add(int pos) {
cur_count += a[pos] * cnt[a[pos]];
++cnt[a[pos]];
cur_count += a[pos] * cnt[a[pos]];
}
void rm(int pos) {
cur_count -= a[pos] * cnt[a[pos]];
--cnt[a[pos]];
cur_count -= a[pos] * cnt[a[pos]];
}
int main() {
int n, t;
cin >> n >> t;
for(int i = 1; i <= n; i++) {
cin >> a[i];
}
for(int i = 0; i < t; i++) {
cin >> q[i].l >> q[i].r;
q[i].id = i;
}
sort(q, q + t);
memset(cnt, 0, sizeof(cnt));
memset(ans, 0, sizeof(ans));
int curl(0), curr(0), l, r;
for(int i = 0; i < t; i++) {
l = q[i].l;
r = q[i].r;
/* This part takes O(n * sqrt(n)) time */
while(curl < l)
rm(curl++);
while(curl > l)
add(--curl);
while(curr > r)
rm(curr--);
while(curr < r)
add(++curr);
ans[q[i].id] = cur_count;
}
for(int i = 0; i < t; i++) {
cout << ans[i] << '\n';
}
return 0;
}
Mise en mémoire tampon des requêtes
essayez ce problème: Requêtes sur un arbre
Ma solution:
#include <bits/stdc++.h>
using namespace std;
const int N = 2e5 + 10, k = 333;
vector<int> t[N], ht;
int tm_, h[N], st[N], nd[N];
inline int hei(int v, int p) {
for(int ch: t[v]) {
if(ch != p) {
h[ch] = h[v] + 1;
hei(ch, v);
}
}
}
inline void tour(int v, int p) {
st[v] = tm_++;
ht.Push_back(h[v]);
for(int ch: t[v]) {
if(ch != p) {
tour(ch, v);
}
}
ht.Push_back(h[v]);
nd[v] = tm_++;
}
int n, tc[N];
vector<int> loc[N];
long long balance[N];
vector<pair<long long,long long>> buf;
inline long long cbal(int v, int p) {
long long ans = balance[h[v]];
for(int ch: t[v]) {
if(ch != p) {
ans += cbal(ch, v);
}
}
tc[v] += ans;
return ans;
}
inline void bal() {
memset(balance, 0, sizeof(balance));
for(auto arg: buf) {
balance[arg.first] += arg.second;
}
buf.clear();
cbal(1,1);
}
int main() {
int q;
cin >> n >> q;
for(int i = 1; i < n; i++) {
int x, y; cin >> x >> y;
t[x].Push_back(y); t[y].Push_back(x);
}
hei(1,1);
tour(1,1);
for(int i = 0; i < ht.size(); i++) {
loc[ht[i]].Push_back(i);
}
vector<int>::iterator lo, hi;
int x, y, type;
for(int i = 0; i < q; i++) {
cin >> type;
if(type == 1) {
cin >> x >> y;
buf.Push_back(make_pair(x,y));
}
else if(type == 2) {
cin >> x;
long long ans(0);
for(auto arg: buf) {
hi = upper_bound(loc[arg.first].begin(), loc[arg.first].end(), nd[x]);
lo = lower_bound(loc[arg.first].begin(), loc[arg.first].end(), st[x]);
ans += arg.second * (hi - lo);
}
cout << tc[x] + ans/2 << '\n';
}
else assert(0);
if(i % k == 0) bal();
}
}
Il existe de nombreux cas. Ce sont les quelques problèmes qui peuvent être résolus dans la complexité root (n) [mieux peut être possible aussi].
Vous rencontrerez de nombreux problèmes qui nécessiteront l'utilisation de l'algorithme de complexité sqrt(n)
.
la complexité sqrt (n) signifie if the input size to your algorithm is n then there approximately sqrt(n) basic operations ( like **comparison** in case of sorting). Then we can say that the algorithm has sqrt(n) time complexity.
Analysons le 3ème problème et ce sera clair.
let's n= positive integer. Now there exists 2 positive integer x and y such that
x*y=n;
Now we know that whatever be the value of x and y one of them will be less than sqrt(n). As if both are greater than sqrt(n)
x>sqrt(n) y>sqrt(n) then x*y>sqrt(n)*sqrt(n) => n>n--->contradiction.
Donc, si nous vérifions 2 à sqrt (n) alors nous aurons tous les facteurs considérés (1 et n sont des facteurs triviaux).
int n;
cin>>n;
print 1,n;
for(int i=2;i<=sqrt(n);i++) // or for(int i=2;i*i<=n;i++)
if((n%i)==0)
cout<<i<<" ";
Remarque: Vous pourriez penser qu'en ne tenant pas compte du doublon, nous pouvons également obtenir le comportement ci-dessus en bouclant de 1 à n. Oui c'est possible mais qui veut exécuter un programme qui peut s'exécuter en O(sqrt(n)) en O (n) .. Nous recherchons toujours le meilleur.
Parcourez le livre de Cormen Introduction aux algorithmes .
Je vous demanderai également de lire la question et les réponses de stackoverflow suivantes, ils dissiperont tous les doutes à coup sûr :)
const isPrime = n => {
for(let i = 2; i <= Math.sqrt(n); i++) {
if(n % i === 0) return false;
}
return true;
};
O (N ^ 1/2) Parce que, pour une valeur donnée de n, il suffit de trouver si son divisible par des nombres de 2 à sa racine.