まず、配列を昇順にソートしましょう。
すると、かならず0 <= P < Q < R < Nにたいしては、A[P] <= A[Q] <= A[R]となりますね。
とりあえず、全部正の整数0以上の整数と考えましょう。
(0 < A[P] <= A[Q] <= A[R]).
ソートされているので、以下の事が言えます。
条件 'A[P] < A[Q] + A[R]' は常に成り立つ。
条件 'A[Q] < A[P] + A[R]' も常に成り立つ。
(A[R]は既に、A[P]、A[Q]よりも大きいですから、正の数を足しても大きいままですね)
ですから条件'A[R] < A[P] + A[Q]'だけをチェックすればいいのですね。
一つでも条件全てにあうtriangularなものがあるかないかを、1か0で返せという問題ですから、あるA[R]にたいして一番大きいA[P] + A[Q]だけを調べればいいということです。(そうすれば全ての条件が成り立つものがあるということになり1を返せば良い)
ということは、連続する3つのスロットをそれぞれA[P]、A[Q]、A[R]として調べればいいですね。
またもとにもどって、なぜ、0以下の値を無視していいのかを考えましょう。
もし、 A[P] <= 0 <= A[Q] <= A[R]であったら、A[P] + A[Q] <= A[Q]になりますね。そうすると’A[P] + A[Q] <= A[Q] <= A[R]’になりますので、条件’A[R] < A[P] + A[Q]’は成り立たなくなります。ですからすべて0以下になるようなPは全て無視していいのです。
この方針で100%のスコアになります。O(N log (N))の時間的な計算量を指定されているので、マージ・ソートなどを使う方が確実ですが(クイック・ソートの最悪実行時間はこれより大きい)、Cにはマージ・ソートのライブラリが標準でないので、qsortを使っています。
また、qsort用の比較関数で’return *(int*)a - *(int*)b;’とやってしまうと、アンダーフローして間違った比較がなされる事があります。同様に'r < p + q' として比較してしまうと、p + qがオーバーフローしてしまうので’r - p < q ’と書き換えて比較しましょう。(この辺で100%でなかったのでハマってました…orz)
int compare_int(const void *a, const void *b)
{
//don't do 'return *(int*)a - *(int*)b;',
//as this can cause underflow or overflow.
if (*(int*)a == *(int*)b){
return 0;
}
if (*(int*)a < *(int*)b){
return -1;
}
return 1;
}
int solution(int A[], int N)
{
if (N < 3){
return 0;
}
qsort(A, N, sizeof(int), compare_int);
int i;
for (i = 2; i < N; i++){
int p = A[i - 2];
int q = A[i - 1];
int r = A[i];
//neglect negative values.
if (p <= 0){
continue;
}
//if write like 'r < p + q', 'p + q' may overflow.
if (r - p < q ){
return 1;
}
}
return 0;
}
0 件のコメント:
コメントを投稿