#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

// Data structure to store value and its original sequence index
struct Element {
    int val;
    int id;

    // Comparison function to sort in ascending order of value
    bool operator<(const Element& other) const {
        return val < other.val;
    }
};

int main() {
    // Optimize I/O in C++
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);

    int n, m;
    if (!(cin >> n >> m)) return 0;

    vector<Element> a;
    a.reserve(n * m);

    // Read input data
    for (int i = 1; i <= n; ++i) {
        for (int j = 1; j <= m; ++j) {
            int v;
            cin >> v;
            a.push_back({v, i});
        }
    }

    // Step 1: Sort all elements in ascending order by value
    sort(a.begin(), a.end());

    // Step 2: Two Pointers Technique (Sliding Window)
    vector<int> freq(n + 1, 0);
    int unique_count = 0;
    int ans = 2e9 + 7; // Initialize answer with a very large value
    int total_elements = n * m;

    int L = 0;
    for (int R = 0; R < total_elements; ++R) {
        // Expand the window to the right (Pointer R)
        if (freq[a[R].id] == 0) {
            unique_count++;
        }
        freq[a[R].id]++;

        // Shrink the window from the left (Pointer L) when all N sequences are present
        while (unique_count == n) {
            ans = min(ans, a[R].val - a[L].val);

            freq[a[L].id]--;
            if (freq[a[L].id] == 0) {
                unique_count--;
            }
            L++; // Move left pointer
        }
    }

    // Step 3: Print result
    cout << ans << "\n";

    return 0;
}