#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <climits>
#include <cfloat>
#include <cstring>
#include <map>
#include <utility>
#include <set>
#include <iostream>
#include <memory>
#include <string>
#include <vector>
#include <list>
#include <algorithm>
#include <functional>
#include <sstream>
#include <complex>
#include <stack>
#include <queue>
#include <unordered_set>
#include <unordered_map>
#include <array>
#include <cassert>
#include <bitset>
using namespace std;
using LL = long long;

namespace scc_space
{
	void dfs(int v_, vector<bool>&used_, vector<int>G_[], vector<int>&vs_)
	{
		used_[v_] = true;
		for (int nxt : G_[v_])
		{
			if (!used_[nxt])dfs(nxt, used_, G_, vs_);
		}
		vs_.push_back(v_);
	}

	void rdfs(int v_, int k_, vector<bool>&used_, vector<vector<int>>&rG_, vector<int>&top)
	{
		used_[v_] = true;
		top[v_] = k_;
		for (int nxt : rG_[v_])
		{
			if (!used_[nxt])rdfs(nxt, k_, used_, rG_, top);
		}
	}
}

//頂点数n_のグラフG_の強連結成分分解をする
//topに強連結成分のトポロジカル順序が格納される
//(top[i]==top[j]のとき、iとjは強連結である。)
//戻り値:強連結成分の個数
int scc(vector<int>G_[], int n_, vector<int>&top)
{
	using namespace scc_space;
	top.resize(n_);
	vector<vector<int>>rG_(n_);
	for (int i = 0; i < n_; ++i)
	{
		for (int to : G_[i])
		{
			rG_[to].push_back(i);
		}
	}
	vector<bool>used(n_, false);
	vector<int>vs;
	for (int v = 0; v < n_; ++v)
	{
		if (!used[v])dfs(v, used, G_, vs);
	}
	fill(used.begin(), used.end(), false);
	int k = 0;
	for (int i = vs.size() - 1; i >= 0; --i)
	{
		if (!used[vs[i]])rdfs(vs[i], k++, used, rG_, top);
	}
	return k;
}

vector<int>graph[114514];

//k番目にいて、それは[a,b)である。
void recurs(vector<int>&vec, int l, int r, int k, int a, int b)
{
	if (r <= a || b <= l)return;
	if (l <= a && b <= r)
	{
		vec.push_back(k);
		return;
	}
	int c = (a + b) / 2;
	recurs(vec, l, r, k * 2 + 2, a, c);
	recurs(vec, l, r, k * 2 + 1, c, b);
}

int main(void)
{
	int n;
	cin >> n;
	vector<pair<int, int>>vec;
	vector<pair<int, int>>raw;
	for (int i = 0; i < n; ++i)
	{
		int x, y;
		cin >> x >> y;
		vec.push_back({ x,i });
		vec.push_back({ y,i });
		raw.push_back({ x,y });
	}
	sort(vec.begin(), vec.end());
	int w = 1;
	while (vec.size() > w)w *= 2;
	int vnum = w * 3 - 1;
	int hi = 1e9 + 7, lo = 0;
	while (lo + 1 < hi)
	{
		fill(graph, graph + vnum, vector<int>());
		int mid = (lo + hi) / 2;
		//ツリーの辺を構築
		for (int i = 0; i < w - 1; ++i)
		{
			graph[vnum - 1 - i].push_back(vnum - 1 - (2 * i + 1));
			graph[vnum - 1 - i].push_back(vnum - 1 - (2 * i + 2));
		}
		//旗ペア同士の頂点を連結する
		for (int i = 0; i < n; ++i)
		{
			int one = lower_bound(vec.begin(), vec.end(), make_pair(raw[i].first, i)) - vec.begin();
			int two = lower_bound(vec.begin(), vec.end(), make_pair(raw[i].second, i)) - vec.begin();
			//!one->two    !two->one
			graph[one + w].push_back(two);
			graph[two + w].push_back(one);
		}
		for (int i = 0; i < vec.size(); ++i)
		{
			int lef = upper_bound(vec.begin(), vec.end(), make_pair(vec[i].first - mid, INT_MAX)) - vec.begin();
			int rht = lower_bound(vec.begin(), vec.end(), make_pair(vec[i].first + mid, 0)) - vec.begin();
			//区間[lef~i)[i+1~rht)にb_iから辺を張る
			{
				vector<int>seg;
				recurs(seg, lef, i, 0, 0, w);
				for (int s : seg)
				{
					graph[i].push_back(vnum - 1 - s);
				}
			}
			{
				vector<int>seg;
				recurs(seg, i + 1, rht, 0, 0, w);
				for (int s : seg)
				{
					graph[i].push_back(vnum - 1 - s);
				}
			}
		}
		vector<int>top;
		scc(graph, vnum, top);
		bool yes = true;
		for (int i = 0; i < n; ++i)
		{
			if (top[i] == top[i + w])
			{
				yes = false;
				break;
			}
		}
		if (yes)
		{
			lo = mid;
		}
		else
		{
			hi = mid;
		}
	}
	cout << lo << endl;
	return 0;
}


Measured memory_bytes: 23416