#include <cstdio>
#include <algorithm>

using std::sort;

const int MAXN=10011;
const int MAXV=MAXN*10;
const int MAXE=MAXV*10;

int N;
int Val[2][MAXN];

struct Vert{
	int FE;
	int Bel;
	bool Vis;
} V[MAXV];

int Vcnt;
int Pos[2][MAXN];

struct Edge{
	int y, next;
	bool i;
} E[MAXE<<1];

int Ecnt;

void addE(int a, int b){
	//printf("%d %d\n", a, b);
	++Ecnt;
	E[Ecnt].y=b;E[Ecnt].next=V[a].FE;V[a].FE=Ecnt;
	E[Ecnt].i=false;
	++Ecnt;
	E[Ecnt].y=a;E[Ecnt].next=V[b].FE;V[b].FE=Ecnt;
	E[Ecnt].i=true;
}

int Dfn[MAXV], DFN;

void DFS(int at){
	V[at].Vis=true;
	for(int k=V[at].FE, to;k;k=E[k].next){
		if(E[k].i)	continue;
		to=E[k].y;
		if(V[to].Vis)	continue;
		DFS(to);
	}
	Dfn[++DFN]=at;
}

void DFS(int at, int b){
	V[at].Vis=true;
	for(int k=V[at].FE, to;k;k=E[k].next){
		if(!E[k].i)	continue;
		to=E[k].y;
		if(V[to].Vis)	continue;
		DFS(to, b);
	}
	V[at].Bel=b;
}

int Bcnt;

void SCC(){
	#define n Vcnt
	DFN=0;Bcnt=0;
	for(int i=1;i<=n;++i)	V[i].Vis=false;
	for(int i=1;i<=n;++i)	if(!V[i].Vis)	DFS(i);
	for(int i=1;i<=n;++i)	V[i].Vis=false;
	for(int i=n;i>=1;--i)	if(!V[Dfn[i]].Vis)	DFS(Dfn[i], ++Bcnt);
	#undef n
}

bool Test(){
	bool ret=true;
	for(int i=1;i<=N;++i)	ret&=(V[Pos[0][i]].Bel!=V[Pos[1][i]].Bel);
	return ret;
}

struct Pair{
	int p, v;
	Pair(){}
	Pair(int _p, int _v){p=_p;v=_v;}
};

inline bool operator < (const Pair &A, const Pair &B){
	return (A.v==B.v)?(A.p<B.p):A.v<B.v;
}

struct Node{
	int l, r;
	int pos;
};

struct Tree{
	Pair Pa[MAXN];
	Node T[MAXN<<2];
	void Build(int at, int l, int r){
		T[at].l=l;T[at].r=r;T[at].pos=++Vcnt;
		int m=(l+r)>>1;
		if(l==r){
			addE(T[at].pos, Pa[m].p);
			return;
		}
		Build(at<<1, l, m);
		addE(T[at].pos, T[at<<1].pos);
		Build((at<<1)|1, m+1, r);
		addE(T[at].pos, T[(at<<1)|1].pos);
	}
	int Pos;
	int L, R;
	int Findl(Pair v){
		if(!(v<Pa[N]))	return N+1;
		int l=1, r=N, m;
		while(l<r){
			m=(l+r)>>1;
			if(v<Pa[m])	r=m;
			else	l=m+1;
		}
		m=(l+r)>>1;
		return m;
	}
	int Findr(Pair v){
		if(!(Pa[1]<v))	return 0;
		int l=1, r=N, m;
		while(l<r){
			m=(l+r)>>1;
			if(Pa[m+1]<v)	l=m+1;
			else	r=m;
		}
		m=(l+r)>>1;
		return m;
	}
	bool Get(Pair vl, Pair vr){
		L=Findl(vl);
		R=Findr(vr);
		return L<=R;
	}
	void Link(int at){
		if(T[at].l>=L && T[at].r<=R){
			addE(Pos, T[at].pos);
			return;
		}
		int m=(T[at].l+T[at].r)>>1;
		if(L<=m)	Link(at<<1);
		if(R>m)	Link((at<<1)|1);
	}
} Tr[2];

void Clear(){
	for(int i=1;i<=Vcnt;++i)	V[i].FE=0;
	Vcnt=0;Ecnt=0;
	
}

bool Try(int k){
	
	Clear();
	
	for(int i=1;i<=N;++i){
		Pos[0][i]=++Vcnt;
		Pos[1][i]=++Vcnt;
	}
	
	for(int i=0;i<2;++i){
		for(int j=1;j<=N;++j){
			Tr[i].Pa[j]=Pair(Pos[!i][j], Val[i][j]);
		}
		sort(Tr[i].Pa+1, Tr[i].Pa+N+1);
		Tr[i].Build(1, 1, N);
	}
	
	for(int i=0;i<2;++i){
		for(int j=1;j<=N;++j){
			if(Tr[!i].Get(Pair(Vcnt+1, Val[i][j]-k), Pair(0, Val[i][j]+k))){
				Tr[!i].Pos=Pos[i][j];
				Tr[!i].Link(1);
			}
			if(Tr[i].Get(Pair(Vcnt+1, Val[i][j]-k), Pair(Pos[!i][j], Val[i][j]))){
				Tr[i].Pos=Pos[i][j];
				Tr[i].Link(1);
			}
			if(Tr[i].Get(Pair(Pos[!i][j], Val[i][j]), Pair(0, Val[i][j]+k))){
				Tr[i].Pos=Pos[i][j];
				Tr[i].Link(1);
			}
		}
	}
	
	SCC();
	return Test();
	
}

int main(){
	
	scanf("%d", &N);
	for(int i=1;i<=N;++i){
		scanf("%d%d", &Val[0][i], &Val[1][i]);
	}
	
	int l=0, r=1000000000, m;
	while(l<r){
		m=(l+r)>>1;
		if(Try(m+1))	l=m+1;
		else	r=m;
	}
	m=(l+r)>>1;
	
	printf("%d\n", m);
	
	return 0;
}



Measured memory_bytes: 22656