假设两个半圆的坐标分别是 (x1,x2), (y1, y2),其中 x2>x1 && y2>y1,那么两个圆是否相交的条件可以有:

  • y2 > x2 > y1 > x1
  • x2 > y2 > x1 > y1

这两种情况对应下面的 isInterSectAisInterSectB,这个题的空间复杂度只需要 O(1) 即上述的 4 个点即可,为了减少代码量,这里使用了数组,可以优化一下。

需要循环判断所有点,所以时间复杂度是 O(N)。

flag = flag || isInterSectA(dotVec, dotVec.size()-1) || isInterSectB(dotVec, dotVec.size()-1); 这句话将 flag 判断放到最前面,一旦出现符合的情况,之后就不再判断情况1和情况 2,稍微优化了一下。

#include <bits/stdc++.h>
using namespace std;

bool isInterSectB(vector<int> &dotVec, int i) {
    return max(dotVec[i-2], dotVec[i-3]) > max(dotVec[i], dotVec[i-1])  && 
        max(dotVec[i], dotVec[i-1]) > min(dotVec[i-2], dotVec[i-3]) && 
        min(dotVec[i-3], dotVec[i-2]) > min(dotVec[i], dotVec[i-1]);
}

bool isInterSectA(vector<int> &dotVec, int i) {
    return max(dotVec[i], dotVec[i-1]) > max(dotVec[i-2], dotVec[i-3]) && 
        max(dotVec[i-2], dotVec[i-3]) > min(dotVec[i], dotVec[i-1]) && 
        min(dotVec[i], dotVec[i-1]) > min(dotVec[i-3], dotVec[i-2]);
}


int main() {
    int sample, dotNum, dot; cin >> sample;
    while (sample--) {
        cin >> dotNum;
        vector<int> dotVec; bool flag = false;
        while (dotNum--) {
            cin >> dot;
            if (dotVec.size() < 4) {
                dotVec.push_back(dot);
            } 
            if (dotVec.size() >= 4) {
                flag = flag || isInterSectA(dotVec, dotVec.size()-1) || isInterSectB(dotVec, dotVec.size()-1);
                dotVec.push_back(dot);
            } 
        }
        cout << (flag ? "y" : "n") << endl;
    }
    return 0;
}