#pragma GCC optimize(2)
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <cassert>
#include <cctype>
#include <climits>
#include <ctime>
#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
#include <stack>
#include <queue>
#include <deque>
#include <map>
#include <set>
#include <bitset>
#include <list>
#include <functional>
typedef long long LL;
typedef unsigned long long ULL;
using std::cin;
using std::cout;
using std::endl;
typedef int INT_PUT;
INT_PUT readIn()
{
	INT_PUT a = 0; bool positive = true;
	char ch = getchar();
	while (!(ch == '-' || std::isdigit(ch))) ch = getchar();
	if (ch == '-') { positive = false; ch = getchar(); }
	while (std::isdigit(ch)) { a = a * 10 - (ch - '0'); ch = getchar(); }
	return positive ? -a : a;
}
void printOut(INT_PUT x)
{
	char buffer[20]; int length = 0;
	if (x < 0) putchar('-'); else x = -x;
	do buffer[length++] = -(x % 10) + '0'; while (x /= 10);
	do putchar(buffer[--length]); while (length);
}

const int maxn = int(1e4) + 5;
int n;
struct Point
{
	int x, y;
	void read()
	{
		x = readIn();
		y = readIn();
	}
	bool operator<(const Point& b) const
	{
		return x < b.x;
	}
} points[maxn];
int idx[maxn];
bool comp(const int& x, const int& y)
{
	return points[x].y < points[y].y;
}

std::vector<std::vector<int> > G;
int buildx(int l, int r)
{
	if (l == r)
		return idx[l]; // x 按 y 排序
	int mid = (l + r) >> 1;
	int node = mid + (n << 1);
	G[node].push_back(buildx(l, mid));
	G[node].push_back(buildx(mid + 1, r));
	return node;
}
int buildy(int l, int r)
{
	if (l == r)
		return l + n; // y 按 x 排序
	int mid = (l + r) >> 1;
	int node = mid + n * 3 - 1;
	G[node].push_back(buildy(l, mid));
	G[node].push_back(buildy(mid + 1, r));
	return node;
}
int g_Pos, g_L, g_R;
void linkx(int l, int r)
{
	int mid = (l + r) >> 1;
	if (g_L <= l && r <= g_R)
	{
		if (l == r) G[g_Pos].push_back(idx[l]);
		else G[g_Pos].push_back(mid + (n << 1));
		return;
	}
	if (g_L <= mid) linkx(l, mid);
	if (g_R > mid) linkx(mid + 1, r);
}
void linky(int l, int r)
{
	int mid = (l + r) >> 1;
	if (g_L <= l && r <= g_R)
	{
		if (l == r) G[g_Pos].push_back(l + n);
		else G[g_Pos].push_back(mid + n * 3 - 1);
		return;
	}
	if (g_L <= mid) linky(l, mid);
	if (g_R > mid) linky(mid + 1, r);
}
void linkx(int from, int l, int r)
{
	if (l > r) return;
	g_Pos = from;
	g_L = l;
	g_R = r;
	linkx(1, n);
}
void linky(int from, int l, int r)
{
	if (l > r) return;
	g_Pos = from;
	g_L = l;
	g_R = r;
	linky(1, n);
}

int stamp;
int N;
bool inStack[maxn * 4];
int stack[maxn * 4];
int dfn[maxn * 4];
int low[maxn * 4];
int belong[maxn * 4];
void Tarjan(int node)
{
	dfn[node] = low[node] = ++stamp;
	stack[++stack[0]] = node;
	inStack[node] = true;

	for (int i = 0; i < G[node].size(); i++)
	{
		int to = G[node][i];
		if (!dfn[to])
		{
			Tarjan(to);
			low[node] = std::min(low[node], low[to]);
		}
		else if (inStack[to])
			low[node] = std::min(low[node], dfn[to]);
	}
	if (dfn[node] == low[node])
	{
		N++;
		int top;
		do
		{
			top = stack[stack[0]--];
			belong[top] = N;
			inStack[top] = false;
		} while (top != node);
	}
}
bool check(int s)
{
	G.clear();
	G.resize(n << 2); // 4n - 2 个点
	buildx(1, n);
	buildy(1, n);

	int l = 1, r = 0;
	for (int i = 1; i <= n; i++) // 选了 x 后，某些不能选 x，等价于这些必须选 y
	{
		while (l <= n && points[i].x - points[l].x >= s) l++;
		while (r < n && points[r + 1].x - points[i].x < s) r++;
		linky(i, l, i - 1); // y 按 x 排序的顺序
		linky(i, i + 1, r);
	}
	l = 1; r = 0;
	for (int i = 1; i <= n; i++) // 选了 x 后，某些不能选 y，等价于这些必须选 x
	{
		while (l <= n && points[i].x - points[idx[l]].y >= s) l++;
		while (r < n && points[idx[r + 1]].y - points[i].x < s) r++;
		linkx(i, l, r); // x 按 y 排序的顺序
	}
	l = 1; r = 0;
	for (int i = 1; i <= n; i++) // 选了 y 后，某些不能选 x，等价于这些必须选 y
	{
		while (l <= n && points[idx[i]].y - points[l].x >= s) l++;
		while (r < n && points[r + 1].x - points[idx[i]].y < s) r++;
		linky(idx[i] + n, l, r); // x 按 y 排序的顺序
	}
	l = 1; r = 0;
	for (int i = 1; i <= n; i++) // 选了 y 后，某些不能选 y，等价于这些必须选 x
	{
		while (l <= n && points[idx[i]].y - points[idx[l]].y >= s) l++;
		while (r < n && points[idx[r + 1]].y - points[idx[i]].y < s) r++;
		linkx(idx[i] + n, l, i - 1); // x 按 y 排序的顺序
		linkx(idx[i] + n, i + 1, r);
	}

	stamp = 0;
	stack[0] = 0;
	N = 0;
	memset(dfn, 0, sizeof(dfn));
	memset(low, 0, sizeof(low));
	for (int i = 1, to = 4 * n - 2; i <= to; i++)
		if (!dfn[i])
			Tarjan(i);

	for (int i = 1; i <= n; i++)
		if (belong[i] == belong[i + n])
			return false;
	return true;
}

void run()
{
	n = readIn();
	for (int i = 1; i <= n; i++)
		points[i].read();
	std::sort(points + 1, points + 1 + n);
	for (int i = 1; i <= n; i++)
		idx[i] = i;
	std::sort(idx + 1, idx + 1 + n, comp);

	int l = 0, r = std::max(points[n].x, points[idx[n]].y) - std::min(points[1].x, points[idx[1]].y) + 1;
	while (r - l > 1)
	{
		int mid = l + ((r - l) >> 1);
		if (check(mid))
			l = mid;
		else
			r = mid;
	}
	printOut(l);
}

int main()
{
	run();
	return 0;
}

Measured memory_bytes: 9500