#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<ll, ll> l_l;
typedef pair<int, int> i_i;
typedef vector<vector<int>> UnWeightedGraph;
template<class T>
inline bool chmax(T &a, T b) {
    if(a < b) {
        a = b;
        return true;
    }
    return false;
}

template<class T>
inline bool chmin(T &a, T b) {
    if(a > b) {
        a = b;
        return true;
    }
    return false;
}

#define EPS (1e-7)
#define INF (1e9)
#define PI (acos(-1))
//const ll mod = 1000000007;
template< typename G >
struct StronglyConnectedComponents {
  const G &g;
  UnWeightedGraph gg, rg;
  vector< int > comp, order, used;

  StronglyConnectedComponents(G &g) : g(g), gg(g.size()), rg(g.size()), comp(g.size(), -1), used(g.size()) {
    for(int i = 0; i < g.size(); i++) {
      for(auto e : g[i]) {
        gg[i].emplace_back((int) e);
        rg[(int) e].emplace_back(i);
      }
    }
  }

  int operator[](int k) {
    return (comp[k]);
  }

  void dfs(int idx) {
    if(used[idx]) return;
    used[idx] = true;
    for(int to : gg[idx]) dfs(to);
    order.push_back(idx);
  }

  void rdfs(int idx, int cnt) {
    if(comp[idx] != -1) return;
    comp[idx] = cnt;
    for(int to : rg[idx]) rdfs(to, cnt);
  }

  void build(UnWeightedGraph &t) {
    for(int i = 0; i < gg.size(); i++) dfs(i);
    reverse(begin(order), end(order));
    int ptr = 0;
    for(int i : order) if(comp[i] == -1) rdfs(i, ptr), ptr++;

    t.resize(ptr);
    for(int i = 0; i < g.size(); i++) {
      for(auto &to : g[i]) {
        int x = comp[i], y = comp[to];
        if(x == y) continue;
        t[x].push_back(y);
      }
    }
  }
};

i_i indexes[10005];
int N;

struct LazySegmentTree {
private:
    int n;
    UnWeightedGraph g;

public:
    LazySegmentTree() {
        int sz = 2 * N;
        n = 1; while(n < sz) n *= 2;
        g.resize(2 * n - 1);
        //cerr << "SIZE: " << 2 * n - 1 << endl;
        for(int i=n-2; i>=0; i--) {
            g[i].push_back(i*2+1);
            g[i].push_back(i*2+2);
            //cerr << "from " << i << " to " << i *2 + 1 << endl;
            //cerr << "from " << i << " to " << i *2 + 2 << endl;
        }
    }

/*
    // k 番目のノードについて遅延評価を行う
    void eval(int k, int l, int r) {

    // 遅延配列が空でない場合、自ノード及び子ノードへの
    // 値の伝播が起こる
        if(lazy[k] != 0) {
            node[k] += lazy[k];

        // 最下段かどうかのチェックをしよう
        // 子ノードは親ノードの 1/2 の範囲であるため、
        // 伝播させるときは半分にする
            if(r - l > 1) {
                lazy[2*k+1] += lazy[k] / 2;
                lazy[2*k+2] += lazy[k] / 2;
            }

        // 伝播が終わったので、自ノードの遅延配列を空にする
            lazy[k] = 0;
        }
    }
*/
    void add(int a, int b, ll from, int k=0, int l=0, int r=-1) {
        if(r < 0) r = n;

    // 範囲外なら何もしない
        if(b <= l || r <= a) return;
    
    // 完全に被覆しているならば、遅延配列に値を入れた後に評価
        if(a <= l && r <= b) {
            g[from + n - 1].push_back(k);
            //cerr << "from: " << from+n-1 << " to " << k << endl;
        }

    // そうでないならば、子ノードの値を再帰的に計算して、
    // 計算済みの値をもらってくる
        else {
            add(a, b, from, 2*k+1, l, (l+r)/2);
            add(a, b, from, 2*k+2, (l+r)/2, r);
        }
    }

    bool run() {
        UnWeightedGraph tmp(2 * n - 1);
        StronglyConnectedComponents<UnWeightedGraph> SCC(g);
        SCC.build(tmp);
        for(int i = 1; i <= N; i++) {
            if(SCC[indexes[i].first + n-1] == SCC[indexes[i].second + n-1]) return false;
        }
        return true;
    }
};

vector<i_i> v;
int x[10005], y[10005];

int main() {
    //cout.precision(10);
    cin.tie(0);
    ios::sync_with_stdio(false);
    cin >> N;
    for(int i = 1; i <= N; i++) {
        cin >> x[i] >> y[i];
        v.push_back({x[i], i * 2});
        v.push_back({y[i], i * 2 + 1});
    }
    sort(v.begin(), v.end());
    for(int i = 1; i <= N; i++) {
        auto itr = lower_bound(v.begin(), v.end(), make_pair(x[i], i*2));
        indexes[i].first = distance(v.begin(), itr);
        itr = lower_bound(v.begin(), v.end(), make_pair(y[i], i*2+1));
        indexes[i].second = distance(v.begin(), itr);
        //cerr << i << " " << indexes[i].first << " " << indexes[i].second << endl;
    }
    int ok = 0;
    int ng = 1e9;
    while(ng - ok > 1) {
        int mid = (ok + ng) / 2;
        //cerr << "---" << mid << "---" << endl;
        LazySegmentTree seg;
        /*
        for(int i = 0; i < v.size(); i++) {
            auto itr = lower_bound(v.begin(), v.end(), v[i] - mid + 1);
            int i1 = distance(v.begin(), itr);
            itr = lower_bound(v.begin(), v.end(), v[i] + mid);
            int i2 = distance(v.begin(), itr);
            cerr << i << " " << i1 << " " << i2 << endl;
            seg.add(i1, i2, i);
        }
        */
        for(int i = 1; i <= N; i++) {
            auto itr = lower_bound(v.begin(), v.end(), make_pair(x[i] - mid + 1, 0));
            int i1 = distance(v.begin(), itr);
            itr = lower_bound(v.begin(), v.end(), make_pair(x[i] + mid, 0));
            int i2 = distance(v.begin(), itr);
            //cerr << indexes[i].second << " " << i1 << " " << i2 << endl;
            seg.add(i1, indexes[i].first, indexes[i].second);
            seg.add(indexes[i].first + 1, i2, indexes[i].second);
            itr = lower_bound(v.begin(), v.end(), make_pair(y[i] - mid + 1, 0));
            i1 = distance(v.begin(), itr);
            itr = lower_bound(v.begin(), v.end(), make_pair(y[i] + mid, 0));
            i2 = distance(v.begin(), itr);
            //cerr << indexes[i].first << " " << i1 << " " << i2 << endl;
            seg.add(i1, indexes[i].second, indexes[i].first);
            seg.add(indexes[i].second + 1, i2, indexes[i].first);
        }
        if(seg.run()) ok = mid;
        else ng = mid;
    }
    cout << ok << endl;
    return 0;
}


Measured memory_bytes: 25000