O(log n)
시간 복잡성보다 시간 복잡성을 선호하는 경우가 O(1)
있습니까? 또는 O(n)
에 O(log n)
?
예가 있습니까?
O(log n)
시간 복잡성보다 시간 복잡성을 선호하는 경우가 O(1)
있습니까? 또는 O(n)
에 O(log n)
?
예가 있습니까?
답변:
낮은 O보다 복잡한 O 시간 복잡성을 가진 알고리즘을 선호하는 데는 여러 가지 이유가있을 수 있습니다.
10^5
보다 big-O 관점에서 더 좋지만 가장 합리적인 경우 첫 번째 알고리즘 이 더 잘 수행됩니다. 예를 들어 행렬 곱셈의 가장 복잡한 점 은 상수가 너무 커서 (내 지식으로는) 계산 라이브러리에서 사용하지 않습니다.1/10^5 * log(n)
O(1)
O(log(n)
n
O(n^2.373)
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을 충분히 찾을 수 있다는 것입니다.O(n^2)
퀵 정렬 또는 병합 정렬보다 나쁘지만 온라인 알고리즘 으로 대부분의 다른 알고리즘 만 효율적으로 작동 할 수있는 경우 사용자 입력으로 수신되는 값 목록을 효율적으로 정렬 할 수 있습니다 전체 값 목록에서.숨겨진 상수는 항상 있으며 O (log n ) 알고리즘 에서 낮을 수 있습니다 . 따라서 실제 데이터에 대해 실제로 더 빠르게 작동 할 수 있습니다.
공간 문제도 있습니다 (예 : 토스터에서 실행).
개발자 시간 문제도 있습니다. O (log n )는 구현 및 확인이 1000 배 더 쉽습니다.
lg n
정도로 k
큰 값에 가깝습니다 n
.
아무도 메모리 바인딩 응용 프로그램을 아직 언급하지 않은 것에 놀랐습니다.
복잡성으로 인해 (즉, O (1) < O (log n )) 또는 복잡성 앞에서 상수가 더 작기 때문에 (즉, 2 n 2 <6 n 2 ) 부동 소수점 연산이 적은 알고리즘이있을 수 있습니다. . 그럼에도 불구하고, 낮은 FLOP 알고리즘이 메모리에 더 많은 경우 FLOP가 더 높은 알고리즘을 선호 할 수 있습니다.
"메모리 바운드"의 의미는 항상 캐시에서 벗어난 데이터에 액세스한다는 것입니다. 이 데이터를 가져 오려면 작업을 수행하기 전에 실제 메모리 공간에서 캐시로 메모리를 가져와야합니다. 이 페치 단계는 종종 작업 자체보다 훨씬 느립니다.
따라서 알고리즘에 더 많은 연산이 필요한 경우 (이러한 연산이 이미 캐시에있는 데이터에서 수행되므로 페치가 필요하지 않음) 더 적은 연산으로 알고리즘의 성능을 여전히 능가합니다 (실제로 수행해야 함) 실제 월 시간 측면에서-캐시 데이터 (따라서 페치 필요).
O(logn)
했다 O(1)
. 가능한 모든 n
메모리에 적은 메모리 바운드 응용 프로그램이 더 빠른 월 타임으로, 심지어 더 복잡한 경우에도 실행 되는 상황을 매우 쉽게 상상할 수 있습니다 .
데이터 보안이 중요한 상황에서,보다 복잡한 알고리즘이 타이밍 공격에 대해 더 나은 내성을 가지면 덜 복잡한 알고리즘보다 더 복잡한 알고리즘이 바람직 할 수 있습니다 .
(n mod 5) + 1
경우에도 여전히 실행 중이지만 O(1)
에 대한 정보가 표시 n
됩니다. 따라서 점진적으로 (실제로는 가능할지라도) 느리더라도 런타임이 더 부드러운 복잡한 알고리즘이 선호 될 수 있습니다.
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 회 읽기로이를 얻을 수 있으며 실제로 첫 번째 키를 캐시 할 수 있습니다.)
malloc(search_space_size)
반환하는 내용을 말하고 첨자 화하는 것이 쉽습니다.
빨강 검정 나무를 고려하십시오. 의 액세스, 검색, 삽입 및 삭제 권한이 있습니다 O(log n)
. 액세스 권한이 O(1)
있고 나머지 작업은 O(n)
입니다.
따라서 우리가 액세스하는 것보다 더 자주 삽입, 삭제 또는 검색하는 응용 프로그램과이 두 구조 중 하나만 선택하면 빨강-검정 트리를 선호합니다. 이 경우, 레드-블랙 트리의 더 번거로운 O(log n)
액세스 시간을 선호한다고 말할 수 있습니다 .
왜? 액세스가 우리의 주요 관심사가 아니기 때문입니다. 우리는 트레이드 오프를하고 있습니다 : 어플리케이션의 성능은 이것 이외의 다른 요소에 의해 더 큰 영향을받습니다. 다른 알고리즘을 최적화하여 큰 이익을 얻으므로이 특정 알고리즘의 성능이 저하됩니다.
따라서 귀하의 질문에 대한 대답은 간단합니다 : 알고리즘의 성장률이 우리가 최적화하고 싶지 않은 경우, 다른 것을 최적화하고 싶을 때. 다른 모든 답변은 특별한 경우입니다. 때로는 다른 작업의 런타임을 최적화합니다. 때때로 우리는 메모리를 최적화합니다. 때로는 보안을 위해 최적화합니다. 때때로 우리는 유지 관리 성을 최적화합니다. 때때로 우리는 개발 시간을 최적화합니다. 알고리즘의 성장률이 런타임에 가장 큰 영향을 미치지 않는다는 것을 알면 무시할 수있는 상수가 낮더라도 런타임에 최적화됩니다. (데이터 세트가이 범위를 벗어난 경우 결국에는 상수를 지배하기 때문에 알고리즘의 성장 속도에 맞게 최적화합니다.) 비용이 많이 들고 대부분의 경우 더 높은 성장 속도의 비용을 다른 것을 최적화하는 알고리즘.
O(log n)
이 "적색 나무"라고 선언 한 "접근"과 "검색"은 무엇 입니까? 5
배열의 위치 2에 삽입 [1, 2, 1, 4]
하면 [1, 2, 5, 1 4]
요소 4
가 3에서 4로 색인이 업데이트됩니다. O(log n)
"분류 목록"이라고하는 "레드-블랙 트리" 에서이 동작을 어떻게 얻을 수 있습니까?
예.
실제로는 짧은 문자열 키와 긴 문자열 키를 사용하여 테이블 조회를 수행하는 몇 가지 테스트를 실행했습니다.
우리는 사용 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) 알고리즘은 유사하거나 더 큰 상수를 쉽게 가질 수 있습니다.
알고리즘을 병렬로 실행할 수 있습니다.
클래스에 대한 예제가 있는지 모르겠다 O(log n)
과O(1)
있지만, 알고리즘은 병렬로 실행하기 쉬운이 때 몇 가지 문제에 대해, 당신은 더 높은 복잡성 클래스와 알고리즘을 선택합니다.
일부 알고리즘은 병렬화 할 수 없지만 복잡도가 매우 낮습니다. 동일한 결과를 달성하고 쉽게 병렬화 할 수 있지만 더 복잡한 클래스를 갖는 다른 알고리즘을 고려하십시오. 한 시스템에서 실행될 때 두 번째 알고리즘은 느리지 만 여러 시스템에서 실행될 때 실제 실행 시간은 점점 낮아지고 첫 번째 알고리즘은 속도를 높일 수 없습니다.
0에서 1,000,000 사이의 숫자가 블랙리스트에 포함될 수있는 임베디드 시스템에서 블랙리스트를 구현한다고 가정 해 봅시다. 그러면 두 가지 가능한 옵션이 남습니다.
비트 세트에 대한 액세스는 지속적인 액세스를 보장합니다. 시간 복잡성 측면에서 최적입니다. 이론적 관점과 실제적인 관점 모두에서 (정수 오버 헤드가 매우 낮은 O (1) 임).
여전히 두 번째 솔루션을 선호 할 수 있습니다. 특히 블랙리스트 정수의 수가 매우 적을 것으로 예상되는 경우 메모리 효율성이 높아집니다.
메모리가 부족한 임베디드 시스템을 개발하지 않더라도 임의의 제한을 1,000,000에서 1,000,000,000,000으로 늘려서 같은 주장을 할 수 있습니다. 그런 다음 비트 세트에는 약 125G의 메모리가 필요합니다. 최악의 경우 O (1)의 복잡성을 보장한다고해서 상사가 그러한 강력한 서버를 제공하도록 설득하지 못할 수도 있습니다.
여기서는 O (1) 비트 집합보다 이진 검색 (O (log n)) 또는 이진 트리 (O (log n))를 선호합니다. 그리고 아마도 최악의 복잡도 인 O (n)을 가진 해시 테이블이 실제로 모든 것을 이길 것입니다.
내 대답 은 확률 행렬의 모든 행 에서 빠른 임의 가중치를 선택 하면 복잡도가 O (m (m)) 인 알고리즘보다 복잡도가 O (m (m)) 인 알고리즘보다 빠른 예 m
입니다.
사람들은 이미 귀하의 정확한 질문에 답변 했으므로 여기에 올 때 사람들이 실제로 생각할 수있는 약간 다른 질문을 다룰 것입니다.
많은 "O (1) 시간"알고리즘 및 데이터 구조는 실제로 예상 O (1) 시간 만 사용합니다. 즉, 평균 실행 시간은 O (1)이며 특정 가정 하에서 만 가능합니다.
일반적인 예 : 해시 테이블, "배열 목록"(일명 동적 크기 배열 / 벡터)의 확장.
이러한 시나리오에서는 평균적으로 성능이 저하 될 수 있지만 시간이 로그 적 으로 절대적으로 제한 되는 데이터 구조 또는 알고리즘을 사용하는 것이 좋습니다 .
따라서 균형 잡힌 이진 검색 트리를 예로들 수 있는데, 평균 실행 시간은 더 좋지만 최악의 경우에는 더 좋습니다.
하나는 선호하는 상황이있는 경우 더 일반적인 질문은 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 년이 지난 후에도 단순 알고리즘은 여전히 선택한 알고리즘 인 것 같습니다 (특정 큰 문제는 제외). 이것은 평균 사례 행동이 종종 더 나쁜 사례 행동보다 중요하다는 명백한 이유 일뿐 아니라 심플 렉스 알고리즘이 더 유익한 정보 (예 : 감도 정보를 추출하기가 더 쉽다)라는 더 미묘한 이유이기도합니다.
내 2 센트를 넣으려면 :
알고리즘이 특정 하드웨어 환경에서 실행될 때 더 나은 알고리즘 대신 더 복잡한 알고리즘이 선택되는 경우가 있습니다. O (1) 알고리즘이 문제를 해결하기 위해 매우 큰 고정 크기 배열의 모든 요소에 순차적으로 액세스한다고 가정합니다. 그런 다음 해당 어레이를 기계식 하드 드라이브 또는 자기 테이프에 놓습니다.
이 경우 O (logn) 알고리즘 (디스크에 순차적으로 액세스한다고 가정)이 더 선호됩니다.
수많은 다른 답변에서 무시한 O (1) 알고리즘 대신 O (log (n)) 알고리즘을 사용하는 좋은 사용 사례가 있습니다 : 불변성. 해시 맵에는 해시 값이 잘 분포되어 있다고 가정하고 O (1) 넣기 및 가져 오기가 있지만 변경 가능한 상태가 필요합니다. 불변 트리 맵에는 O (log (n)) 넣기 및 가져 오기가 있으며, 이는 점진적으로 느립니다. 그러나 불변성은 성능 저하를 보완하기에 충분히 가치가 있으며, 여러 버전의 맵을 유지해야하는 경우 불변성을 통해 맵 (O (n))을 복사하지 않아도되므로 개선 할 수 있습니다. 공연.
간단히 말해 : 설정, 저장 및 해당 단계의 실행 시간과 관련된 계수는 더 큰 것보다 작은 큰 O 문제로 훨씬 더 클 수 있기 때문입니다. Big-O는 알고리즘 확장 성의 척도입니다 .
양자 역학 의 다중 세계 해석에 의존하는 정렬 알고리즘을 제안하는 Hacker 's Dictionary의 다음 예제를 고려하십시오 .
- 퀀텀 프로세스를 사용하여 배열을 무작위로 치환
- 배열이 정렬되지 않은 경우 유니버스를 삭제하십시오.
- 남아있는 모든 유니버스가 [현재 포함 된 유니버스 포함] 정렬됩니다.
(출처 : http://catb.org/~esr/jargon/html/B/bogo-sort.html )
이 알고리즘의 big-O는 O(n)
일반 항목에 대해 알려진 정렬 알고리즘보다 우선 합니다. 선형 단계의 계수도 매우 낮습니다 (왜냐하면 스왑이 아닌 비교 일뿐이므로 선형으로 수행되기 때문입니다). 실제로 비슷한 알고리즘을 사용하여 두 가지 문제를 해결할 수 있습니다. 각각의 가능한 솔루션 (또는 솔루션이 없다는 가능한 증거)을 생성 한 다음 검증 할 수 있기 때문에 실제로 다항식 시간으로 NP 및 co-NP의 수 있습니다. 다항식 시간.
그러나 대부분의 경우 우리는 2 단계를 수행하는 행위가 여전히 "독자의 연습으로 남아있다"는 점을 제외하고 복수 세계가 정확하지 않을 위험을 감수하고 싶지 않을 것입니다.
n이 바인드되고 O (1) 알고리즘의 상수 승수가 log (n)의 바운드보다 높은 경우 예를 들어, 해시 세트에 값을 저장하는 것은 O (1)이지만 값 비싼 해시 함수 계산이 필요할 수 있습니다. 데이터 항목을 (일부 순서와 관련하여) 사소하게 비교할 수 있고 n에 바인딩 된 값이 log n이 임의의 한 항목에 대한 해시 계산보다 현저히 낮은 경우 균형 이진 트리에 저장하는 것이 저장하는 것보다 빠를 수 있습니다 해시 셋.
이미 좋은 답변에 추가 실제 사례는 postgres 데이터베이스의 해시 인덱스와 B- 트리 인덱스입니다.
해시 인덱스는 해시 테이블 인덱스를 형성하여 디스크의 데이터에 액세스하고 이름에서 알 수 있듯이 btree는 Btree 데이터 구조를 사용합니다.
Big-O 시간에서 이들은 O (1) 대 O (logN)입니다.
해시 인덱스는 현재 데이터베이스 시스템의 실제 상황에서 postgres에서 권장하지 않으며 충돌없이 해싱을 얻는 것이 매우 어렵고 (O (N) 최악의 경우 복잡성을 초래할 수 있음)이 때문에 훨씬 더 어렵습니다. 그것들은 안전하게 추락합니다 (postgres에서 WAL이라고 함).
O (logN)가 인덱스에 충분하고 O (1) 구현이 매우 어렵고 시차가 실제로 중요하지 않기 때문에 이러한 상황에서 이러한 절충이 이루어집니다.
누군가가 문제에 대한 답변을 너무 빨리 얻지 못하도록 의도적으로 알고리즘이 느린 문제를 설계하려는 보안 응용 프로그램의 경우가 종종 있습니다.
여기 내 머리 꼭대기에 몇 가지 예가 있습니다.
O(2^n)
시간에 크랙되도록 설계되었습니다 n
(이것은 무차별적인 힘입니다).CS의 다른 곳에서 빠른 정렬은 O(n^2)
최악의 경우이지만 일반적인 경우는 O(n*log(n))
입니다. 이러한 이유로 알고리즘 효율성을 분석 할 때 "Big O"분석 만 신경 쓰는 것은 아닙니다.
O(log n)
알고리즘보다 알고리즘을 선호O(1)
하지만 후자는 이해하지 못한다 ...