#include<bits/stdc++.h>
using namespace std;

typedef vector<int> vec;
typedef vector<vec> mat;
int maxm=0,mini=1e9;

int s[2000][2000];
int t[2000][2000];

bool check(const mat &A,int M){
  int H=A.size();
  int W=A[0].size();
  memset(s,0,sizeof(s));
  memset(t,0,sizeof(t));
  
  for(int i=0;i<H;i++){
    for(int j=0;j<W;j++){
      if( abs(mini-A[i][j]) > M ){
        s[i][j]=1;
      }
      if( abs(maxm-A[i][j]) > M ){
        t[i][j]=1;
      }
    }
  }
  
  for(int i=0;i<H;i++){
    for(int j=0;j<W;j++){
      if(i+1<H)t[i+1][j]|=t[i][j];
      if(j+1<W)t[i][j+1]|=t[i][j];
    }
  }

  for(int i=H-1;i>=0;i--){
    for(int j=W-1;j>=0;j--){
      if(i-1>=0)s[i-1][j]|=s[i][j];
      if(j-1>=0)s[i][j-1]|=s[i][j];
    }
  }

  for(int i=0;i<H;i++)
    for(int j=0;j<W;j++)
      if(s[i][j]&&t[i][j])return false;

  return true;
}

int solve(const mat &A){
  int left=0,right=1e9,mid;
  while(left<right){
    mid=(left+right)/2;
    if(check(A,mid))right=mid;
    else left=mid+1;
  }
  return left;
}

void f1(mat &A){
  int H=A.size();
  int W=A[0].size();
  mat res(W , vec(H,0) );
  for(int i=0;i<H;i++){
    for(int j=0;j<W;j++){
      res[W-1-j][H-1-i]=A[i][j];
    }
  }
  A=res;
}

void f2(mat &A){
  int H=A.size();
  int W=A[0].size();
  for(int i=0;i<H;i++){
    for(int j=0;j<W/2;j++){
      swap(A[i][j],A[i][W-1-j]);
    }
  }
}

int main(){
  int H,W;
  scanf("%d %d",&H,&W);
  
  mat A( H, vec(W,0) );
  
  for(int i=0;i<H;i++){
    for(int j=0;j<W;j++){
      scanf("%d",&A[i][j]);
      maxm=max(maxm,A[i][j]);
      mini=min(mini,A[i][j]);
    }
  }
  
  int ans=1e9;
  for(int i=0;i<2;i++){
    for(int j=0;j<2;j++){
      ans=min(ans,solve(A));
      if(j==0)f1(A);
    }
    if(i==0)f2(A);
  }

  printf("%d\n",ans);
  return 0;
}