#include <bits/stdc++.h>
using namespace std;
using Pint = pair<int, int>;

struct DirectedGraph
{
    int V; // 頂点数
    vector<vector<int> > to;
    vector<vector<int> > from;

    vector<bool> used;
    vector<int> vs;

    void dfs(int v)
    {
        used[v] = true;
        for (auto t : to[v]) if (!used[t]) dfs(t);
        vs.push_back(v);
    }
    void rdfs(int v, int k)
    {
        used[v] = true;
        cmp[v] = k;
        for (auto t : from[v]) if (!used[t]) rdfs(t, k);
    }

public:
    vector<int> cmp;
    DirectedGraph(int V) : V(V),
                           to(vector<vector<int> >(V)), 
                           from(vector<vector<int> >(V)),
                           cmp(vector<int>(V))
                           {}
    void add_edge(int from_, int to_)
    {
        to[from_].push_back(to_);
        from[to_].push_back(from_);
    }

    int scc()
    {
        used = vector<bool>(V, false);
        vs.clear();
        for (int v = 0; v < V; v++) if (!used[v]) dfs(v);

        used = vector<bool>(V, false);
        int k = 0;
        for (int i = vs.size() - 1; i >= 0; i--) if (!used[vs[i]]) rdfs(vs[i], k++);
        return k;
    }
};

int N;
int MMAX;
vector<Pint> z;
vector<int> zinv;

void segTreeadd(int iz, int l, int r, int now, int begin, int end, DirectedGraph &g)
{
    if (r <= begin || l >= end) return;
    if (l<=begin && end<=r)
    {
        g.add_edge(MMAX - 1 + iz, 2 * MMAX + now);
    }
    else if (end - begin > 1) {
        segTreeadd(iz, l, r, now*2+1, begin, (begin+end)/2, g);
        segTreeadd(iz, l, r, now*2+2, (begin+end)/2, end, g);
    }
}

bool nibun(int d)
{
    DirectedGraph g(MMAX * 4);
    
    // Prepare for binary trees
    // index of g:
    // 0 ~ MMAX - 1 segTreeT 不要
    // MMAX-1 ~ MMAX-1 + N*2 flag z[i]
    // 2MMAX ~ 3MMAX - 1 segTreeF
    // 3MMAX-1 ~ 3MMAX-1 + N*2 flag ~z[i]

    for (int i=0; i<N; i++)
    {
        int ix = zinv[i];
        int iy = zinv[i+N];
        g.add_edge(MMAX - 1 + ix, 3*MMAX-1 + iy);
        g.add_edge(3*MMAX-1 + iy, MMAX - 1 + ix);
        g.add_edge(MMAX - 1 + iy, 3*MMAX-1 + ix);
        g.add_edge(3*MMAX-1 + ix, MMAX - 1 + iy);
    }

    // "SegTree"構築
    for (int i=0; i<MMAX-1; i++)
    {
        g.add_edge(2 * MMAX + i, 2 * MMAX + 2*i + 1);
        g.add_edge(2 * MMAX + i, 2 * MMAX + 2*i + 2);
    }

    // 制約をSegTreeに貼り付け
    for (int i=0; i<2*N; i++)
    {
        int l = distance(z.begin(), lower_bound(z.begin(), z.end(), Pint(z[i].first-d, 2*N)));
        int r = distance(z.begin(), upper_bound(z.begin(), z.end(), Pint(z[i].first+d, -1)));
        segTreeadd(i, l, i, 0, 0, MMAX, g);
        segTreeadd(i, i+1, r, 0, 0, MMAX, g);
    }

    g.scc();
    for (int i = 0; i < 2 * N; i++) if (g.cmp[MMAX - 1 + i] == g.cmp[3 * MMAX - 1 + i]) return false;
    
    return true;
}

int main()
{
    cin >> N;
    MMAX = 1;
    while (MMAX < N) MMAX *= 2;
    MMAX *= 2;
    for (int i=0; i<N; i++)
    {
        int x, y; cin >> x >> y;
        z.push_back(Pint(x, i));
        z.push_back(Pint(y, i+N));
    }
    sort(z.begin(), z.end());
    zinv.resize(2*N);
    for (int i=0; i<2*N; i++) zinv[z[i].second] = i;

    int l = 0;
    int r = 1E9;
    while (r - l > 1)
    {
        if (nibun((l + r)/2)) l = (l + r) / 2;
        else r = (l + r) / 2;
    }
    cout << l << endl;
    return 0;
}


Measured memory_bytes: 22648