#include <bits/stdc++.h>
using namespace std;
inline int Max(int a, int b) { return (((b - a) >> (32 - 1)) & (a ^ b)) ^ b; }
inline int Min(int a, int b) { return (((b - a) >> (32 - 1)) & (a ^ b)) ^ a; }
unsigned long long bit[1005][20];
vector<int> v;
int a[1005][1005];
int main() {
  int n, m;
  while (scanf("%d%d", &n, &m) != EOF) {
    v.clear();
    for (int i = (0); i <= (n - 1); i++) {
      for (int j = (0); j <= (m - 1); j++) {
        scanf("%d", a[i] + j);
        v.push_back(a[i][j]);
      }
    }
    sort(v.begin(), v.end());
    int sz = unique(v.begin(), v.end()) - v.begin();
    v.resize(sz);
    int l = 0, r = sz;
    while (l < r - 1) {
      int mid = (l + r) >> 1;
      int cnt = -1000000007;
      memset(bit, 0, sizeof(bit));
      for (int i = (0); i <= (n - 1); i++) {
        for (int j = (0); j <= (m - 1); j++) {
          if (a[i][j] >= v[mid]) {
            bit[i][j / 64] |= 1ull << (j % 64);
          }
        }
        for (int j = (0); j <= (i - 1); j++) {
          cnt = 0;
          for (int k = (0); k <= (18); k++) {
            cnt += __builtin_popcountll(bit[i][k] & bit[j][k]);
          }
          if (cnt >= 2) break;
        }
        if (cnt >= 2) break;
      }
      if (cnt >= 2)
        l = mid;
      else
        r = mid;
    }
    printf("%d\n", v[l]);
  }
  return 0;
}
