컴퓨터/수학이랑

배열의 모든 요소가 같은 부호를 갖고 있는지 판단하기

adnoctum 2010. 6. 9. 18:33


   해결해야 하는 문제는 배열(container)에 있는 모든 요소(실수 형)가 같은 부호를 갖고 있는지를 판단하는 것이다. 가장 직관적인 방법은 아마도 다음과 같을 것이다.

bool all_value_have_same_sign(const std::vector<double>& value)

{

        if(value.empty() == true) return false;

        if(value.size() == 1) return true;

        bool is_negative = (value[0] < 0);

        bool is_positive = (value[0] > 0);

        std::vector<double>::const_iterator pos = value.begin() + 1;

        for(; pos != value.end(); pos++){

                is_negative &= (*pos < 0);

                is_positive &= (*pos > 0);

                if(is_negative == false && is_positive == false) return false;

        }

        return true;

}



즉, 배열의 모든 원소를 차례대로 순회를 하는데, 한 변수 (위 코드에서 is_negative)는 지금까지의 값들이 음수였는지를 기록하고, 또 다른 변수 하나 (위 코드에서 is_positive)는 지금까지의 값들이 양수였는지를 기록하는 것이다. 만약 이 두 변수가 모두 false가 되면 부호가 다른 값을 만나는 것이 된다. 왜냐 하면, 다음과 같기 때문이다.



두 번째 아이디어는 인접한 두 요소의 부호가 같은지만을 판단하는 것이다.

bool all_value_have_same_sign(const std::vector<double>& value)

{

        if(value.empty() == true) return false;

        if(value.size() == 1) return true;

        bool is_negative = (value[0] < 0);

        std::vector<double>::const_iterator pos = value.begin() + 1;

        for(; pos != value.end(); pos++){

            if(is_negative != (*pos < 0)) return false;

            is_negative = (*pos < 0);

        }

        return true;

}


이것에 대한 증명은 다음과 같다.

원소가 (v1, ..., vn) 이 있을 때, sign(v_i) == sign(v_{i+1}) for all i = 1, ..., n-1 only if sign(v_i) == sign(v_j} for all 1 <= i, j <= n 이 맞는지를 확인해 보면 된다. Let sign(v_i) == sign(v_{i+1}) for all i = 1, ..., n-1 (1). Suppose that ∃ i < j such that sign(v_i) ≠ sign(v_j). If i - j = 1, then it contradicts to (1). Therefore, there must be (a_1, ..., a_m) such that i < (a_1, ..., a_m) < j. By (1), sign(v_i) == sign(v_{a_1}). By the induction, sign(v_{a_m}) == sign(v_j), which is contradiction. Q.E.D.

조금 쉽게, 다시 설명하면, 우리가 알아 보고자 하는 것은, 모든 인접한 두 원소의 부호가 같을 때, 전체 원소가 모두 같은 부호를 갖고 있는가? 이다. 즉, i 번째 부호와 i+1 번째 부호가 모든 i 에 대하여 같았을 때, 어느 두 원소를 선택해도 부호가 같을 것인가? 이다. 모든 i 에 대하여 i 번째와 i+1 번째의 부호가 같았는데(1), 어느 두 원소를 뽑았더니 부호가 다른 원소가 있었다고 가정해 보자. 그 각각의 원소의 인덱스를 a 와 b라고 하고, a 가 더 작은 값이라고 하자. 만약 a == b + 1 이었다면 (1)에 모순되기 때문에 말이 안되므로 a 와 b 사이에는 몇 개의 정수가 들어 갈 수 있게 되서, (a, a+1, ..., b-1, b) 의 sub-sequence를 만들 수 있게 된다. (1)에 의해 a 번째와 a+1 번째 원소의 부호는 같아야 하며, 같은 식으로 계속 해나가다 보면 b-1번째와 b번째의 부호도 같아야 하고, 따라서 a 번째부터 b번째의 원소의 부호는 모두 같다. 그런데 이것은 가정에 모순이므로, 모든 i 에 대하여 i 번째와 i+1 번째의 부호가 같았는데, 어느 두 원소를 뽑았더니 부호가 다른 원소가 있을 수는 없다. 즉, 모든 i 에 대하여 i 번째와 i+1 번째의 부호가 같다면 모든 원소의 부호가 같다.


그런데, 좀 더 생각을 해보면, 아주 간단하게는 모든 원소의 부호가 첫 번째 원소의 부호와 같으면 된다. 증명은 쉽고, 코드도 쉽다... >.<"" 어려운 문제인 줄 알았는데... ㅋㅋㅋ 두 실수 (a,b)에 대하여 relation R을 부호의 같음으로 정의하면 R은 equivalence relation 이 되기 때문에.