#include <bits/stdc++.h>
using std::bitset;
using std::cin;
using std::cout;
using std::deque;
using std::endl;
using std::getline;
using std::greater;
using std::lower_bound;
using std::make_pair;
using std::map;
using std::max;
using std::min;
using std::multimap;
using std::pair;
using std::priority_queue;
using std::queue;
using std::random_shuffle;
using std::set;
using std::sort;
using std::stack;
using std::string;
using std::stringstream;
using std::swap;
using std::unique;
using std::vector;
const int MAXN(200010);
const int MAXM(50010);
const int MAXE(100010);
const int MAXK(6);
const int HSIZE(131313);
const int SIGMA_SIZE(52);
const int MAXH(19);
const int INFI((INT_MAX - 1) >> 1);
const unsigned long long BASE(31);
const long long LIM(10000000);
const int INV(-10000);
const int MOD(1000000007);
const double EPS(1e-7);
template <typename T>
void checkmax(T &a, T b) {
  if (b > a) a = b;
}
template <typename T>
void checkmin(T &a, T b) {
  if (b < a) a = b;
}
template <typename T>
T ABS(const T &a) {
  return a < 0 ? -a : a;
}
bool vis[1010][1010];
int mp[1010][1010];
int arr[1000010];
int count;
int N, M;
bool test(int value) {
  for (int i = 0; i < M; ++i)
    for (int j = 0; j < M; ++j) vis[i][j] = false;
  for (int i = 0; i < N; ++i) {
    count = 0;
    for (int j = 0; j < M; ++j)
      if (mp[i][j] >= value) arr[count++] = j;
    for (int j = 0; j < count; ++j)
      for (int k = j + 1; k < count; ++k) {
        if (vis[arr[j]][arr[k]]) return true;
        vis[arr[j]][arr[k]] = true;
      }
  }
  return false;
}
int main() {
  while (~scanf("%d%d", &N, &M)) {
    int l = INT_MAX, r = 0;
    for (int i = 0; i < N; ++i)
      for (int j = 0; j < M; ++j) {
        scanf("%d", mp[i] + j);
        checkmin(l, mp[i][j]);
        checkmax(r, mp[i][j]);
      }
    ++r;
    while (l < r) {
      int m = (l + r) >> 1;
      if (test(m))
        l = m + 1;
      else
        r = m;
    }
    --l;
    printf("%d\n", l);
  }
  return 0;
}
