时间复杂度(Java,快速排序)
Time complexity(Java, Quicksort)
我有一个关于计算时间复杂度(大 O 表示法)的非常普遍的问题。当人们说 QuickSort 的最差时间复杂度是 O(n^2)(每次都选择数组的第一个元素作为基准,并且数组是反向排序的)时,他们考虑了哪个操作来得到 O(n ^2)?人们会计算 if/else 语句所做的比较吗?或者他们只计算它进行的掉期总数?一般来说,你怎么知道要计算哪个"steps"来计算大O符号。
我知道这是一个非常基本的问题,但是我已经阅读了几乎所有关于 google 的文章,但仍然没有弄明白
快速排序的最坏情况
快速排序的最坏情况是数组被逆向排序,正常排序并且所有元素都相等。
了解大佬
说到这里,我们先来了解一下Big-Oh of something是什么意思吧。
当我们只有渐近上界时,我们使用 O-notation。对于给定的函数 g(n),我们用 O(g(n)) 表示函数集,
O(g(n)) = { f(n) : 存在正 c 和 no,
这样 0<= f(n) <= cg(n) 对于所有 n >= no}
我们如何计算Big-Oh?
Big-Oh 基本上意味着程序的复杂性如何随着输入大小而增加。
代码如下:
import java.util.*;
class QuickSort
{
static int partition(int A[],int p,int r)
{
int x = A[r];
int i=p-1;
for(int j=p;j<=r-1;j++)
{
if(A[j]<=x)
{
i++;
int t = A[i];
A[i] = A[j];
A[j] = t;
}
}
int temp = A[i+1];
A[i+1] = A[r];
A[r] = temp;
return i+1;
}
static void quickSort(int A[],int p,int r)
{
if(p<r)
{
int q = partition(A,p,r);
quickSort(A,p,q-1);
quickSort(A,q+1,r);
}
}
public static void main(String[] args) {
int A[] = {5,9,2,7,6,3,8,4,1,0};
quickSort(A,0,9);
Arrays.stream(A).forEach(System.out::println);
}
}
考虑以下陈述:
区块 1:
int x = A[r];
int i=p-1;
第 2 块:
if(A[j]<=x)
{
i++;
int t = A[i];
A[i] = A[j];
A[j] = t;
}
区块 3:
int temp = A[i+1];
A[i+1] = A[r];
A[r] = temp;
return i+1;
区块 4:
if(p<r)
{
int q = partition(A,p,r);
quickSort(A,p,q-1);
quickSort(A,q+1,r);
}
假设每条语句花费固定时间c。让我们计算一下每个块计算了多少次。
第一个块被执行 2c 次。
第二个块执行 5c 次。
口渴块被执行4c次。
我们将其写为 O(1),这意味着即使输入大小不同,语句执行的次数也相同。所有 2c、5c 和 4c 都是 O(1)。
但是,当我们在第二个块上添加循环时
for(int j=p;j<=r-1;j++)
{
if(A[j]<=x)
{
i++;
int t = A[i];
A[i] = A[j];
A[j] = t;
}
}
它运行s n次(假设r-p等于n,输入的大小)即nO(1)次即O(n ).但这并不是每次都 运行 n 次。因此,我们有平均情况 O(log n),即至少遍历 log(n) 个元素。
我们现在确定分区 运行s O(n) 或 O(log n)。最后一个块,即 quickSort 方法,在 O(n) 中定义为 运行s。我们可以将其视为一个包含 运行s n 次的封闭 for 循环。因此整个复杂度是 O(n2) 或 O(nlog n).
主要是看可以增长的大小(n),所以对于数组快排就是数组的大小。您需要访问数组的每个元素多少次?如果你只需要访问每个元素一次那么它是一个 O(n) 等等..
随着n的增长而增长的临时变量/局部变量将被计算在内。
其他在n增长时增长不明显的变量可以算作常量:O(n) + c = O(n)
只是补充一下其他人所说的,我同意那些说你计算一切的人,但如果我没记错的话我在大学 类 的算法,与比较相比,交换开销通常是最小的次,在某些情况下为 0(如果相关列表已经排序)。
例如。线性搜索的公式是
T= K * N / 2.
其中T是总时间; K 是定义总计算时间的常数; N 是列表中的元素数。
平均而言,比较次数为N/2。
但我们可以将其重写为以下内容:
T = (K/2) * N
或重新定义K,
T = K * N.
这就明确了时间与N的大小成正比,这才是我们真正关心的。随着 N 显着增加,它成为唯一真正重要的东西。
另一方面,二进制搜索以对数方式增长 (O log(N))。
我有一个关于计算时间复杂度(大 O 表示法)的非常普遍的问题。当人们说 QuickSort 的最差时间复杂度是 O(n^2)(每次都选择数组的第一个元素作为基准,并且数组是反向排序的)时,他们考虑了哪个操作来得到 O(n ^2)?人们会计算 if/else 语句所做的比较吗?或者他们只计算它进行的掉期总数?一般来说,你怎么知道要计算哪个"steps"来计算大O符号。
我知道这是一个非常基本的问题,但是我已经阅读了几乎所有关于 google 的文章,但仍然没有弄明白
快速排序的最坏情况
快速排序的最坏情况是数组被逆向排序,正常排序并且所有元素都相等。
了解大佬
说到这里,我们先来了解一下Big-Oh of something是什么意思吧。
当我们只有渐近上界时,我们使用 O-notation。对于给定的函数 g(n),我们用 O(g(n)) 表示函数集,
O(g(n)) = { f(n) : 存在正 c 和 no,
这样 0<= f(n) <= cg(n) 对于所有 n >= no}
我们如何计算Big-Oh?
Big-Oh 基本上意味着程序的复杂性如何随着输入大小而增加。
代码如下:
import java.util.*;
class QuickSort
{
static int partition(int A[],int p,int r)
{
int x = A[r];
int i=p-1;
for(int j=p;j<=r-1;j++)
{
if(A[j]<=x)
{
i++;
int t = A[i];
A[i] = A[j];
A[j] = t;
}
}
int temp = A[i+1];
A[i+1] = A[r];
A[r] = temp;
return i+1;
}
static void quickSort(int A[],int p,int r)
{
if(p<r)
{
int q = partition(A,p,r);
quickSort(A,p,q-1);
quickSort(A,q+1,r);
}
}
public static void main(String[] args) {
int A[] = {5,9,2,7,6,3,8,4,1,0};
quickSort(A,0,9);
Arrays.stream(A).forEach(System.out::println);
}
}
考虑以下陈述:
区块 1:
int x = A[r];
int i=p-1;
第 2 块:
if(A[j]<=x)
{
i++;
int t = A[i];
A[i] = A[j];
A[j] = t;
}
区块 3:
int temp = A[i+1];
A[i+1] = A[r];
A[r] = temp;
return i+1;
区块 4:
if(p<r)
{
int q = partition(A,p,r);
quickSort(A,p,q-1);
quickSort(A,q+1,r);
}
假设每条语句花费固定时间c。让我们计算一下每个块计算了多少次。
第一个块被执行 2c 次。 第二个块执行 5c 次。 口渴块被执行4c次。
我们将其写为 O(1),这意味着即使输入大小不同,语句执行的次数也相同。所有 2c、5c 和 4c 都是 O(1)。
但是,当我们在第二个块上添加循环时
for(int j=p;j<=r-1;j++)
{
if(A[j]<=x)
{
i++;
int t = A[i];
A[i] = A[j];
A[j] = t;
}
}
它运行s n次(假设r-p等于n,输入的大小)即nO(1)次即O(n ).但这并不是每次都 运行 n 次。因此,我们有平均情况 O(log n),即至少遍历 log(n) 个元素。
我们现在确定分区 运行s O(n) 或 O(log n)。最后一个块,即 quickSort 方法,在 O(n) 中定义为 运行s。我们可以将其视为一个包含 运行s n 次的封闭 for 循环。因此整个复杂度是 O(n2) 或 O(nlog n).
主要是看可以增长的大小(n),所以对于数组快排就是数组的大小。您需要访问数组的每个元素多少次?如果你只需要访问每个元素一次那么它是一个 O(n) 等等..
随着n的增长而增长的临时变量/局部变量将被计算在内。 其他在n增长时增长不明显的变量可以算作常量:O(n) + c = O(n)
只是补充一下其他人所说的,我同意那些说你计算一切的人,但如果我没记错的话我在大学 类 的算法,与比较相比,交换开销通常是最小的次,在某些情况下为 0(如果相关列表已经排序)。
例如。线性搜索的公式是
T= K * N / 2.
其中T是总时间; K 是定义总计算时间的常数; N 是列表中的元素数。
平均而言,比较次数为N/2。
但我们可以将其重写为以下内容:
T = (K/2) * N
或重新定义K,
T = K * N.
这就明确了时间与N的大小成正比,这才是我们真正关心的。随着 N 显着增加,它成为唯一真正重要的东西。
另一方面,二进制搜索以对数方式增长 (O log(N))。