#include <algorithm>
#include <iostream>
#include <cassert>
#include <cstring>
#include <utility>
#include <cstdio>
#include <cctype>
#include <vector>
using namespace std;

const int ALL=1e9+5;
const int MAXN=2e4+5;
const int MAXM=1e5+5;
vector<int> v[MAXM];

inline int read()
{
	int x=0;char ch=getchar();
	while(!isdigit(ch)) ch=getchar();
	while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();}
	return x;
}

inline void Min(int &x,int y)
{
	if(x>y) x=y;
}

int n,tot,another[MAXN],cnt[MAXN];
pair<int,int> dat[MAXN],rev[MAXN];

inline void prepare()
{
	sort(cnt+1,cnt+tot+1);
	sort(dat+1,dat+tot+1);
	for(int i=1;i<=tot;i++)
	{
		int id=dat[i].second;
		if(!rev[id].first)
			rev[id].first=i;
		else
			rev[id].second=i,
			another[i]=rev[id].first,
			another[rev[id].first]=i;
	}
}

namespace Segment_Tree
{
	int ls[MAXM],rs[MAXM],in[MAXM],out[MAXM],root,tree_cnt,to;
	
	void build(int l,int r,int &cur)
	{
		cur=++tree_cnt;
		if(l==r) return out[l]=cur,void();
		int mid=(l+r)>>1;
		build(l,mid,ls[cur]);
		build(mid+1,r,rs[cur]);
		v[cur].push_back(ls[cur]);
		v[cur].push_back(rs[cur]);
	}
	
	void modify(int l,int r,int ql,int qr,int cur)
	{
		if(ql<=l&&qr>=r)
			return v[to].push_back(cur);
		int mid=(l+r)>>1;
		if(ql<=mid) modify(l,mid,ql,qr,ls[cur]);
		if(qr>mid) modify(mid+1,r,ql,qr,rs[cur]);
	}
	
	inline void clear()
	{
		for(int i=1;i<=tree_cnt;i++)
			v[i].clear();
		tree_cnt=0;
	}
	
	inline void rebuild()
	{
		clear();
		for(int i=1;i<=tot;i++)
			in[i]=++tree_cnt;
		build(1,tot,root);
		for(int i=1;i<=tot;i++)
			v[out[i]].push_back(in[another[i]]);
	}
	
	inline void add(int cur,int l,int r)
	{
		to=cur; if(l>r) return;
		modify(1,tot,max(0,l),min(r,tot),root);
	}
	
	inline void add_edge(int mid)
	{
		for(int i=1;i<=tot;i++)
		{
			int pos=dat[i].first;
			int l=lower_bound(cnt+1,cnt+tot+1,pos-mid+1)-cnt;
			int r=upper_bound(cnt+1,cnt+tot+1,pos+mid-1)-cnt-1;
			add(in[i],l,i-1);
			add(in[i],i+1,r);
		}
	}
}

using Segment_Tree::in;
using Segment_Tree::out;
using Segment_Tree::tree_cnt;

namespace Tarjan
{
	int st[MAXM],top;
	int co[MAXM],co_cnt;
	int dfn[MAXM],low[MAXM],dfn_cnt;
	
	void tarjan(int x)
	{
		st[++top]=x;
		dfn[x]=low[x]=++dfn_cnt;
		for(auto y:v[x])
		{
			if(!dfn[y])
			{
				tarjan(y);
				Min(low[x],low[y]);
			}
			else if(!co[y])
				Min(low[x],dfn[y]);
		}
		if(dfn[x]==low[x])
		{
			++co_cnt;
			while(st[top]!=x)
				co[st[top--]]=co_cnt;
			co[st[top--]]=co_cnt;
		}
	}
	
	inline void clear()
	{
		top=co_cnt=dfn_cnt=0;
		memset(co,0,sizeof(co));
		memset(dfn,0,sizeof(dfn));
	}
	
	inline void tarjan()
	{
		clear();
		for(int i=1;i<=tree_cnt;i++)
			if(!dfn[i])
				tarjan(i);
	}
	
	inline bool check()
	{
		for(int i=1;i<=n;i++)
		{
			int x1=rev[i].first;
			int x2=rev[i].second;
			if(co[in[x1]]==co[out[x1]])
				return false;
			if(co[in[x2]]==co[out[x2]])
				return false;
		}
		return true;
	}
}

inline bool check(int mid)
{
	Segment_Tree::rebuild();
	Segment_Tree::add_edge(mid);
	Tarjan::tarjan();
	return Tarjan::check();
}

int main()
{
	n=read();
	for(int i=1;i<=n;i++)
	{
		int x=read(),y=read();
		cnt[++tot]=x,cnt[++tot]=y;
		dat[tot-1]=make_pair(x,i);
		dat[tot]=make_pair(y,i);
	}
	prepare();
	int l=0,r=ALL,ans=0;
	while(l<=r)
	{
		int mid=(l+r)>>1;
		if(!check(mid)) r=mid-1;
		else l=mid+1,ans=mid;
	}
	printf("%d\n",ans);
	return 0;
}

Measured memory_bytes: 18364