더 낮은 것보다 더 큰 big-O 시간 복잡성 알고리즘을 선호하는 경우가 있습니까?


242

O(log n)시간 복잡성보다 시간 복잡성을 선호하는 경우가 O(1)있습니까? 또는 O(n)O(log n)?

예가 있습니까?


67
나는 전자를 이해한다면 O(log n)알고리즘보다 알고리즘을 선호 O(1)하지만 후자는 이해하지 못한다 ...
Codor

14
이론적 인 컴퓨터 과학의 O (1) 연산으로 비실용적 인 데이터 구조가 많이 있습니다. 한 가지 예는 5 개의 간접 레이어를 사용하여 o (n) 개의 추가 공간과 연산 당 O (1)에서 지원 될 수있는 비트 벡터의 select ()입니다. O와 함께 간단한 이진 검색 (1) 순위 ()의 저자에 따라 실제로는 더 빨리 밝혀 간결 데이터 구조 라이브러리
니클라스 나에게

17
낮은 점근 복잡도는 더 빠른 런타임을 보장하지 않습니다. 구체적인 예를위한 리서치 행렬 곱셈.
코너 클라크

54
또한 ... 충분히 큰 테이블 조회가 주어지면 모든 알고리즘을 O (1)로 변환 할 수 있습니다.)
Connor Clark

19
@Hoten-테이블 조회가 O (1)이라고 가정합니다. 이것은 당신이 말하는 테이블의 크기에 대해 전혀 주어지지 않았습니다! :)
Jander

답변:


267

낮은 O보다 복잡한 O 시간 복잡성을 가진 알고리즘을 선호하는 데는 여러 가지 이유가있을 수 있습니다.

  • 대부분의 경우 Big-O 복잡성이 낮 으면 달성하기 어렵고 숙련 된 구현, 많은 지식 및 많은 테스트가 필요합니다.
  • big-O는 상수에 대한 세부 사항을 숨 깁니다. 수행하는 알고리즘은 ( vs ) 10^5보다 big-O 관점에서 더 좋지만 가장 합리적인 경우 첫 번째 알고리즘 이 더 잘 수행됩니다. 예를 들어 행렬 곱셈의 가장 복잡한 점 은 상수가 너무 커서 (내 지식으로는) 계산 라이브러리에서 사용하지 않습니다.1/10^5 * log(n)O(1)O(log(n)nO(n^2.373)
  • big-O는 큰 것을 계산할 때 의미가 있습니다. 세 개의 숫자 배열을 정렬 해야하는 경우 사용 O(n*log(n))또는 O(n^2)알고리즘 여부는 거의 중요하지 않습니다 .
  • 때때로 소문자 시간 복잡성의 이점은 실제로 무시할 수 있습니다. 예를 들어, 데이터 구조 탱고 트리는O(log log N) 항목을 찾기에 시간 복잡성을 제공 하지만,에서 동일한 것을 찾는 이진 트리도 있습니다 O(log n). 엄청난 n = 10^20차이 의 경우 에도 무시할 수 있습니다.
  • 시간의 복잡성이 전부는 아닙니다. 실행되고 메모리 O(n^2)가 필요한 알고리즘을 상상해보십시오 O(n^2). n이 실제로 크지 않은 경우 O(n^3)시간과 O(1)공간에 걸쳐 바람직 할 수 있습니다 . 문제는 오랫동안 기다릴 수 있지만 알고리즘과 함께 사용할 RAM을 충분히 찾을 수 있다는 것입니다.
  • 병렬화는 분산 된 세계에서 좋은 기능입니다. 쉽게 병렬화 할 수있는 알고리즘이 있으며 전혀 병렬화되지 않는 알고리즘이 있습니다. 때로는 약간 더 복잡한 하나의 컴퓨터를 사용하는 것보다 복잡도가 높은 1000 개의 상용 컴퓨터에서 알고리즘을 실행하는 것이 좋습니다.
  • 일부 장소 (보안)에서는 복잡성이 요구 될 수 있습니다. 누구도 굉장히 빨리 해시 할 수있는 해시 알고리즘을 원하지 않습니다.
  • 이것은 복잡성 전환과 관련이 없지만 일부 보안 기능은 타이밍 공격방지 하는 방식으로 작성되어야합니다 . 그것들은 대부분 같은 복잡성 클래스에 머물러 있지만 무언가를하기 위해서는 항상 더 나쁜 경우가되도록 수정됩니다. 한 예는 문자열이 같은지 비교하는 것입니다. 대부분의 응용 프로그램에서 첫 번째 바이트가 다르면 빠르게 중단되는 것이 합리적이지만 보안 상 끝까지 나쁜 소식을 전할 때까지 기다리게됩니다.
  • 누군가는 복잡성이 낮은 알고리즘에 대해 특허를 받았으며 회사가 돈을 지불하는 것보다 더 높은 복잡성을 사용하는 것이 더 경제적입니다.
  • 일부 알고리즘은 특정 상황에 잘 적응합니다. 예를 들어 삽입 정렬의 평균 복잡도는 O(n^2)퀵 정렬 또는 병합 정렬보다 나쁘지만 온라인 알고리즘 으로 대부분의 다른 알고리즘 만 효율적으로 작동 할 수있는 경우 사용자 입력으로 수신되는 값 목록을 효율적으로 정렬 할 수 있습니다 전체 값 목록에서.

6
또한 사람들이 중앙 알고리즘의 큰 O에 집중하지만 설치 비용을 무시하는 몇 번을 보았습니다. 예를 들어, 해시 테이블을 작성하는 것은 배열을 반복해서 반복 할 필요가 없다면 선형으로 진행하는 것보다 비용이 많이들 수 있습니다. 사실, 최신 CPU가 구축되는 방식으로 인해 이진 검색과 같은 것조차 선형 정렬만큼 정렬 된 배열에서 빠를 수 있습니다. 프로파일 링은 필수입니다.
Luaan

@Luaan "사실, 최신 CPU가 구축되는 방식으로 인해 이진 검색과 같은 것조차 선형 정렬만큼 정렬 된 배열에서도 빠를 수 있습니다. 프로파일 링은 필수입니다." 흥미 롭습니다! 최신 CPU에서 이진 검색과 선형 검색에 동일한 시간이 걸리는 방법을 설명 할 수 있습니까?
DJG

3
@Luaan-걱정 마세요, 이걸 찾았습니다 : schani.wordpress.com/2010/04/30/linear-vs-binary-search
DJG

2
@DenisdeBernardy : 아니요, 실제로는 그렇지 않습니다. 그것들은 P의 알고리즘 일 수 있습니다. 그리고 이것이 그렇지 않다하더라도, 병렬화의 의미에 대한 합리적인 정의 하에서 P! = NP를 의미하지는 않습니다. 또한 비 결정적 튜링 머신의 가능한 실행 공간을 검색하는 것은 매우 병렬화 할 수 있습니다.
einpoklum

228

숨겨진 상수는 항상 있으며 O (log n ) 알고리즘 에서 낮을 수 있습니다 . 따라서 실제 데이터에 대해 실제로 더 빠르게 작동 할 수 있습니다.

공간 문제도 있습니다 (예 : 토스터에서 실행).

개발자 시간 문제도 있습니다. O (log n )는 구현 및 확인이 1000 배 더 쉽습니다.


감사합니다 프로그램 안정성을 보장하기 위해 O (logn) 알고리즘을 고려할 가치가 있다고 생각했습니다 (예 : 자체 균형 이진 트리)
V.Leymarie

16
내가 생각할 수있는 한 가지 예 : 작은 정렬 된 배열의 경우 프로그래머가 완전한 해시 맵 구현을 작성하고 대신 사용하는 것보다 이진 검색 기능을 구현하는 것이 더 쉽고 간단합니다.
대령 삼십이

5
복잡성의 예 : 정렬되지 않은 목록의 중앙값을 찾는 것은 O (n * log n)에서는 쉽지만 O (n)에서는하기가 어렵습니다.
Paul Draper

1
-1, 토스터에 통나무를 넣지 마십시오. 대부분의 작업에서 차이를 인식하지 못할 lg n정도로 k큰 값에 가깝습니다 n.
corsiKa

3
또한 대부분의 사람들에게 익숙한 알고리즘 복잡성이 캐시 효과를 고려하지 않는다는 사실도 있습니다. 대부분의 사람들에 따르면 이진 트리에서 무언가를 찾는 것은 O (log2 (n))이지만 실제로는 이진 트리의 위치가 좋지 않기 때문에 훨씬 나쁩니다.
Doval

57

아무도 메모리 바인딩 응용 프로그램을 아직 언급하지 않은 것에 놀랐습니다.

복잡성으로 인해 (즉, O (1) < O (log n )) 또는 복잡성 앞에서 상수가 더 작기 때문에 (즉, 2 n 2 <6 n 2 ) 부동 소수점 연산이 적은 알고리즘이있을 수 있습니다. . 그럼에도 불구하고, 낮은 FLOP 알고리즘이 메모리에 더 많은 경우 FLOP가 더 높은 알고리즘을 선호 할 수 있습니다.

"메모리 바운드"의 의미는 항상 캐시에서 벗어난 데이터에 액세스한다는 것입니다. 이 데이터를 가져 오려면 작업을 수행하기 전에 실제 메모리 공간에서 캐시로 메모리를 가져와야합니다. 이 페치 단계는 종종 작업 자체보다 훨씬 느립니다.

따라서 알고리즘에 더 많은 연산이 필요한 경우 (이러한 연산이 이미 캐시에있는 데이터에서 수행되므로 페치가 필요하지 않음) 더 적은 연산으로 알고리즘의 성능을 여전히 능가합니다 (실제로 수행해야 함) 실제 월 시간 측면에서-캐시 데이터 (따라서 페치 필요).


1
"공간 문제"에 대해 이야기 할 때 Alistra 간접적으로이 문제를 해결
자크 Saucier

2
엄청난 양의 캐시 누락은 최종 실행에 일정한 값 (1.6GHz 램이있는 4 코어 3.2GHz CPU의 경우 8보다 크지 않음, 일반적으로 훨씬 낮음)을 곱하기 때문에 큰 값으로 고정 상수로 계산됩니다 -O 표기법. 따라서 캐시에서 누락되는 것은 O (n) 솔루션이 O (1) 솔루션보다 느리기 시작하는 n의 임계 값을 이동시키는 것입니다.
Marian Spanik

1
@MarianSpanik 물론 정확합니다. 그러나이 질문은 우리가 선호하는 상황을 요구 O(logn)했다 O(1). 가능한 모든 n메모리에 적은 메모리 바운드 응용 프로그램이 더 빠른 월 타임으로, 심지어 더 복잡한 경우에도 실행 되는 상황을 매우 쉽게 상상할 수 있습니다 .
NoseKnows 전체

@MarianSpanik은 최대 300 클럭 사이클의 캐시 미스가 아닙니까? 8은 어디에서 오는가?
희망적으로 도움이 된

43

데이터 보안이 중요한 상황에서,보다 복잡한 알고리즘이 타이밍 공격에 대해 더 나은 내성을 가지면 덜 복잡한 알고리즘보다 더 복잡한 알고리즘이 바람직 할 수 있습니다 .


6
당신이 말한 것은 사실이지만,이 경우 O (1)에서 실행되는 알고리즘은 정의상 타이밍 공격에 취약합니다.
저스틴 레 서드

17
@JustinLessard : O (1)은 알고리즘의 런타임이 상수에 의해 제한되는 입력 크기가 있음을 의미합니다. 이 임계 값 미만에서 발생하는 일을 알 수 없습니다. 또한 실제 알고리즘 사용에 대한 임계 값도 충족되지 않을 수 있습니다. 알고리즘은 선형 일 수 있으므로 예를 들어 입력 길이에 대한 정보가 누출됩니다.
Jörg W Mittag

12
런타임은 여전히 ​​제한적이지만 다른 방식으로 변동될 수 있습니다. 런타임이에 비례하는 (n mod 5) + 1경우에도 여전히 실행 중이지만 O(1)에 대한 정보가 표시 n됩니다. 따라서 점진적으로 (실제로는 가능할지라도) 느리더라도 런타임이 더 부드러운 복잡한 알고리즘이 선호 될 수 있습니다.
Christian Semrau

이것이 기본적으로 bcrypt가 좋은 것으로 간주되는 이유입니다. 이 느리게 일을한다
다윗은 분석 재개 모니카 말한다

@DavidGrinberg 이것이 bcrypt가 사용되는 이유이며 질문에 적합합니다. 그러나 그것은 타이밍 공격에 대해 이야기하는이 답변과 관련이 없습니다.
Christian Semrau

37

Alistra는 그것을 못 박았지만 어떤 예도 제공하지 않아서 그렇게 할 것입니다.

상점에서 판매하는 것에 대한 10,000 개의 UPC 코드 목록이 있습니다. 10 자리 UPC, 가격 (정액 단위 가격)의 정수, 영수증의 설명 문자 30 자

O (log N) 접근 방식 : 정렬 된 목록이 있습니다. ASCII 인 경우 44 바이트, 유니 코드 인 경우 84 바이트 또는 UPC를 int64로 취급하면 42 및 72 바이트가됩니다. 10,000 개 레코드-가장 높은 경우 메가 바이트 단위의 스토리지에서 비트를보고 있습니다.

O (1) 접근 방식 : UPC를 저장하지 말고 대신 UPC를 배열의 항목으로 사용하십시오. 가장 낮은 경우에는 테라 바이트 급 스토리지의 거의 3 분의 1을보고 있습니다.

사용하는 방법은 하드웨어에 따라 다릅니다. 대부분의 합리적인 최신 구성에서는 log N 접근 방식을 사용합니다. RAM이 매우 짧은 환경에서 대량 저장 공간이 충분한 환경에서 실행하는 경우 두 번째 접근 방식이 정답이라고 생각할 수 있습니다. 디스크에서 테라 바이트의 3 분의 1은 별다른 문제가되지 않으므로 디스크의 한 프로브에서 데이터를 얻는 것이 가치가 있습니다. 간단한 이진법은 평균 13이 걸립니다. (단, 키를 클러스터링하면 보장 된 3 회 읽기로이를 얻을 수 있으며 실제로 첫 번째 키를 캐시 할 수 있습니다.)


2
나는 약간 혼란 스러워요. 10 억 개의 엔트리 배열 (대부분 정의되지 않음)을 만들고 UPC를 해당 배열의 인덱스로 취급하는 것에 대해 이야기하고 있습니까?
David Z

7
@DavidZ 예. 스파 스 배열을 사용하는 경우 O (1)을 얻지 못할 수도 있지만 1MB 메모리 만 사용합니다. 실제 어레이를 사용하는 경우 O (1) 액세스가 보장되지만 1 / 3TB 메모리가 사용됩니다.
Navin

최신 시스템에서는 1 / 3TB의 주소 공간을 사용하지만 할당 된 백업 메모리와 가까운 곳이 될 수 있습니다. 대부분의 최신 OS는 필요할 때까지 할당을 위해 스토리지를 커밋하지 않습니다. 이 작업을 수행 할 때는 OS / 하드웨어 가상 메모리 시스템 내부의 데이터에 대한 연관 조회 구조를 숨기고 있습니다.
Phil Miller

@Novelocrat True, 그러나 RAM 속도로 수행하는 경우 조회 시간이 중요하지 않으므로 1mb 대신 40mb를 사용해야 할 이유가 없습니다. 스토리지 버전이 비싼 경우에만 어레이 버전이 의미가 있습니다.
Loren Pechtel

1
또는 이것이 성능에 중요한 작업이 아니고 개발자 시간이 비싸면 malloc(search_space_size)반환하는 내용을 말하고 첨자 화하는 것이 쉽습니다.
Phil Miller

36

빨강 검정 나무를 고려하십시오. 의 액세스, 검색, 삽입 및 삭제 권한이 있습니다 O(log n). 액세스 권한이 O(1)있고 나머지 작업은 O(n)입니다.

따라서 우리가 액세스하는 것보다 더 자주 삽입, 삭제 또는 검색하는 응용 프로그램과이 두 구조 중 하나만 선택하면 빨강-검정 트리를 선호합니다. 이 경우, 레드-블랙 트리의 더 번거로운 O(log n)액세스 시간을 선호한다고 말할 수 있습니다 .

왜? 액세스가 우리의 주요 관심사가 아니기 때문입니다. 우리는 트레이드 오프를하고 있습니다 : 어플리케이션의 성능은 이것 이외의 다른 요소에 의해 더 큰 영향을받습니다. 다른 알고리즘을 최적화하여 큰 이익을 얻으므로이 특정 알고리즘의 성능이 저하됩니다.

따라서 귀하의 질문에 대한 대답은 간단합니다 : 알고리즘의 성장률이 우리가 최적화하고 싶지 않은 경우, 다른 것을 최적화하고 싶을 때. 다른 모든 답변은 특별한 경우입니다. 때로는 다른 작업의 런타임을 최적화합니다. 때때로 우리는 메모리를 최적화합니다. 때로는 보안을 위해 최적화합니다. 때때로 우리는 유지 관리 성을 최적화합니다. 때때로 우리는 개발 시간을 최적화합니다. 알고리즘의 성장률이 런타임에 가장 큰 영향을 미치지 않는다는 것을 알면 무시할 수있는 상수가 낮더라도 런타임에 최적화됩니다. (데이터 세트가이 범위를 벗어난 경우 결국에는 상수를 지배하기 때문에 알고리즘의 성장 속도에 맞게 최적화합니다.) 비용이 많이 들고 대부분의 경우 더 높은 성장 속도의 비용을 다른 것을 최적화하는 알고리즘.


O (1) 조회 및 O (n) 업데이트와 함께 배열을 사용할 수있는 작업이 레드 블랙 트리에 해당하는 방법을 모르는 사람들은 (적어도 나를) 생각했습니다. 대부분의 경우 먼저 레드-블랙 트리에 대한 키 기반 조회를 생각합니다. 그러나 배열과 일치하려면 인덱스 기반 조회를 제공하고 삽입시 다시 색인을 생성하기 위해 상위 노드에 많은 양의 하위 노드를 유지하는 약간 다른 구조이어야합니다. Red-black을 사용하여 균형을 유지하는 데 동의하지만 해당 작업의 세부 사항에 대해 모호한 경우 균형 트리를 사용할 수 있습니다.
오니

@ony 레드-블랙 트리를 사용하여 맵 / 사전 유형 구조를 정의 할 수 있지만 반드시 그럴 필요는 없습니다. 노드는 요소 일 수 있으며 기본적으로 정렬 된 목록을 구현합니다.
jpmc26

요소의 순서를 정의하는 정렬 된 목록과 배열은 정보량이 다릅니다. 하나는 요소 사이의 순서를 기반으로하며, 다른 하나는 요소 사이의 순서를 정의하지 않는 임의의 순서를 정의합니다. 또 다른 것은 당신 O(log n)이 "적색 나무"라고 선언 한 "접근"과 "검색"은 무엇 입니까? 5배열의 위치 2에 삽입 [1, 2, 1, 4]하면 [1, 2, 5, 1 4]요소 4가 3에서 4로 색인이 업데이트됩니다. O(log n)"분류 목록"이라고하는 "레드-블랙 트리" 에서이 동작을 어떻게 얻을 수 있습니까?
ony

@ony "요소의 순서를 정의하는 정렬 된 목록과 배열은 정보량이 다릅니다." 예, 이것이 다른 성능 특성을 갖는 이유의 일부입니다. 요점이 없습니다. 하나는 모든 상황에서 다른 하나를 대체하는 것이 아닙니다. 그들은 다른 일을 최적화 하고 다른 무역 오프를 확인 하고 포인트는 개발자가 지속적으로 그 무역 오프에 대한 의사 결정을한다는 것이다.
jpmc26

@ony 액세스, 검색, 삽입 및 삭제는 알고리즘 성능과 관련하여 특정 의미를 갖습니다. 액세스가 위치별로 요소를 가져오고 있습니다. 검색은 값을 기준으로 요소를 찾고 있습니다 (비맵 구조에 대한 포함 확인으로 실제 응용 프로그램 만 있음). 그러나 삽입과 삭제는 간단해야합니다. 사용법 예는 여기에서 볼 수 있습니다 .
jpmc26

23

예.

실제로는 짧은 문자열 키와 긴 문자열 키를 사용하여 테이블 조회를 수행하는 몇 가지 테스트를 실행했습니다.

우리는 사용 std::map하는 std::unordered_map해시와 그 샘플을 최대 10 문자열의 길이 배 (이 괜찮은 그래서 우리의 키, GUID 같은 경향), 및 샘플 모든 문자 (이론적으로는 충돌을 감소)하는 해시, 우리가 ==비교를 수행하는 정렬되지 않은 벡터 와 해시를 저장하는 정렬되지 않은 벡터 (해시를 비교하는 경우)를 먼저 비교 한 다음 문자를 비교하십시오.

이 알고리즘의 범위는 O(1)(정렬되지 않은 맵)에서 O(n)(선형 검색)까지입니다.

적당한 크기의 N의 경우, O (n)이 O (1)을 이겼습니다. 노드 기반 컨테이너는 컴퓨터가 메모리를 더 많이 뛰어 넘어야했지만 선형 기반 컨테이너는 그렇지 않았기 때문이라고 생각합니다.

O(lg n)둘 사이에 존재합니다. 어떻게했는지 기억이 나지 않습니다.

성능 차이는 그다지 크지 않았으며 더 큰 데이터 세트에서 해시 기반의 성능이 훨씬 우수했습니다. 그래서 우리는 해시 기반의 순서없는 맵을 고수했습니다.

실제로 합리적인 크기의 n에 대해서는 O(lg n)입니다 O(1). 컴퓨터에 테이블에 40 억 개의 항목 만있는 공간이 있으면으로 표시 O(lg n)됩니다 32. (lg (2 ^ 32) = 32) (컴퓨터 과학에서 lg는 로그 기반 2의 속기입니다).

실제로, lg (n) 알고리즘은 로그 성장 인자 때문에가 아니라 lg (n) 부분이 일반적으로 알고리즘에 일정한 수준의 복잡성이 있다는 것을 의미하기 때문에 O (1) 알고리즘보다 느리며, 복잡성은 lg (n) 항의 "성장"중 하나보다 큰 상수 계수.

그러나 해시 매핑과 같은 복잡한 O (1) 알고리즘은 유사하거나 더 큰 상수를 쉽게 가질 수 있습니다.


21

알고리즘을 병렬로 실행할 수 있습니다.

클래스에 대한 예제가 있는지 모르겠다 O(log n)O(1) 있지만, 알고리즘은 병렬로 실행하기 쉬운이 때 몇 가지 문제에 대해, 당신은 더 높은 복잡성 클래스와 알고리즘을 선택합니다.

일부 알고리즘은 병렬화 할 수 없지만 복잡도가 매우 낮습니다. 동일한 결과를 달성하고 쉽게 병렬화 할 수 있지만 더 복잡한 클래스를 갖는 다른 알고리즘을 고려하십시오. 한 시스템에서 실행될 때 두 번째 알고리즘은 느리지 만 여러 시스템에서 실행될 때 실제 실행 시간은 점점 낮아지고 첫 번째 알고리즘은 속도를 높일 수 없습니다.


그러나 병렬화가하는 모든 것은 다른 사람들이 이야기 한 상수 요소를 줄이는 것입니다.
gengkev

1
예. 그러나 병렬 알고리즘은 실행 시스템 수를 두 배로 늘릴 때마다 상수를 2로 나눌 수 있습니다. 다른 단일 스레드 알고리즘은 일정한 방식으로 상수 요인을 한 번만 줄일 수 있습니다. 따라서 병렬 알고리즘을 사용하면 n의 크기에 동적으로 반응하고 벽시계 실행 시간이 더 빨라집니다.
Simulant

15

0에서 1,000,000 사이의 숫자가 블랙리스트에 포함될 수있는 임베디드 시스템에서 블랙리스트를 구현한다고 가정 해 봅시다. 그러면 두 가지 가능한 옵션이 남습니다.

  1. 1,000,000 비트 비트 세트 사용
  2. 블랙리스트 정수의 정렬 된 배열을 사용하고 이진 검색을 사용하여 액세스

비트 세트에 대한 액세스는 지속적인 액세스를 보장합니다. 시간 복잡성 측면에서 최적입니다. 이론적 관점과 실제적인 관점 모두에서 (정수 오버 헤드가 매우 낮은 O (1) 임).

여전히 두 번째 솔루션을 선호 할 수 있습니다. 특히 블랙리스트 정수의 수가 매우 적을 것으로 예상되는 경우 메모리 효율성이 높아집니다.

메모리가 부족한 임베디드 시스템을 개발하지 않더라도 임의의 제한을 1,000,000에서 1,000,000,000,000으로 늘려서 같은 주장을 할 수 있습니다. 그런 다음 비트 세트에는 약 125G의 메모리가 필요합니다. 최악의 경우 O (1)의 복잡성을 보장한다고해서 상사가 그러한 강력한 서버를 제공하도록 설득하지 못할 수도 있습니다.

여기서는 O (1) 비트 집합보다 이진 검색 (O (log n)) 또는 이진 트리 (O (log n))를 선호합니다. 그리고 아마도 최악의 복잡도 인 O (n)을 가진 해시 테이블이 실제로 모든 것을 이길 것입니다.



12

사람들은 이미 귀하의 정확한 질문에 답변 했으므로 여기에 올 때 사람들이 실제로 생각할 수있는 약간 다른 질문을 다룰 것입니다.

많은 "O (1) 시간"알고리즘 및 데이터 구조는 실제로 예상 O (1) 시간 만 사용합니다. 즉, 평균 실행 시간은 O (1)이며 특정 가정 하에서 만 가능합니다.

일반적인 예 : 해시 테이블, "배열 목록"(일명 동적 크기 배열 / 벡터)의 확장.

이러한 시나리오에서는 평균적으로 성능이 저하 될 수 있지만 시간이 로그 적 으로 절대적으로 제한 되는 데이터 구조 또는 알고리즘을 사용하는 것이 좋습니다 .
따라서 균형 잡힌 이진 검색 트리를 예로들 수 있는데, 평균 실행 시간은 더 좋지만 최악의 경우에는 더 좋습니다.


11

하나는 선호하는 상황이있는 경우 더 일반적인 질문은 O(f(n))에 알고리즘을 O(g(n))비록 알고리즘 g(n) << f(n)으로 n무한대가. 다른 사람들이 이미 언급했듯이 where f(n) = log(n)g(n) = 1. f(n)다항식이지만 g(n)지수 적 인 경우에도 때때로 그렇습니다 . 유명하고 중요한 예는 선형 프로그래밍 문제를 해결하기위한 Simplex Algorithm 입니다. 1970 년대에 그것은이었다 O(2^n). 따라서 최악의 경우 행동은 불가능합니다. 그러나 평균 사례 수만 개의 변수와 제약 조건에 대한 실제적인 문제에도 불구 행동은 매우 좋습니다. 1980 년대 다항식 시간 알고리즘 (예 :선형 프로그래밍을위한 Karmarkar의 내부-포인트 알고리즘 (interior-point algorithm )이 발견되었지만 30 년이 지난 후에도 단순 알고리즘은 여전히 ​​선택한 알고리즘 인 것 같습니다 (특정 큰 문제는 제외). 이것은 평균 사례 행동이 종종 더 나쁜 사례 행동보다 중요하다는 명백한 이유 일뿐 아니라 심플 렉스 알고리즘이 더 유익한 정보 (예 : 감도 정보를 추출하기가 더 쉽다)라는 더 미묘한 이유이기도합니다.


10

내 2 센트를 넣으려면 :

알고리즘이 특정 하드웨어 환경에서 실행될 때 더 나은 알고리즘 대신 더 복잡한 알고리즘이 선택되는 경우가 있습니다. O (1) 알고리즘이 문제를 해결하기 위해 매우 큰 고정 크기 배열의 모든 요소에 순차적으로 액세스한다고 가정합니다. 그런 다음 해당 어레이를 기계식 하드 드라이브 또는 자기 테이프에 놓습니다.

이 경우 O (logn) 알고리즘 (디스크에 순차적으로 액세스한다고 가정)이 더 선호됩니다.


여기서는 순차 액세스 드라이브 또는 테이프에서 O (1) 알고리즘이 대신 O (n)이되므로 순차 솔루션이 더 유리 해집니다. 많은 O (1) 연산은 상수 액세스 알고리즘이 아닌 상수 시간 알고리즘 인 추가 및 색인 조회에 의존합니다.
TheHansinator

9

수많은 다른 답변에서 무시한 O (1) 알고리즘 대신 O (log (n)) 알고리즘을 사용하는 좋은 사용 사례가 있습니다 : 불변성. 해시 맵에는 해시 값이 잘 분포되어 있다고 가정하고 O (1) 넣기 및 가져 오기가 있지만 변경 가능한 상태가 필요합니다. 불변 트리 맵에는 O (log (n)) 넣기 및 가져 오기가 있으며, 이는 점진적으로 느립니다. 그러나 불변성은 성능 저하를 보완하기에 충분히 가치가 있으며, 여러 버전의 맵을 유지해야하는 경우 불변성을 통해 맵 (O (n))을 복사하지 않아도되므로 개선 할 수 있습니다. 공연.


9

간단히 말해 : 설정, 저장 및 해당 단계의 실행 시간과 관련된 계수는 더 큰 것보다 작은 큰 O 문제로 훨씬 더 클 수 있기 때문입니다. Big-O는 알고리즘 확장 성의 척도입니다 .

양자 역학다중 세계 해석에 의존하는 정렬 알고리즘을 제안하는 Hacker 's Dictionary의 다음 예제를 고려하십시오 .

  1. 퀀텀 프로세스를 사용하여 배열을 무작위로 치환
  2. 배열이 정렬되지 않은 경우 유니버스를 삭제하십시오.
  3. 남아있는 모든 유니버스가 [현재 포함 된 유니버스 포함] 정렬됩니다.

(출처 : http://catb.org/~esr/jargon/html/B/bogo-sort.html )

이 알고리즘의 big-O는 O(n)일반 항목에 대해 알려진 정렬 알고리즘보다 우선 합니다. 선형 단계의 계수도 매우 낮습니다 (왜냐하면 스왑이 아닌 비교 일뿐이므로 선형으로 수행되기 때문입니다). 실제로 비슷한 알고리즘을 사용하여 두 가지 문제를 해결할 수 있습니다. 각각의 가능한 솔루션 (또는 솔루션이 없다는 가능한 증거)을 생성 한 다음 검증 할 수 있기 때문에 실제로 다항식 시간으로 NPco-NP의 수 있습니다. 다항식 시간.

그러나 대부분의 경우 우리는 2 단계를 수행하는 행위가 여전히 "독자의 연습으로 남아있다"는 점을 제외하고 복수 세계가 정확하지 않을 위험을 감수하고 싶지 않을 것입니다.


7

n이 바인드되고 O (1) 알고리즘의 상수 승수가 log (n)의 바운드보다 높은 경우 예를 들어, 해시 세트에 값을 저장하는 것은 O (1)이지만 값 비싼 해시 함수 계산이 필요할 수 있습니다. 데이터 항목을 (일부 순서와 관련하여) 사소하게 비교할 수 있고 n에 바인딩 된 값이 log n이 임의의 한 항목에 대한 해시 계산보다 현저히 낮은 경우 균형 이진 트리에 저장하는 것이 저장하는 것보다 빠를 수 있습니다 해시 셋.


6

확실한 상한이 필요한 실시간 상황에서는 힙 정렬의 평균 동작도 최악의 동작이므로 빠른 정렬과 달리 힙 정렬을 선택합니다.


6

이미 좋은 답변에 추가 실제 사례는 postgres 데이터베이스의 해시 인덱스와 B- 트리 인덱스입니다.

해시 인덱스는 해시 테이블 인덱스를 형성하여 디스크의 데이터에 액세스하고 이름에서 알 수 있듯이 btree는 Btree 데이터 구조를 사용합니다.

Big-O 시간에서 이들은 O (1) 대 O (logN)입니다.

해시 인덱스는 현재 데이터베이스 시스템의 실제 상황에서 postgres에서 권장하지 않으며 충돌없이 해싱을 얻는 것이 매우 어렵고 (O (N) 최악의 경우 복잡성을 초래할 수 있음)이 때문에 훨씬 더 어렵습니다. 그것들은 안전하게 추락합니다 (postgres에서 WAL이라고 함).

O (logN)가 인덱스에 충분하고 O (1) 구현이 매우 어렵고 시차가 실제로 중요하지 않기 때문에 이러한 상황에서 이러한 절충이 이루어집니다.



3
  1. O (1)의 "1"작업 단위가 O (log n)의 작업 단위에 비해 매우 높고 예상 설정 크기가 작은 경우. 예를 들어, 2 개 또는 3 개의 항목 만있는 경우 배열을 반복하는 것보다 Dictionary 해시 코드를 계산하는 것이 느릴 수 있습니다.

또는

  1. O (1) 알고리즘의 메모리 또는 기타 비 시간 자원 요구 사항이 O (log n) 알고리즘에 비해 예외적으로 큰 경우

3
  1. 프로그램을 다시 디자인 할 때 프로시 저는 O (lgN) 대신 O (1)으로 최적화 된 것으로 확인되었지만이 프로그램의 병목 현상이 아니고 O (1) alg를 이해하기 어렵습니다. 그러면 O (1) 알고리즘을 사용할 필요가 없습니다
  2. O (1)에 제공 할 수없는 많은 메모리가 필요한 경우 O (lgN)의 시간을 승인 할 수 있습니다.

1

누군가가 문제에 대한 답변을 너무 빨리 얻지 못하도록 의도적으로 알고리즘이 느린 문제를 설계하려는 보안 응용 프로그램의 경우가 종종 있습니다.

여기 내 머리 꼭대기에 몇 가지 예가 있습니다.

  • 무차별 암호로 추측하기 어렵게하기 위해 암호 해싱이 때때로 느리게 만들어집니다. 이 정보 보안 게시물 에는 그에 대한 글 머리 기호가 있습니다.
  • 비트 코인 은 을 "채굴"하기 위해 컴퓨터 네트워크가 해결하기 위해 느리게 느린 문제를 사용합니다. 이것은 통화가 집단 시스템에 의해 통제 된 비율로 채굴 될 수있게합니다.
  • RSA 와 같은 비대칭 암호 는 개인 키가없는 다른 사람이 암호화를 해독하지 못하도록 의도적으로 키없이 해독을 수행하도록 설계되었습니다. 알고리즘은 키의 비트 길이가되는 희망적인 O(2^n)시간에 크랙되도록 설계되었습니다 n(이것은 무차별적인 힘입니다).

CS의 다른 곳에서 빠른 정렬은 O(n^2)최악의 경우이지만 일반적인 경우는 O(n*log(n))입니다. 이러한 이유로 알고리즘 효율성을 분석 할 때 "Big O"분석 만 신경 쓰는 것은 아닙니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.