#include <bits/stdc++.h>
using namespace std;
int n, m;
int arr[1000][1000];
bool works(int k) {
  vector<bitset<1000> > myVec(n);
  for (int i = 0; i < n; i++) {
    for (int j = 0; j < m; j++) {
      myVec[i][j] = (arr[i][j] >= k);
    }
  }
  bool dp[m][m];
  for (int i = 0; i < m; i++) {
    for (int j = 0; j < m; j++) {
      dp[i][j] = false;
    }
  }
  for (int i = 0; i < n; i++) {
    vector<int> temp;
    for (int j = 0; j < m; j++) {
      if (myVec[i][j]) temp.emplace_back(j);
    }
    for (int j = 0; j < temp.size(); j++) {
      for (int k = j + 1; k < temp.size(); k++) {
        if (dp[temp[j]][temp[k]]) return true;
        dp[temp[j]][temp[k]] = true;
      }
    }
  }
  return false;
}
int main() {
  ios_base::sync_with_stdio(false);
  cin.tie(NULL);
  cin >> n >> m;
  int minval = INT_MAX;
  int maxval = INT_MIN;
  set<int> mySet;
  for (int i = 0; i < n; i++) {
    for (int j = 0; j < m; j++) {
      cin >> arr[i][j];
      mySet.insert(arr[i][j]);
    }
  }
  vector<int> newVec;
  for (auto it : mySet) newVec.emplace_back(it);
  int bmin = 0;
  int bmax = newVec.size() - 1;
  while (bmin < bmax) {
    int bmid = (bmin + bmax) / 2;
    if ((bmax - bmin) % 2 == 1) bmid++;
    if (works(newVec[bmid])) {
      bmin = bmid;
    } else {
      bmax = bmid - 1;
    }
  }
  cout << newVec[bmin] << endl;
}
