#include <bits/stdc++.h>

#define REP(i,n) for(int i=0;i<(int)(n);i++)
#define ALL(x) (x).begin(),(x).end()

using namespace std;

using ll = long long;
using ld = long double;

template <typename T> T &chmin(T &a, const T &b) { return a = min(a, b); }
template <typename T> T &chmax(T &a, const T &b) { return a = max(a, b); }

struct yes_no : numpunct<char> {
  string_type do_truename()  const { return "Yes"; }
  string_type do_falsename() const { return "No"; }
};

struct Edge{ int src, dest; };

using Edges = vector<Edge>;
using Graph = vector<Edges>;

void add_edge(Graph &g, int from, int to) {
  g[from].push_back((Edge){from, to});
}

int scc(Graph &graph, vector<int> &cmp) {
  int V = graph.size();
  vector<vector<int>> g(V), rg(V);
  vector<int> vs;
  vector<bool> used(V, false);
  cmp.resize(V);
  REP(i,V) {
    for (Edge e: graph[i]) {
      g[i].push_back(e.dest);
      rg[e.dest].push_back(i);
    }
  }
  function<void(int)> dfs = [&g, &vs, &used, &dfs](int v) {
    used[v] = true;
    for (int i: g[v]) if (!used[i]) dfs(i);
    vs.push_back(v);
  };
  function<void(int,int)> rdfs = [&rg, &cmp, &used, &rdfs](int v, int k) {
    used[v] = true; cmp[v] = k;
    for (int i: rg[v]) if (!used[i]) rdfs(i, k);
  };
  REP(v,V) if (!used[v]) dfs(v);
  used = vector<bool>(V, false);
  reverse(ALL(vs));
  int k = 0;
  for(int i: vs) if (!used[i]) rdfs(i, k++);
  return k;
}

void make_edges(vector<pair<int,int>> &edges, int &offset, int &size) {
  if (size == 1) { ++offset; return; }
  REP(i,size) edges.emplace_back(offset + i, offset + size + i / 2);
  offset += size;
  size = (size + 1) / 2;
  make_edges(edges, offset, size);
}

void range(int l, int r, int offset, int size, vector<int> &vec) {
  if (l >= r) return;
  if (l % 2) { vec.push_back(offset + l); ++l; }
  if (r % 2) { vec.push_back(offset + r-1); --r; }
  range(l / 2, r / 2, offset + size, (size + 1) / 2, vec);
}

bool is_ok(const vector<int> &a, const vector<int> &b,
           const vector<int> &x, int d) {
  const int n = a.size();
  vector<pair<int,int>> edges;
  int offset = 2 * n, size = x.size();
  make_edges(edges, offset, size);
  Graph g(offset + 4 * n);
  for (auto e: edges) add_edge(g, e.second, e.first);
  REP(i,n) {
    add_edge(g, 2 * n + lower_bound(ALL(x), a[i]) - begin(x), 2 * i + 1);
    add_edge(g, 2 * n + lower_bound(ALL(x), b[i]) - begin(x), 2 * i);
  }
  vector<pair<int,int>> xvec;
  REP(i,n) xvec.emplace_back(a[i], i * 2 + 1);
  REP(i,n) xvec.emplace_back(b[i], i * 2);
  sort(ALL(xvec));
  REP(i,n*2-1) {
    if (xvec[i].first == xvec[i+1].first) {
      add_edge(g, offset + i, offset + i + 1);
      add_edge(g, offset + 2 * n + i + 1, offset + 2 * n + i);
    }
  }
  REP(i,n*2) {
    add_edge(g, offset + i, xvec[i].second);
    add_edge(g, offset + 2 * n + i, xvec[i].second);
  }
  REP(i,n) {
    int from = upper_bound(ALL(x), a[i] - d) - begin(x);
    int to   = lower_bound(ALL(x), a[i] + d) - begin(x);
    int me   = lower_bound(ALL(x), a[i]) - begin(x);
    vector<int> vec;
    range(from, me, 2 * n, int(x.size()), vec);
    for (int j: vec) add_edge(g, 2 * i, j);
    vec.clear();
    range(me + 1, to, 2 * n, int(x.size()), vec);
    for (int j: vec) add_edge(g, 2 * i, j);

    int it = lower_bound(ALL(xvec), make_pair(a[i], i * 2 + 1)) - begin(xvec);
    if (it + 1 != int(xvec.size()) && xvec[it].first == xvec[it+1].first)
      add_edge(g, i * 2, offset + it + 1);
    if (it - 1 >= 0 && xvec[it].first == xvec[it-1].first)
      add_edge(g, i * 2, offset + 2 * n + it - 1);
  }
  REP(i,n) {
    int from = upper_bound(ALL(x), b[i] - d) - begin(x);
    int to   = lower_bound(ALL(x), b[i] + d) - begin(x);
    int me   = lower_bound(ALL(x), b[i]) - begin(x);
    vector<int> vec;
    range(from, me, 2 * n, int(x.size()), vec);
    for (int j: vec) add_edge(g, 2 * i + 1, j);
    vec.clear();
    range(me + 1, to, 2 * n, int(x.size()), vec);
    for (int j: vec) add_edge(g, 2 * i + 1, j);

    int it = lower_bound(ALL(xvec), make_pair(b[i], i * 2)) - begin(xvec);
    if (it + 1 != int(xvec.size()) && xvec[it].first == xvec[it+1].first)
      add_edge(g, i * 2 + 1, offset + it + 1);
    if (it - 1 >= 0 && xvec[it].first == xvec[it-1].first)
      add_edge(g, i * 2 + 1, offset + 2 * n + it - 1);
  }
  vector<int> cmp;
  scc(g, cmp);
  REP(i,n) {
    if (cmp[i * 2] == cmp[i * 2 + 1]) return false;
  }
  return true;
}

int main() {
  int n;
  cin >> n;
  vector<int> a(n), b(n);
  REP(i,n) cin >> a[i] >> b[i];
  int lb = 0, ub = 1e9 + 100;

  vector<int> x;
  for (int i: a) x.push_back(i);
  for (int i: b) x.push_back(i);
  sort(ALL(x));
  auto it = unique(ALL(x));
  x.erase(it, end(x));

  while (ub - lb > 1) {
    const int mid = (lb + ub) / 2;
    if (is_ok(a, b, x, mid)) lb = mid; else ub = mid;
  }
  cout << lb << endl;
  return 0;
}


Measured memory_bytes: 29268