#include <bits/stdc++.h>
using namespace std;
template <class T>
void inline checkMax(T& a, T b) {
  if (a < b) {
    a = b;
  }
};
template <class T>
void inline checkMin(T& a, T b) {
  if (b < a) {
    a = b;
  }
};
int const kMaxn = 1024;
int maze[kMaxn][kMaxn];
int new_maze[kMaxn][kMaxn];
int next_value[kMaxn][kMaxn];
int cnt[kMaxn];
int n, m;
bool solve(int mid) {
  for (int n___LINE__ = (n), i = 0; i < n___LINE__; ++i)
    for (int n___LINE__ = (m), j = 0; j < n___LINE__; ++j) {
      if (maze[i][j] >= mid) {
        new_maze[i][j] = 1;
      } else {
        new_maze[i][j] = 0;
      }
    }
  for (int n___LINE__ = (n), i = 0; i < n___LINE__; ++i) {
    next_value[i][m - 1] = -1;
    for (int j = m - 2; j >= 0; --j) {
      if (new_maze[i][j + 1] == 1) {
        next_value[i][j] = j + 1;
      } else {
        next_value[i][j] = next_value[i][j + 1];
      }
    }
  }
  for (int j = 0; j < m - 1; ++j) {
    memset(cnt, 0, (sizeof cnt));
    for (int i = 0; i < n; ++i) {
      if (new_maze[i][j] == 0) {
        continue;
      }
      for (int jj = next_value[i][j]; jj != -1; jj = next_value[i][jj]) {
        cnt[jj]++;
        if (cnt[jj] == 2) {
          return true;
        }
      }
    }
  }
  return false;
}
int main() {
  while (scanf("%d%d", &n, &m) == 2) {
    for (int n___LINE__ = (n), i = 0; i < n___LINE__; ++i) {
      for (int n___LINE__ = (m), j = 0; j < n___LINE__; ++j) {
        scanf("%d", maze[i] + j);
      }
    }
    int mi = maze[0][0];
    int ma = maze[0][0];
    for (int n___LINE__ = (n), i = 0; i < n___LINE__; ++i)
      for (int n___LINE__ = (m), j = 0; j < n___LINE__; ++j) {
        checkMin(mi, maze[i][j]);
        checkMax(ma, maze[i][j]);
      }
    int lo = mi, hi = ma;
    while (lo != hi) {
      int mid = (lo + hi + 1) / 2;
      if (solve(mid)) {
        lo = mid;
      } else {
        hi = mid - 1;
      }
    }
    std::cout << lo << std::endl;
  }
  return 0;
}
