기술적으로 "Hello World"에 대한 O (1) 알고리즘입니까?


117

이것이 "Hello, World!"에 대한 O (1) 알고리즘으로 분류됩니까? ??

public class Hello1
{
   public static void Main()
   {
      DateTime TwentyYearsLater = new DateTime(2035,01,01);
      while ( DateTime.Now < TwentyYearsLater )
      { 
          System.Console.WriteLine("It's still not time to print the hello ...");
      }
      System.Console.WriteLine("Hello, World!");
   }
}

나는 사용을 생각하고있다

DateTime TwentyYearsLater = new DateTime(2035,01,01);
while ( DateTime.Now < TwentyYearsLater )
{ 
   // ... 
}

누군가가 특정 복잡한 알고리즘을 요청할 때마다 농담으로 넣는 바쁜 루프로 코드 스 니펫. 이것이 맞습니까?


15
이다 O(N)복잡하지O(1)
Fabjan

19
@SubparWebDev 아니요, 프로그램을 시작할 때와 지정된 날짜 사이의 정확한 시간 차이를 알고 있더라도 루프를 통과하는 횟수를 알 수 없습니다. 컴퓨터가 얼마나 빨리 실행되는지, 다른 항목이 실행되고 있는지, CPU가 작업을 예약하는 방법 등에 따라
다릅니다

131
@Fabjan N알고리즘이 의존하는 것이 없으므로 실제로 O (N) 알고리즘이라고 말할 수 없습니다.
Servy

29
기술적으로는 입력이 없으므로 N의미가 없습니다. 그러나 DateTime.Now이것이 여전히 결과에 의존하도록 만드는 입력을 고려할 수 있습니다. 에 대한 현실적인 값을 가정 할 수 있다면 DateTime.Now예, 프로그램은 일정한 횟수만큼 반복됩니다.
찌르기

43
문제 설명은 N이 무엇인지 정의해야합니다.
Yacoub Massad 2015

답변:


406

이 컨텍스트에서 Big O 표기법은 함수 입력 크기와 해당 입력에 대한 결과를 계산하기 위해 수행해야하는 작업 수 간의 관계를 설명하는 데 사용됩니다.

작업에 출력과 관련 될 수있는 입력이 없으므로 Big O 표기법을 사용하는 것은 의미가 없습니다. 작업에 걸리는 시간은 작업 입력과 무관 합니다 (없음). 입력과 수행 된 작업 수간에 관계 없기 때문에 존재하지 않는 관계를 설명하는 데 Big O를 사용할 수 없습니다.


6
어때 O(max(1, 2035 - yearTheProgramIsStarted))?
Bergi

19
@Bergi [실제로는 아니오 [( stackoverflow.com/questions/34048740/… ), 작업을 실행 한 시간만을 기준으로 루프 반복 횟수를 설명 할 수 없습니다. 물론 사용자가 시스템 시계를 언제든지 원하는 시간으로 변경할 수 있다는 사실과 결합하여 여러 가지와 정확하게 관련 될 수있는 올바른 형식의 입력이 아직 없습니다. 출력을 생성하는 데 필요한 작업. 출력 자체도 일관성이 없습니다.
Servy

23
시스템 상태 (시계 포함)가 프로그램 입력의 일부라고 주장 할 수 있습니다. 그런 의미에서 명시 적이지는 않지만 날짜를 입력 매개 변수로 사용할 수 있습니다. 그래도 이상합니다.
Connor Clark

9
더 명확하게 말하면 '암시 적'입력은 2035 년 1 월 1 일과 오늘 사이의 델타입니다.
Connor Clark

6
@Hoten 그러나 시스템 시간은 고정 값이 아닙니다. 이 기능은 없다 단지 수락 같은 DateTime입력으로 시작 시간. 앞서 말했듯 이 시스템 시계는 시간이 지남에 따라 변경 될 수 있습니다 . 다시 말하지만, 설명하고있는 quazi 입력을 고정 출력에 직접 매핑 할 수 없습니다. 주어진 시작 시간 동안 수행 된 작업의 수는 알려져 있지 않으며, 항상 합리적인 값인을받는 두 프로그램에 대해 수행 DateTime.Now되지 않으므로 시간이 변경되면 둘을 연결할 수 없습니다. 시간 은 변하지 않습니다 .
Servy

88

Big-O 표기법은 대략 '작업량 N, 계산 시간, N에 비례하여 알고리즘에 걸리는 시간'을 대략적으로 의미합니다. 예를 들어, 크기가 N 인 배열을 정렬하는 것은 N ^ 2, Nlog (N) 등을 취할 수 있습니다.

여기에는 조치 할 입력 데이터가 없습니다. 그래서 그것은 아닙니다 O(anything).

더 나쁘다. 이것은 기술적으로 알고리즘이 아닙니다. 알고리즘은 수학 함수의 값을 계산하는 방법입니다. 수학 함수는 하나의 입력에서 출력으로의 매핑입니다. 이것은 입력을받지 않고 아무것도 반환하지 않기 때문에 수학적 의미에서 함수가 아닙니다. wikipedia에서 :

알고리즘은 한정된 공간과 시간 내에서 함수를 계산하기 위해 잘 정의 된 공식 언어로 표현할 수있는 효과적인 방법입니다. 초기 상태 및 초기 입력 (비어있을 수 있음)에서 시작하여 명령어는 실행될 때 유한 한 수의 잘 정의 된 연속 상태를 진행하여 결국 "출력"을 생성하고 최종 종료 상태에서 종료되는 계산을 설명합니다.

이것은 기술적으로 제어 시스템입니다. wikipedia에서;

제어 시스템은 다른 장치 또는 시스템의 동작을 관리, 명령, 지시 또는 규제하는 장치 또는 장치 집합입니다.

수학적 기능과 알고리즘의 차이에 대한보다 심층적 인 답변을 원하는 사람들과 콘솔 출력, 그래픽 표시 또는 로봇 제어와 같은 부작용을 일으키는 컴퓨터의 더 강력한 능력을 원하는 사람들 을 위해이 문서를 읽으십시오. 강력한 교회 학습 가설

요약

계산 위치 계산의 고전적 관점은 입력 (합리적 숫자 또는 유한 문자열)을 출력으로의 폐쇄 형 변환으로 나타냅니다. 컴퓨팅의 대화 형 관점에 따르면 계산은 입력을 출력으로 변환하는 기능 기반이 아니라 지속적인 대화 형 프로세스입니다. 특히 외부 세계와의 통신은 계산 전이나 후에가 아니라 계산 중에 발생합니다. 이 접근 방식은 계산이 무엇이며 어떻게 모델링되는지에 대한 우리의 이해를 근본적으로 변화시킵니다.

상호 작용을 새로운 패러다임으로 받아들이는 것은 Turing Machines (TM)가 모든 계산을 캡처한다는 광범위한 믿음 인 Strong Church-Turing Thesis (SCT)에 의해 방해를 받고 있으므로 TM보다 표현력이 더 높은 계산 모델은 불가능합니다. 이 논문에서 우리는 SCT가 원래의 Church-Turing Thesis (CTT)를 Turing이 의도하지 않은 방식으로 재 해석한다는 것을 보여줍니다. 일반적으로 원본과 동등하다고 가정되는 것은 신화입니다. 우리는 SCT에 대한 광범위한 믿음에 대한 역사적 이유를 식별하고 분석합니다. 그것이 거짓임을 받아들이는 것만으로 상호 작용을 계산의 대안 적 패러다임으로 채택 할 수 있습니다.


시퀀스 일 필요는 없습니다. 이는 단지 일부 데이터 입력일 뿐이며, Landau 표기법은 해당 데이터의 일부 메트릭 (일반적으로 크기와 관련된 것)과 관련하여 실행 시간을 설명합니다.
Bergi

@Bergi-네, 요점을 참조하십시오! 근사값을내는 것뿐입니다.하지만 예, 할 일의 양과 거기에 도달하는 데 걸리는 단계의 양을 측정 할 수 있다면 big-o는이 두 측정 값의 관계를 반영합니다. 더 가까이?
Steve Cooper

@kapep-void 메서드이기 때문에 순수한 함수는 아니지만 콘솔 출력을 계산하면 여전히 무작위입니다. { "Hello, World!", "아직 hello를 인쇄 할 시간이 아닙니다 ... \ nHello, World!", "아직 hello를 인쇄 할 시간이 아닙니다. 아직 인쇄 할 시간이 아닙니다. the hello ... \ nHello, World! ", ...}
Steve Cooper

1
stdout으로 인쇄하는 것이 출력이 아닙니까?
rpax

4
@rpax 수학적으로는 아닙니다. 함수는 입력에서 출력으로 변하지 않는 변환입니다. 예를 들어 'square'는 3을 입력하면 항상 9를 반환하는 함수입니다. 동일한 매개 변수를 사용하는 호출이 항상 동일한 반환 값을 제공하는 경우 c # 메서드는 수학 함수일뿐입니다. 그렇지 않으면-콘솔에 쓰기, 그래픽 표시, 메모리 할당과 같은 부작용이있는 경우에는 수학적 함수가 아닙니다. (후끈 : 극심한 상세하게 들어가는 내 대답에 링크 추가)
스티브 쿠퍼

41

아니요, 코드의 시간 복잡성은 O(2^|<DeltaTime>|),

현재 시간의 적절한 코딩을 위해.
제 영어에 대해 먼저 사과하겠습니다.

CS에서 Big O의 정의 및 작동 방식

Big O 표기법 은 프로그램의 입력을 실행 시간과 연결하는 데 사용되지 않습니다 .
Big O 표기법은 엄격함을 남기고 두 양점근 비율 을 표현하는 방법 입니다.

알고리즘 분석의 경우이 두 수량은 입력 (먼저 "측정"기능이 있어야 함) 및 실행 시간 이 아닙니다 .
이는 문제 1 의 인스턴스 코딩 길이 와 관심 메트릭입니다.

일반적으로 사용되는 측정 항목은 다음과 같습니다.

  1. 주어진 계산 모델에서 알고리즘을 완료하는 데 필요한 단계 수입니다.
  2. 그러한 개념이있는 경우 계산 모델에 필요한 공간입니다.

암시 적으로 TM을 모델로 가정하여 첫 번째 지점 은 전환 2 기능 , 즉 "단계" 의 응용 프로그램 수로 변환되고 두 번째 지점 은 적어도 한 번 기록 된 서로 다른 테이프 셀 의 수를 변환합니다 .

또한 원래의 인코딩 대신 다 항적으로 관련된 인코딩을 사용할 수 있다고 암시 적으로 가정하는 경우가 있습니까? 예를 들어 배열을 처음부터 끝까지 검색하는 함수 O(n)는 이러한 배열의 인스턴스 코딩이 다음 길이를 가져야한다는 사실에도 불구하고 복잡합니다. 각 요소의 (상수) 기호 수는 n*b+(n-1)어디에 있습니까 b? 이는 b계산 모델의 상수로 간주되므로 위의 표현식과 n점근 적으로 동일하기 때문입니다.

등의 알고리즘 이유도 설명 평가판 부문 입니다 지수 기본적으로 인에도 불구하고 알고리즘 for(i=2; i<=sqr(N); i++)알고리즘과 같은 3 .

참조 .

이것은 또한 big O 표기법이 문제를 설명하는 데 필요한만큼의 매개 변수를 사용할 수 있음을 의미합니다 . 일부 알고리즘에 대해 k 매개 변수 를 갖는 것은 드문 일이 아닙니다 .

따라서 이것은 "입력"또는 "입력이 없음"에 관한 것이 아닙니다 .

지금 연구 사례

Big O 표기법은 알고리즘에 의문을 제기하는 것이 아니라 수행중인 작업을 알고 있다고 가정합니다. 그것은 본질적으로 모든 곳에서 적용 가능한 도구이며, 심지어 당신과 같이 의도적으로 까다로울 수있는 알고리즘에도 적용됩니다.

문제를 해결하기 위해 현재 날짜와 미래 날짜를 사용 했으므로 어떻게 든 문제의 일부가되어야합니다. 간단히 말해서, 그것들은 문제의 일부입니다.

특히 인스턴스는 다음과 같습니다.

<DeltaTime>

여기서는 <>선택의 비 병리 적 코딩을 의미합니다.

매우 중요한 설명 은 아래를 참조하십시오 .

따라서 O(2^|<DeltaTime>|)현재 시간의 값에 따라 많은 반복을 수행하기 때문에 큰 O 복잡도 시간은 단지 입니다. 점근 표기법이 상수를 제거하므로 유용하므로 다른 숫자 상수를 넣는 것은 의미가 없습니다 (예를 들어의 사용 O(10^|<DeltaTime>|*any_time_unit)은 무의미합니다).

까다로운 부분은

우리는 위에서 한 가지 중요한 가정을했습니다 : 계산 모델이 5 번 반복되고 시간이란 (실제?) 물리적 시간을 의미합니다. 표준 계산 모델에는 그러한 개념이 없습니다. TM은 시간을 알지 못합니다 . 이것이 우리의 현실이 작동하는 방식이기 때문에 시간을 단계 수와 연결합니다 4 .

모델에서 시간은 계산의 일부이지만 Main은 순수하지 않지만 개념은 동일하다고 말하여 기능적 사람들의 용어를 사용할 수 있습니다.

이것을 이해하려면 프레임 워크가 실제 시간보다 두 배, 다섯 배, 열 배 빠른 가짜 시간을 사용하는 것을 막을 수있는 것은 없습니다. 이렇게하면 코드가 "시간"의 "절반", "1/5", "1/10"에 실행됩니다.

이 반영은의 인코딩을 선택하는 데 중요합니다. 이것은 <DeltaTime>본질적으로 <(CurrentTime, TimeInFuture)>를 작성하는 압축 된 방법입니다. 시간이 수도회에 존재하지 않는 때문에, currentTime을의 코딩 아주 잘 단어 수 이제 (또는 다른 선택) 전날으로 코딩 할 수 어제 ,이 가정을 파괴함으로써 그 코딩의 길이를 증가 물리적 시간과 앞으로 이동 (그리고 DeltaTime 중 하나가 감소 함)

유용한 작업을 수행하려면 계산 모델에서 시간을 적절하게 모델링해야합니다.

우리가 할 수있는 유일한 안전한 선택은 물리적 시간이 진행됨에 따라 증가하는 길이 (하지만 여전히 단항을 사용하지 않음)로 타임 스탬프를 인코딩하는 것입니다. 이것은 우리가 필요로하는 유일한 진정한 시간 속성이며 인코딩이 포착해야하는 속성입니다. 알고리즘에 시간 복잡성이 주어질 수있는 것은 이러한 유형의 인코딩에서만 가능합니까?

혼동이 있다면 ' 시간 복잡성 은 무엇입니까 ?'라는 문구에서 시간 이라는 단어가 있다는 사실에서 발생합니다. 그리고 '얼마나 시간 이 걸릴까요?' 매우 다른 것을 의미합니다

아아, 용어는 같은 단어를 사용하지만 머리 속에 "단계 복잡성"을 사용하여 자신에게 다시 질문 할 수 있습니다. 답이 실제로 ^ _ ^임을 이해하는 데 도움이되기를 바랍니다.


1 이것은 또한 각 인스턴스가 다르지만 임의적이지 않은 길이를 가지므로 점근 적 접근의 필요성을 설명합니다.
2 여기서 올바른 영어 용어를 사용하고 있기를 바랍니다.
3 또한 이것이 우리 log(log(n))가 수학에서 종종 용어를 찾는 이유 입니다.
4 Idest, 단계는 유한하지만 null이 아니거나 연결되지 않은 시간 간격을 차지해야합니다.
5 이것은 물리적 시간에 대한 지식으로서의 계산 모드, 즉 용어로 표현할 수 있음을 의미합니다. 비유는 제네릭이 .NET 프레임 워크에서 작동하는 방식입니다.


3
"그래서 당신의 큰 O 실행 시간은 단지".. 나는 당신이 '큰 O 복잡성'을 의미한다고 확신합니까?. 또한 우리는 여전히 'deltaTime'을 'n'이라고 부를 수 있습니다. 그래서 당신이 말하는 O (2 ^ N)는 피보나치 알고리즘의 복잡성과 같은 것입니다. "2 ^"에 어떻게 오셨습니까?
Ross

@Ross, 요점에 감사드립니다. 이진수로 작업하는 습관이 2를 가지고 왔습니다. 요점은 단계가 숫자 표현의 길이 와 선형이라는 것입니다 . 실제 기본은 실제로 중요하지 않으며 특정 인코딩에 따라 다릅니다. 그것은는 의사 선형 .
Yuni Mj 2015

죄송합니다. 복잡성이 O(2^n)어떻게 결론을 내 렸는지 답변에 더 자세히 설명해 주 시겠습니까? 초보자에게는 명확하지 않습니다.
Arturo Torres Sánchez

2
당신의 논리가 기술적으로 잘못된 것은 아니지만 @YuniMj, 나는 측정하는 주장으로 생각 크기DeltaTime대신의 값을 , 당신은 단지 추가 혼란을 추가하고 있습니다. 예를 들어, 최적의 정렬 알고리즘이없는 이유는 $ O (n \ cdot log n) $ 시간 복잡도를 갖습니다. 왜? 정렬 할 식별 가능한 개체가 한정되어 있기 때문에 항상 버킷 정렬을 사용하여 $ O (n) $에서 정렬 할 수 있습니다. 또는 개체 크기가 제한되지 않습니다.이 경우 $ O (n \ cdot log n) $은 유지되지 않습니다. 단일 비교는 더 이상 일정한 시간을 갖지 않기 때문입니다 ...
fgp

1
FWIW O (2 ^ n)! = O (10 ^ n) stackoverflow.com/questions/19081673/…
Nathan FD

29

여기에 훌륭한 답변이 많이 있지만 모두 조금 다시 말하겠습니다.

Big-O 표기법은 함수 를 설명하기 위해 존재 합니다 . 알고리즘 분석에 적용 할 때 먼저이 알고리즘의 일부 특성을 함수 측면에서 정의해야 합니다 . 일반적인 선택은 입력 크기 의 함수로 단계 수를 고려 하는 것입니다 . 다른 답변에서 언급했듯이 명확하게 정의 된 "입력"이 없기 때문에 귀하의 경우에 그러한 기능을 생각해내는 것이 이상하게 보입니다. 그래도 시도 할 수 있습니다.

  • 우리는 당신의 알고리즘을 어떤 크기의 입력이든 받아들이고, 그것을 무시하고, 고정 된 시간 동안 기다렸다가 끝나는 상수 함수로 간주 할 수 있습니다. 이 경우 런타임은 f (n) = const 이고 O (1) 시간 알고리즘입니다. 이것은 당신이 듣기를 기대했던 것입니다. 예, 기술적으로 O (1) 알고리즘 입니다.
  • 관심있는 TwentyYearsLater"입력 크기"와 유사한 매개 변수로 간주 할 수 있습니다 . 이 경우 런타임은 f (n) = (nx)입니다. 여기서 x 는 호출 시점의 "현재 시간"입니다. 이런 식으로 보면 O (n) 시간 알고리즘입니다. 기술적으로 O (1) 알고리즘 을 다른 사람들에게 보여줄 때마다이 반론을 기대하십시오 .
  • 오,하지만 k =TwentyYearsLater 가 입력이라면 그 크기 n 은 실제로 그것을 나타내는 데 필요한 비트 수입니다. 즉, n = log (k) 입니다. 따라서 입력 n 의 크기 와 런타임 간의 종속성은 f (n) = 2 ^ n-x 입니다. 알고리즘이 기하 급수적으로 느려진 것 같습니다! 으.
  • 프로그램에 대한 또 다른 입력은 실제로 OS가 루프 의 호출 시퀀스에 대해 제공하는 응답 스트림입니다DateTime.Now . 실제로이 전체 시퀀스가 ​​프로그램을 실행하는 순간 입력으로 제공된다고 상상할 수 있습니다. 그런 다음 런타임은이 시퀀스의 속성, 즉 첫 번째 TwentyYearsLater요소 까지의 길이에 의존하는 것으로 간주 할 수 있습니다 . 이 경우 런타임은 다시 f (n) = n 이고 알고리즘은 O (n) 입니다.

그러나 다시 질문에서 런타임에 관심이 있다고 말하지 않았습니다. 메모리 사용을 의미한다면? 상황을 모델링하는 방법에 따라 알고리즘이 O (1)-메모리 또는 아마도 O (n)-메모리라고 말할 수 있습니다 DateTime.Now.

그리고 당신의 목표가 어리석은 것을 생각해내는 것이었다면, 화면에서 알고리즘 코드의 크기 (픽셀 단위)가 선택한 확대 / 축소 수준에 따라 달라지는 방식에 관심이 있다고 말하십시오. 이것은 f (zoom) = 1 / zoom 과 같을 수 있으며 알고리즘을 O (1 / n) 픽셀 크기로 자랑스럽게 선언 할 수 있습니다 !


+1. 나는 " DateTime.Now호출 순서에 대해 OS가 제공하는 응답의 흐름" 이 여기서 실제 입력이라고 생각합니다. 그러나 결론은 O (n)이 아니라 O (k)입니다. 여기서 k는 길이입니다. 첫 번째 TwentyYearsLater요소 까지 .
justhalf

7
이것이 지금까지 최고의 대답입니다. Big O가 의미를 갖기 위해서는 물리적 구현에 수학적 의미론 / 가정을 적용해야합니다 (본질적으로 "입력"의 의미있는 정의로 프로그램에 대한 수학적 모델을 정의). 이런 의미에서 "프로그램"의 복잡성은 적용하는 의미에 따라 달라집니다. N이 작업 수에 따라 선형 적으로 확장되는 시간 차이라고 가정하면 O (n)입니다. 고정 된 기간의 결과로 고정 된 수의 작업을 가정하면 O (1)입니다.
Ant P

21

나는 Servy에 약간 동의하지 않습니다. 이 프로그램에 대한 입력은 명확하지 않더라도 시스템의 시간입니다. 이것은 의도하지 않은 기술 일 수 있지만 TwentyYearsFromNow변수는 현재 시스템 시점 에서 20 년이 아닙니다. 2035 년 1 월 1 일에 정적으로 할당됩니다.

따라서이 코드를 가져 와서 시스템 시간이 1970 년 1 월 1 일인 시스템에서 실행하면 컴퓨터의 속도에 관계없이 완료하는 데 65 년이 걸릴 것입니다 (시계에 결함이있는 경우 약간의 차이가있을 수 있음). ). 이 코드를 가져 와서 시스템 시간이 2035 년 1 월 2 일인 시스템에서 실행하면 거의 즉시 완료됩니다.

귀하의 의견 n은 다음과 같습니다.January 1st, 2035 - DateTime.Now , 그리고 그것의 O (N).

그리고 작업 횟수 문제도 있습니다. 어떤 사람들은 더 빠른 컴퓨터가 더 빨리 루프에 도달하여 더 많은 작업을 유발한다고 지적했지만 이는 관련이 없습니다. big-O 표기법으로 작업 할 때 프로세서의 속도 나 정확한 작업 수를 고려하지 않습니다. 이 알고리즘을 컴퓨터에서 실행 한 다음 다시 실행했지만 동일한 컴퓨터에서 10 배 더 오래 실행하면 작업 수가 10 배의 동일한 요소로 증가 할 것으로 예상됩니다.

이것에 관해서 :

나는 누군가가 특정 복잡한 알고리즘을 요청할 때마다 농담으로 넣는 바쁜 루프로 코드의 [편집 된 코드] 스 니펫을 사용할 생각입니다. 이것이 맞습니까?

아니 정말. 다른 답변에서 이것을 다루었으므로 언급하고 싶었습니다. 일반적으로 수년간의 실행을 big-O 표기법과 연관시킬 수 없습니다. 예 : 20 년의 처형 = O (n ^ 87) 또는 그 문제에 대해 다른 어떤 것도 말할 방법이 없습니다. 당신이 준 알고리즘에서도 TwentyYearsFromNow20110, 75699436 또는 123456789로 변경할 수 있고 big-O는 여전히 O (n)입니다.


7
시간은 함수에 대한 입력이 아니라 메서드 실행 동안 관찰되는 상태지속적으로 변경 합니다. 기능이 실행되는 동안 시스템 시계를 변경할 수도 있습니다 . Big O가 의미를 갖기 위해서는 각 입력이 출력 값과 1-1과 일치하도록해야 할뿐만 아니라이를 계산하는 데 필요한 여러 연산도 필요합니다. 이 조작의 출력 (실제로는 변화 같은 입력에도 일치하지 격렬 ), 동작 횟수에 더하여 수행 또한 격렬 변화.
Servy

When working with big-O notation, we don't consider the speed of the processor or the exact number of operations.이것은 잘못된 진술입니다. Big O 값을 계산하려고 시도하는 거의 모든 현명한 작업은 하드웨어를 기반으로 수행되는 작업 수를 변경 하지 않지만이 작업은 . Big O는 작업 수를 입력 크기와 연관시키는 방법입니다. 시스템 하드웨어와 독립적 인 대부분의 작업에 적합합니다. 이 경우에는 그렇지 않습니다 .
Servy

If you took this algorithm and ran it on a computer, and then ran it again but for 10x longer on the same computer, you would expect the number of operations to grow by the same factor of 10x.그것은 또한 잘못된 진술입니다. 환경은 루프의 작업 수를 반드시 선형으로 변경하지는 않습니다. 예를 들어, 시간이 지남에 따라이 응용 프로그램에 주어진 시간을 지속적으로 변경하여 다른 시점에서 CPU 시간을 더 많이 또는 적게 사용하는 다른 프로그램이 컴퓨터에있을 수 있습니다.
Servy

나는 이것에 대해 @Servy와 함께 있지만 약간 다른 이유가 있습니다. 주 함수는 매개 변수를 취하지 않고 입력을 반환하지 않습니다. 원하는 경우 nil => nil의 함수입니다. 시간은 중요하지 않지만 여전히 아무것도 반환하지 않습니다.
Steve Cooper

1
이 정의를 사용한다면, "수학에서 함수는 각 입력이 정확히 하나의 출력과 관련이 있다는 특성을 가진 입력 세트와 허용 가능한 출력 세트 간의 관계입니다." (wikipedia)-콘솔 출력을 '함수 출력'으로 계산하고 있습니다.이 값은 다양하며 더 빠른 컴퓨터에서는 더 길어집니다. ""아직 인사를 인쇄 할 시간이 아닙니다 ... "" 더 자주.
Steve Cooper

13

Big-O 분석은 처리되는 데이터의 양이 제한없이 증가함에 따라 관련된 처리량을 다룹니다.

여기에서는 실제로 고정 된 크기의 단일 개체 만 처리합니다. 따라서 big-O 분석을 적용하는 것은 용어를 정의하는 방법에 따라 크게 달라집니다 (주로?).

예를 들어, 일반적으로 출력물을 인쇄하고 합리적인 양의 데이터가 정확히 동일한 기간에 인쇄 될 수 있도록 너무 오래 기다려야 함을 의미 할 수 있습니다. 또한 매우 멀리 떨어지려면 다소 비정상적인 (완전히 잘못되지는 않았더라도) 정의를 조금 더 추가해야합니다. 특히 big-O 분석은 일반적 으로 작업을 수행하는 데 필요한 기본 작업 수로 정의됩니다. 특정 작업 (하지만 CPU 사용 / 수행 된 작업뿐만 아니라 메모리 사용과 같은 측면에서도 복잡성을 고려할 수 있음).

기본 작업의 수는 일반적으로 소요 시간에 상당히 가깝게 변환되므로 두 가지를 동의어로 취급하는 것은 큰 무리가 아닙니다. 그러나 불행히도 우리는 처리되는 데이터의 양이 제한없이 증가한다는 다른 부분에 여전히 고착되어 있습니다. 그렇기 때문에 사용자가 부과 할 수있는 고정 지연은 실제로 작동하지 않습니다. O (1)을 O (N)과 동일시하려면, 무한한 양의 데이터처럼 고정 된 양의 데이터를 인쇄하는 데 영원히 걸리도록 무한 지연을 부과해야합니다.


10

무엇에 대한 빅오?

당신은 그것이 twentyYearsLater"입력"이라고 직관하는 것 같습니다 . 실제로 함수를 다음과 같이 작성했다면

void helloWorld(int years) {
   // ...
}

N = 연도 (또는 그냥 O(years) ) 인 )입니다.

나는 당신의 알고리즘이 twentyYearsLater =.로 시작하는 코드 줄에 쓰는 숫자와 관련하여 O (N)이라고 말할 것입니다 . 그러나 사람들은 일반적으로 실제 소스 코드의 숫자를 입력으로 간주하지 않습니다. 그들은 명령 줄 입력을 입력으로 간주하거나 함수 서명 입력을 입력으로 간주 할 수 있지만 소스 코드 자체는 아닐 가능성이 높습니다. 그것이 당신이 친구와 이의를 제기하는 것입니다. 이것이 "입력"입니까? 직관적으로 입력처럼 보이도록 코드를 설정하고 프로그램의 6 행에있는 숫자 N과 관련하여 큰 O 실행 시간을 물을 수 있지만 기본이 아닌 선택을 사용하는 경우 입력으로 당신은 정말로 그것에 대해 명시해야합니다.

그러나 입력을 명령 줄이나 함수에 대한 입력과 같이 더 일반적인 것으로 취하면 출력이 전혀없고 함수는 O (1)입니다. 20 년이 걸리지 만 big-O는 상수 배수로 변하지 않기 때문에 O (1) = O (20 년)입니다.

비슷한 질문-런타임은 무엇입니까?

void sortArrayOfSizeTenMillion(int[] array)

그것이 말하는 것을 수행하고 입력이 유효하고 알고리즘이 퀵 정렬 또는 버블 정렬 또는 합리적인 모든 것을 활용한다고 가정하면 O (1)입니다.


입력을 하드 코딩한다고해서 입력이 사라지는 것은 아닙니다. 어떤 경우에도 퀵 정렬 및 버블 정렬이 O (1) 시간 복잡성이 아닙니다. bigocheatsheet.com
테오 브 링크

@TheoBrinkman 기술적으로 튜링 머신 모델에서 입력에 대해 생각하는 것을 튜링 머신 자체에 인코딩하여 입력이 아닌 정의에 따라 만듭니다. 그런 다음 Turing 머신은 실제 입력에 관계없이 일정한 시간에 실행됩니다. 어떤 의미에서는 "버블 정렬"을 실행하지 않는데, 그 이유는 아무것도 정렬하지 않고 자체 표현에 따라 작동하기 때문입니다. 그러나 비 기술적 인 용어로 알고리즘을 거품 정렬로 설명 할 수 있습니다.
djechlin 2015

마찬가지로 '비 기술적 용어'로 문제의 알고리즘을 현수교로 설명 할 수 있습니다.
Theo Brinkman 2015

@TheoBrinkman 아니, 당신은 할 수 없습니다. 그것은 누구에게도 말이되지 않을 것입니다.
djechlin 2015

O (1) 버블 정렬로 설명하는 것만 큼 모든 것이 이해가됩니다.
Theo Brinkman 2015

8

이 "알고리즘"은 O (1) 또는 일정 시간으로 올바르게 설명됩니다. 이 프로그램에 대한 입력이 없으므로 Big Oh의 관점에서 분석 할 N이 없다는 주장이 있습니다. 입력이 없다는 데 동의하지 않습니다. 이것이 실행 파일로 컴파일되고 호출되면 사용자는 임의 길이의 입력을 지정할 수 있습니다. 그 입력 길이는 N입니다.

프로그램은 입력 (길이에 관계없이)을 무시하므로 소요 시간 (또는 실행 된 기계 명령 수)은 입력 길이 (고정 된 환경 = 시작 시간 + 하드웨어)에 관계없이 동일하므로 O (1 ).


그러나 동일한 시작 시간과 하드웨어를 사용하더라도 작업 횟수 반드시 일치 하지는 않습니다 . 또한 O (1) 알고리즘을 주장하려면 출력이 항상 일정해야하며 그렇지 않으면 시작 시간과 하드웨어에 따라 크게 달라 집니다. 그것은 또한 매우 쉽게 무한 할 수 있으며, 이는 확실히 일정하지 않습니다. 정의한 입력과 수행 된 작업 수 간에는 관계없습니다 . 그것은 일정하지 않고 정의되지 않은 것입니다. 유한 숫자의 이름을 지정할 수 없으며 항상 그보다 적은 작업이 있음을 알 수 있습니다.
Servy

걸리는 최대 실시간 시간은 20 년입니다. 미래에 시작하면 더 오래 걸릴 것입니다. 루프 반복에 걸리는 시간에 유한 하한이 있고 직렬 하드웨어에서 실행되고 있다고 가정 해 보겠습니다. 그런 다음 루프가 실행되는 횟수를 제한 할 수 있습니다. 이는 무시 된 입력의 크기에 관계없이 전체 계산이 상수 함수로 제한 될 수 있음을 의미합니다.
waldol1 2015

Let's suppose that there is a finite lower bound on the amount of time a loop iteration takes그것은 잘못된 가정입니다. 이 프로그램은 영원히 실행될 수 있습니다. 내가해야 할 일은 내 시스템 시계를 지금부터 50 년으로 설정하고 시작하면 결코 끝나지 않을 것입니다. 또는 시계가 앞으로 이동하는 것보다 더 빨리 뒤로 이동하거나 과거의 불확실한 지점에서 시작할 수 있습니다. 프로그램이 실행되는 시간에 하한이 있다고 가정 할 수 없습니다. 영원히 실행될 수 있습니다. 그러나 (거짓) 가정을 참으로 간주하더라도 수행 된 작업 수를 입력과 관련시킬 수 없습니다.
Servy

단일 루프 반복에는 유한 한 시간이 걸립니다. 무한한 횟수로 실행하는 것이 가능할 수 있지만 각각은 대략 일정해야합니다. 나는 그 가정에 문제가 없다고 생각합니다.
waldol1 2015

모든 개별 연산이 항상 일정 하기 때문에 [완전히 잘못된] 논리에 의해 모든 알고리즘은 항상 O (1) 입니다. 당신은 단순히 Big O가 무엇인지 모른다는 것을 보여주고 있습니다. 입력 크기와 수행 된 관련 작업 수 간의 관계를 설명하는 도구입니다. O (1)은 입력에 관계없이 수행되는 작업 수가 일정 함을 의미합니다. 여기에는 입력에 관계없이 수행되는 작업의 수가 일정 하지 않으며 잠재적으로 무한한 작업이 수행됩니다. 무한! = 상수입니다.
Servy

6

내가 놀란 한 가지는 아직 언급되지 않았습니다. big-O 표기법은 상한입니다!

모두가 알아 차린 문제는 알고리즘에 대한 입력을 설명하는 N이 없으므로 big-O 분석을 수행 할 수 없다는 것입니다. 그러나 이것은 int n"Hello World" n시간 을 받아들이고 인쇄 하는 것과 같은 몇 가지 기본적인 속임수로 쉽게 완화됩니다 . 그것은 그 불만을 우회하고 어떻게 그것이 어떻게DateTime 피하고 괴물 작동 입니다.

while 루프가 종료 될 것이라는 실제 보장은 없습니다. 언젠가 는해야한다고 생각 하지만 시스템 날짜와 시간DateTime.now반환 한다고 생각합니다 . 실제로 이것이 단조롭게 증가한다는 보장은 없습니다. 누군가가 원숭이에게 자동 맞춤 신발과 호버 보드를 줄 때까지 병리학 적으로 훈련 된 일부 원숭이가 지속적으로 시스템 날짜와 시간을 2015 년 10 월 21 일 12:00:00 UTC로 변경하고있을 수 있습니다. 이 루프는 실제로 무한한 시간 동안 실행될 수 있습니다!

big-O 표기법의 수학적 정의를 실제로 파헤쳐 보면 상한이됩니다. 그들은 아무리 가능성이 없어도 최악의 시나리오를 보여줍니다. 여기서 최악의 시나리오 * 시나리오는 무한 런타임이므로이 알고리즘의 런타임 복잡성을 설명하는 big-O 표기법이 없음 을 선언해야 합니다. 1/0이 존재하지 않는 것처럼 존재하지 않습니다.

* 편집 : KT와의 토론에서 big-O 표기법으로 모델링하는 시나리오가 최악의 경우라고 가정하는 것이 항상 유효한 것은 아닙니다. 대부분의 경우 개인이 사용중인 케이스를 지정하지 않으면 최악의 케이스를 탐색하려고합니다. 그러나 최상의 경우 런타임에 대해 big-O 복잡성 분석을 수행 할 수 있습니다.


2
O는 어떤 의미에서 "상한"입니다. 그러나 O 표기법을 사용하여 "최악의 경우 복잡성"만 말할 수 있다는 의미는 아닙니다. 예상 복잡성, 최상의 경우 복잡성, 기타 기능적 속성-모두 O 경계 측면에서 논의 할 수 있습니다.
KT.

@KY 최고의 경우 복잡성은 little-o라고하며 예상되는 복잡성은 big-theta입니다. big-o는 수학적 정의로 볼 때 항상 최악의 복잡성입니다.
Cort Ammon 2015

아니, 당신은 여기에서 착각합니다. 정의를 다시 확인하십시오.
KT.

@KT 좋아요, 다시 확인하겠습니다. 당신도 그들을 다시 확인합니다. en.wikipedia.org/wiki/Big_O_notation 바흐 - 랜도 표기법의 가족에서 그것의
콜트 암몬

나는 당신이 함수를 취하고 함수 가 같은 것으로 f선언 하는 것처럼 미친 짓을 할 수 있다고 생각 하지만 제한된 도메인을 사용하여 's best case 만 포함 하고 big-oh on 을 수행하지만 그렇게하면 소리가 나 빠지기 시작합니다. 그. gffg
Cort Ammon 2015

5

복잡성은 시간 / 공간 측면에서 계산 "마력"을 측정하는 데 사용됩니다. Big O 표기법은 어떤 문제가 "계산 가능"인지 "계산 불가능"인지 비교하고 어떤 솔루션 (알고리즘)이 다른 솔루션보다 나은지 비교하는 데 사용됩니다. 따라서 알고리즘을 다항식 시간에 풀 수있는 것과 풀 수없는 두 가지 범주로 나눌 수 있습니다.

Sieve of Erathostene과 같은 문제는 O (n ^ exp)이므로 n의 작은 값에 대해 해결할 수 있습니다. 다항식 시간 (NP)이 아니라 계산 가능하므로 주어진 숫자가 소수인지 아닌지 묻는 질문에 답 은 그러한 숫자의 크기에 따라 달라집니다 . 또한 복잡성은 하드웨어에 의존하지 않으므로 더 빠른 컴퓨터를 사용하면 아무것도 변경되지 않습니다.

Hello World는 알고리즘이 아니므로 복잡성을 결정하려는 시도는 무의미합니다. 간단한 알고리즘은 다음과 같을 수 있습니다. 임의의 숫자가 주어지면 짝수인지 홀수인지 결정합니다. 자, 주어진 숫자가 500 자리라는 것이 중요할까요? 아니요, 마지막 숫자가 짝수인지 홀수인지 확인해야하기 때문입니다. 좀 더 복잡한 알고리즘은 주어진 숫자가 3으로 균등하게 나뉘는지 확인하는 것입니다. 일부 숫자는 계산하기 "쉽지만"다른 숫자는 "어려우며"그 크기 때문입니다. 다음 사이의 나머지를 결정하는 데 걸리는 시간을 비교하십시오. 한 자리 숫자와 500 자리 숫자.

더 복잡한 경우는 텍스트를 디코딩하는 것입니다. 해독 키를 가진 사람들에게 메시지를 전달하는 것으로 알고있는 임의의 기호 배열이 있습니다. 보낸 사람이 왼쪽에있는 키를 사용했고 Hello World가 Gwkki Qieks를 읽었다 고 가정 해 보겠습니다. "big-hammer, no-brain"솔루션은 Aaaa에서 Zzzz까지 이러한 문자에 대한 모든 조합을 생성 한 다음 단어 사전을 검색하여 유효한 단어를 식별하고 암호의 두 공통 문자 (i, k)를 공유합니다. 같은 위치. 이 변환 함수는 Big O가 측정하는 것입니다!


4

대부분의 사람들은 매우 중요한 두 가지를 놓치고있는 것 같습니다.

  1. 이 프로그램은 않는 입력을 가지고있다. 시스템 시간이 비교되는 하드 코딩 된 날짜 / 시간입니다. 입력은 알고리즘을 실행하는 사람이 제어하고 시스템 시간은 그렇지 않습니다. 이 프로그램을 실행하는 사람이 제어 할 수있는 유일한 것은 비교에 하드 코딩 한 날짜 / 시간입니다.

  2. 프로그램은 입력 에 따라 달라 지지만 big-O 표기법과 관련된 입력 세트 의 크기가 아닙니다 .

따라서 이것은 불확실하며이 프로그램에 가장 적합한 'big-O'표기법은 아마도 O (null) 또는 O (NaN) 일 것입니다.


1
(2) 플랫 아웃이 잘못되었습니다. 일반적으로 "입력 길이"가 고려됩니다. 고정 크기 객체 (예 : 정수)의 목록 또는 배열의 경우 실제로 세트의 크기가됩니다. 1395195191600333과 같은 숫자를 인수 분해하려면 이진수 (또는 십진수 등) 표현의 길이, 즉 자릿수입니다. (2)에서 정의한대로 big-O를 사용하여 "findPrimeFactors (int num)"의 복잡성을 논의하는 것을 금지하며, 대부분의 암호학자는이를 반대합니다.
djechlin 2015

4

N을 정의하지 않는다는 모든 사람들이 올바르게 지적 했지만 대답은 가장 합리적인 해석 아래에 있지 않습니다. N 이 인쇄 할 문자열의 길이 이면 "hello, world!" 이것은 단지 예일뿐입니다.“for”라는 알고리즘으로이 설명에서 추론 할 수 hello, world!있으므로 알고리즘은 O ( N )입니다. 인쇄하는 데 30 년, 40 년 또는 50 년이 걸리는 출력 문자열이있을 수 있습니다. 여기에 일정한 시간 만 추가됩니다. O ( kN + c ) ∈ O ( N ).

추가:

놀랍게도 누군가 이의를 제기하고 있습니다. big O와 big Θ의 정의를 기억하십시오. 일정한 시간 c 를 기다린 다음 선형 시간 으로 길이 N 의 메시지를 출력 하는 알고리즘이 있다고 가정합니다 . (이것은 원본 코드 샘플의 일반화입니다.) 인쇄를 시작하는 데 20 년이 걸리고 1 조 개의 문자를 인쇄하는 데 20 년이 더 걸린다고 임의로 가정 해 봅시다. 예를 들어, c = 20 및 k = 10¹²라고 합시다 . 그러나 양의 실수라면 가능합니다. 이는 문자 당 d = c / k (이 경우 2 × 10⁻¹¹) 년의 비율이므로 실행 시간 f ( N )는 점근 적으로dN + c 년. 마다 N > K , DN = C / K N > C . 따라서 모든 N > kf ( N ) ∈ Θ ( N )에 대해 dN < dN + c = f ( N ) <2 dN 입니다 . QED


우리는 N = 13가 어디
djechlin

그러나 "Hello world"만 인쇄하는 것이 아니라 알 수없는 수의 "아직 시간이 아닙니다"줄을 인쇄합니다. 또한 Big O는 실제로 입력 크기와 출력 크기를 비교하는 데 사용되지 않으며 일반적으로 입력 크기를 작업 수 또는 사용 된 메모리 양과 비교하는 데 사용됩니다.
Servy

@Servy 상수 메모리이지만 실행 시간을 암시 적으로 제한했습니다. 임의의 문자열 에 대해 출력의 크기도 O ( N )입니다. 때가되면 인쇄하는 문자열은 20 년 분량의 please-wait 메시지와 비교해도 임의로 클 수 있습니다.
Davislor

@Servy 나는 여기서 N 이 출력 크기가 아니라는 것을 명확히하기 위해 편집했습니다 . 어떻게 그 인상을 주 었는지 모르겠지만 모호한 부분을 제거하겠습니다.
Davislor 2015

1
따라서 프로그램이 입력을받는다고 가정하면, 그렇지 않을 때 출력이 임의로 클 수 있고, 할 수 없을 때 루프가 아무 작업도하지 않고, 수행 할 때, 출력이 다음과 관련이 있다고 가정합니다. 입력이 아닌 경우 예, 프로그램은 선형입니다. 물론 이러한 가정은 모두 완전히 거짓이므로 그로부터 도출 한 결론은 유효하지 않습니다. 잘못된 가정을하지 않고 자신의 요점을 입증 할 수 있다면 그것은 의미가있는 것입니다.
Servy dec. 05 dec. 152015-12-05

4

코드가 전통적인 알고리즘처럼 보이지 않기 때문에 사람들이 버려지고 있다고 생각 합니다. 다음은 더 잘 구성된 코드의 번역이지만 OP의 질문 정신에 충실합니다.

void TrolloWorld(long currentUnixTime, long loopsPerMs){
    long laterUnixTime = 2051222400000;  //unix time of 01/01/2035, 00:00:00
    long numLoops = (laterUnixTime-currentUnixTime)*loopsPerMs;

    for (long i=0; i<numLoops; i++){
        print ("It's still not time to print the hello …");
    }
    print("Hello, World!");
}

입력은 명시 적이지만 코드가 시작된 시간과 코드를 실행하는 하드웨어의 속도에 의해 암시 적으로 제공되기 전에는 명시 적입니다. 코드는 결정적이며 주어진 입력에 대해 잘 정의 된 출력을 가지고 있습니다.

우리가 제공 할 수있는 입력에 부과 된 제한 때문에 실행될 연산의 수에 상한이 있으므로이 알고리즘은 실제로 O (1)입니다.


2

이 시점에서 yes

이 알고리즘에는 암시 적 입력, 즉 프로그램이 시작되는 시간이 있습니다. 실행 시간 은 시작시기에 따라 선형 적으로 1 달라집니다. 2035 년 이후에는 while 루프가 즉시 종료되고 프로그램은 상수 작업 2 후에 종료됩니다 . 따라서 런타임이 O(max(2035 - start year, 1))3 이라고 말할 수 있습니다 . 그러나 시작 연도에는 최소값이 있으므로 알고리즘을 실행하는 데 20 년 이상 걸리지 않습니다 (예 : 상수 값).

4 를 정의하여 의도에 맞게 알고리즘을 만들 수 있습니다.DateTime TwentyYearsLater = DateTime.Now + new TimeSpan(365*20,0,0,0);

1 이것은 시간 단위당 최대 작업 수가 있기 때문에 작업 수로 측정되는 실행 시간에 대한보다 기술적 감각을 유지합니다.
2 가져 오기 DateTime.Now가 지속적인 작업 이라고 가정하면 합리적입니다.
3 나는 여기에서 big O 표기법을 다소 남용하고 있는데, 왜냐하면 이것은에 대해 감소하는 함수이기 때문입니다. start year그러나 우리는 이것을years prior to 2035 .
4 그러면 알고리즘이 더 이상 시작 시간의 암시 적 입력에 의존하지 않지만 이는 중요하지 않습니다.


1

나는 이것이 O (n)이라고 주장하고 싶습니다. 사용 http://www.cforcoding.com/2009/07/plain-english-explanation-of-big-o.html을 참조한다.

Big O는 무엇입니까?

Big O 표기법은 키 요소가 무한대를 향하는 경향이있을 때 성장률을 키 요소로 줄임으로써 알고리즘의 상대적 복잡성을 설명하려고합니다.

내가 생각할 수있는 Big-O의 가장 좋은 예는 산술을하는 것입니다. 학교에서 배운 기본적인 산술 연산은 다음과 같습니다.

덧셈; 빼기; 곱셈; 그리고 부서. 이들 각각은 작업 또는 문제입니다. 이를 해결하는 방법을 알고리즘이라고합니다.

예를 들어,

n = 20 (년 단위)의 입력이 주어지면.

알고리즘은 수학 함수 f ()입니다. 여기서 f ()는 '디버그'문자열을 사이에두고 n 년 동안 대기합니다. 축척 계수는 1입니다. f ()는이 축척 계수를 변경하여 감소 / 또는 증가시킬 수 있습니다.

이 경우 출력도 20입니다 (입력을 변경하면 출력이 선형으로 변경됨).

본질적으로 기능은

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