算法中O字符解释

出处:stackoverflow

伯乐在线有同志翻译了一下:http://blog.jobbole.com/55184/

Big O complexity can be visualized with this graph:

The simplest definition I can give for Big-O notation is this:

Big-O notation is a relative representation of the complexity of an algorithm.

There are some important and deliberately chosen words in that sentence:

  • relative: you can only compare apples to apples. You can‘t compare an algorithm to do arithmetic multiplication to an algorithm that sorts a list of integers. But a comparison of two algorithms to do arithmetic operations (one multiplication, one addition) will tell you something meaningful;
  • representation: Big-O (in its simplest form) reduces the comparison between algorithms to a single variable. That variable is chosen based on observations or assumptions. For example, sorting algorithms are typically compared based on comparison operations (comparing two nodes to determine their relative ordering). This assumes that comparison is expensive. But what if comparison is cheap but swapping is expensive? It changes the comparison; and
  • complexity: if it takes me one second to sort 10,000 elements how long will it take me to sort one million? Complexity in this instance is a relative measure to something else.

Come back and reread the above when you‘ve read the rest.

The best example of Big-O I can think of is doing arithmetic. Take two numbers (123456 and 789012). The basic arithmetic operations we learnt in school were:

  • addition;
  • subtraction;
  • multiplication; and
  • division.

Each of these is an operation or a problem. A method of solving these is called an algorithm.

Addition is the simplest. You line the numbers up (to the right) and add the digits in a column writing the last number of that addition in the result. The ‘tens‘ part of that number is carried over to the next column.

Let‘s assume that the addition of these numbers is the most expensive operation in this algorithm. It stands to reason that to add these two numbers together we have to add together 6 digits (and possibly carry a 7th). If we add two 100 digit numbers together we have to do 100 additions. If we add two 10,000 digit numbers we have to do 10,000 additions.

See the pattern? The complexity (being the number of operations) is directly proportional to the number of digits n in the larger number. We call this O(n) or linear complexity.

Subtraction is similar (except you may need to borrow instead of carry).

Multiplication is different. You line the numbers up, take the first digit in the bottom number and multiply it in turn against each digit in the top number and so on through each digit. So to multiply our two 6 digit numbers we must do 36 multiplications. We may need to do as many as 10 or 11 column adds to get the end result too.

If we have two 100-digit numbers we need to do 10,000 multiplications and 200 adds. For two one million digit numbers we need to do one trillion (1012) multiplications and two million adds.

As the algorithm scales with n-squared, this is O(n2) or quadratic complexity. This is a good time to introduce another important concept:

We only care about the most significant portion of complexity.

The astute may have realized that we could express the number of operations as: n2 + 2n. But as you saw from our example with two numbers of a million digits apiece, the second term (2n) becomes insignificant (accounting for 0.0002% of the total operations by that stage).

One can notice that we‘ve assumed the worst case scenario here. While multiplying 6 digit numbers if one of them is 4 digit and the other one is 6 digit, then we only have 24 multiplications. Still we calculate the worst case scenario for that ‘n‘, i.e when both are 6 digit numbers. Hence Big-O notation is about the Worst-case scenario of an algorithm

The Telephone Book

The next best example I can think of is the telephone book, normally called the White Pages or similar but it‘ll vary from country to country. But I‘m talking about the one that lists people by surname and then initials or first name, possibly address and then telephone numbers.

Now if you were instructing a computer to look up the phone number for "John Smith" in a telephone book that contains 1,000,000 names, what would you do? Ignoring the fact that you could guess how far in the S‘s started (let‘s assume you can‘t), what would you do?

A typical implementation might be to open up to the middle, take the 500,000th and compare it to "Smith". If it happens to be "Smith, John", we just got real lucky. Far more likely is that "John Smith" will be before or after that name. If it‘s after we then divide the last half of the phone book in half and repeat. If it‘s before then we divide the first half of the phone book in half and repeat. And so on.

This is called a binary search and is used every day in programming whether you realize it or not.

So if you want to find a name in a phone book of a million names you can actually find any name by doing this at most 20 times. In comparing search algorithms we decide that this comparison is our ‘n‘.

  • For a phone book of 3 names it takes 2 comparisons (at most).
  • For 7 it takes at most 3.
  • For 15 it takes 4.
  • For 1,000,000 it takes 20.

That is staggeringly good isn‘t it?

In Big-O terms this is O(log n) or logarithmic complexity. Now the logarithm in question could be ln (base e), log10, log2 or some other base. It doesn‘t matter it‘s still O(log n) just like O(2n2) and O(100n2) are still both O(n2).

It‘s worthwhile at this point to explain that Big O can be used to determine three cases with an algorithm:

  • Best Case: In the telephone book search, the best case is that we find the name in one comparison. This is O(1) or constant complexity;
  • Expected Case: As discussed above this is O(log n); and
  • Worst Case: This is also O(log n).

Normally we don‘t care about the best case. We‘re interested in the expected and worst case. Sometimes one or the other of these will be more important.

Back to the telephone book.

What if you have a phone number and want to find a name? The police have a reverse phone book but such look-ups are denied to the general public. Or are they? Technically you can reverse look-up a number in an ordinary phone book. How?

You start at the first name and compare the number. If it‘s a match, great, if not, you move on to the next. You have to do it this way because the phone book is unordered (by phone number anyway).

So to find a name given the phone number (reverse lookup):

  • Best Case: O(1);
  • Expected Case: O(n) (for 500,000); and
  • Worst Case: O(n) (for 1,000,000).

The Travelling Salesman

This is quite a famous problem in computer science and deserves a mention. In this problem you have N towns. Each of those towns is linked to 1 or more other towns by a road of a certain distance. The Travelling Salesman problem is to find the shortest tour that visits every town.

Sounds simple? Think again.

If you have 3 towns A, B and C with roads between all pairs then you could go:

  • A → B → C
  • A → C → B
  • B → C → A
  • B → A → C
  • C → A → B
  • C → B → A

Well actually there‘s less than that because some of these are equivalent (A → B → C and C → B → A are equivalent, for example, because they use the same roads, just in reverse).

In actuality there are 3 possibilities.

  • Take this to 4 towns and you have (iirc) 12 possibilities.
  • With 5 it‘s 60.
  • 6 becomes 360.

This is a function of a mathematical operation called a factorial. Basically:

  • 5! = 5 × 4 × 3 × 2 × 1 = 120
  • 6! = 6 × 5 × 4 × 3 × 2 × 1 = 720
  • 7! = 7 × 6 × 5 × 4 × 3 × 2 × 1 = 5040
  • 25! = 25 × 24 × … × 2 × 1 = 15,511,210,043,330,985,984,000,000
  • 50! = 50 × 49 × … × 2 × 1 = 3.04140932 × 1064

So the Big-O of the Travelling Salesman problem is O(n!) or factorial or combinatorial complexity.

By the time you get to 200 towns there isn‘t enough time left in the universe to solve the problem with traditional computers.

Something to think about.

Polynomial Time

Another point I wanted to make quick mention of is that any algorithm that has a complexity of O(na) is said to have polynomial complexity or is solvable in polynomial time.

O(n), O(n2) etc are all polynomial time. Some problems cannot be solved in polynomial time. Certain things are used in the world because of this. Public Key Cryptography is a prime example. It is computationally hard to find two prime factors of a very large number. If it wasn‘t, we couldn‘t use the public key systems we use.

Anyway, that‘s it for my (hopefully plain English) explanation of Big O (revised).

时间: 2024-08-01 10:46:43

算法中O字符解释的相关文章

微软算法100题88 将字符串中的字符'*'移到串的前部分

函数将字符串中的字符'*'移到串的前部分,前面的非'*'字符后移,但不能改变非'*'字符的先后顺序,函数返回串中字符'*'的数量.如原始串为:ab**cd**e*12,处理后为*****abcde12,函数并返回值为5.(要求使用尽量少的时间和辅助空间) 思路:类似于快速排序,用两个指针分别指向字符数组的左右边界,寻找左边第一个不为*的字符,寻找右边第一个*,然后交换字符,然后继续寻找和交换的过程,直到两个指针相交, 时间复杂度o(n), 空间复杂度o(1) 第一个写的程序有问题,没有考虑到保持

关于DPM(Deformable Part Model)算法中模型可视化的解释

DPM源码(voc-release)中的模型可视化做的还算相当炫酷的,可以让我们直观的看到训练好的模型,甚至我们不用去做模型的评价,直接根据肉眼的观察,就能大致了解一个目标训练的好不好,比如我训练一个人体模型,那他的可视化图当然就是越接近人体越好. 下面是对DPM源码中有关模型可视化部分代码的分析,通过分析这些代码,有助于更好的理解DPM模型. 注意:我的源码版本是voc-release3.1,第4版往后的模型变得更复杂,这里不讨论. 有关模型可视化的代码主要在visualizemodel.m,

将数组中的字符按出现次数多少排序输出

原题 一个有N个元素的集合,其中有相同元素. 需要得到按重复元素多少排序的新集合. 输入  {"a","b","c","c","a","c"} 输出  {"c","a","b"} 求算法 import java.util.ArrayList; import java.util.Collections; import java.u

字符串模式匹配KMP算法中的next数组算法及C++实现

一.问题描述: 对于两个字符串S.T,找到T在S中第一次出现的起始位置,若T未在S中出现,则返回-1. 二.输入描述: 两个字符串S.T. 三.输出描述: 字符串T在S中第一次出现的起始位置,若未出现,则返回-1. 四.输入例子: ababaababcbababc 五.输出例子: 5 六.KMP算法解析: KMP算法分为两步,第一步是计算next数组,第二步是根据next数组通过较节省的方式回溯来比较两个字符串. 网络上不同文章关于next数组的角标含义略有差别,这里取参考文献中王红梅<数据结构

由“Java中一个字符占两个字节”引起

起因 Java中一个字符占两个字节,这和C/C++稍有区别.在C/C++中我们可以通过sizeof运算符方便地知道某个变量类型或对象的大小,那在Java中又如何? 问题出现 Java为什么没有提供sizeof运算符? 要回答这个问题,我们可以从另一个角度来看,那就是为什么C/C++中提供sizeof运算符.这就让人忍不住想到C/C++和Java在内存管理上的区别. 在C中,内存分配和释放的任务交给了程序员,当我们尝试用malloc为某个对象分配一块堆内存时,一个无法逃避的问题是,这个即将被创建的

Oracle sql 中的字符(串)替换与转换[转载]

1.REPLACE 语法:REPLACE(char, search_string,replacement_string) 用法:将char中的字符串search_string全部转换为字符串replacement_string.       举例:SQL> select REPLACE('fgsgswsgs', 'fk' ,'j') 返回值 from dual;            返回值            ---------            fgsgswsgs SQL> sele

正则表达式中各字符的含义

正则表达式中各种字符的含义 正则表达式(regular expression)描述了一种字符串匹配的模式,可以用来检查一个串是否含有某种子串.将匹配的子串做替换或者从某个串中取出符合某个条件的子串等. 列目录时, dir *.txt或ls *.txt中的*.txt就不是一个正则表达式,因为这里*与正则式的*的含义是不同的. 正则表达式是由普通字符(例如字符 a 到 z)以及特殊字符(称为元字符)组成的文字模式.正则表达式作为一个模板,将某个字符模式与所搜索的字符串进行匹配. 3.1 普通字符 由

java中的容器解释

解释一:容器(Container)Spring 提供容器功能,容器可以管理对象的生命周期.对象与对象之间的依赖关系,您可以使用一个配置文件(通常是XML),在上面定义好对象的名称.如何产生(Prototype 方式或Singleton 方式).哪个对象产生之后必须设定成为某个对象的属性等,在启动容器之后,所有的对象都可以直接取用,不用编写任何一行程序代码来产生对象,或是建立对象与对象之间的依赖关系.换个更直白点的说明方式:容器是一个Java 所编写的程序,原先必须自行编写程序以管理对象关系,现在

1161: 零起点学算法68——删除字符(未AC)

1161: 零起点学算法68--删除字符 Time Limit: 1 Sec  Memory Limit: 64 MB   64bit IO Format: %lldSubmitted: 1412  Accepted: 479[Submit][Status][Web Board] Description 从键盘输入任意一个字符串和一个字符,要求从该字符串中删除所有该字符. Input 输入有多组测试数据. 每组两行,第一行是字符串(字符串至少还有一个字符,不多于100个),第二行是一个字符 Ou