// Original C++ solution (slower):
#include <iostream>

#include <sstream>

#include <iomanip>

#include <cstdio>

#include <cstdlib>

#include <cmath>

#include <cctype>

#include <cstring>

#include <vector>

#include <list>

#include <queue>

#include <deque>

#include <stack>

#include <map>

#include <set>

#include <algorithm>

#include <iterator>

#include <bitset>

#include <ctime>

#include <complex>



using namespace std;



#define FOR(i,a,b) for (int i = (a); i < (b); i++)

#define RFOR(i,b,a) for (int i = (b)-1; i >= (a); i--)

#define ITER(it,a) for (__typeof(a.begin()) it = a.begin(); it != a.end(); it++)

#define FILL(a,value) memset(a, value, sizeof(a))



#define SZ(a) (int)a.size()

#define ALL(a) a.begin(), a.end()

#define PB push_back

#define MP make_pair



typedef long long LL;

typedef vector<int> VI;

typedef pair<int, int> PII;

//#define double float



const double PI = acos(-1.0);

const int INF = 1000 * 1000 * 1000 + 7;

const LL LINF = INF * (LL) INF;



const double EPS = 1e-6;

const int MAX = 300 + 47;

const int MIN = 50 + 7;

const int MOD = INF;





int A[MAX][MAX];

int U[MAX];

int F[MAX];



int main()

{

    int n, m;

    scanf("%d%d", &n, &m);

    FOR(i, 0, n)

        FOR(j, 0, m)

            scanf("%d", &A[i][j]), A[i][j]--;

    

    int ans = INF;

    FOR(it, 0, m)

    {

        FILL(F, 0);

        FOR(i, 0, n)

            FOR(j, 0, m)

            {

                int id = A[i][j];

                if (U[id])continue;

                F[id]++;

                break;

            }

        int idx = -1;

        FOR(i, 0, m)

                if (idx == -1 || F[i] > F[idx])

                    idx = i;

        ans = min(ans, F[idx]);

        U[idx] = 1;

    }

    

    cout << ans << endl;

    

    

}


// Optimized solution to the same problem (faster):
#include<cstdio>

#include<cstring>

#include<algorithm>

using namespace std;

typedef long long ll;



template<typename T>

void input(T &x) {

	x=0; T a=1;

	register char c=getchar();

	for(;c<48||c>57;c=getchar())

		if(c==45) a=-1;

	for(;c>=48&&c<=57;c=getchar())

		x=x*10+c-48;

	x*=a;

	return;

}



#define MAXN 1010

#define MAXM 1010



int n,m;

int a[MAXN][MAXM];

int sum[MAXM];



namespace solve30 { //O(n*m*2^m)

	

	bool chose[15];



	void main() {

		for(int i=1;i<=n;i++)

			for(int j=1;j<=m;j++)

				input(a[i][j]),a[i][j]--;

		int ans=2147483647;

		for(int s=1;s<1<<m;s++) {

			for(int i=0;i<m;i++)

				if(s&(1<<i)) chose[i]=true;

			for(int i=1;i<=n;i++)

				for(int j=1;j<=m;j++)

					if(chose[a[i][j]]) {

						sum[a[i][j]]++;

						break;

					}

			int Max=0;

			for(int i=0;i<m;i++) {

				Max=max(Max,sum[i]),

				sum[i]=0,chose[i]=false;

			}

			ans=min(ans,Max);

		}

		printf("%d\n",ans);

		return;

	}



}



namespace solve70 { // O(n*m*log n)

	

	int cnt[MAXN];

	bool not_chose[MAXM];



	bool Judge(int mid) {

		memset(not_chose,0,sizeof(not_chose));

		for(int i=1;i<=n;i++) cnt[i]=1;

		while(true) {

			memset(sum,0,sizeof(sum));

			bool flag=true;

			for(int i=1;i<=n;i++) {

				for(;cnt[i]<=m&&not_chose[a[i][cnt[i]]];cnt[i]++);

				if(cnt[i]>m) return false;

				if(++sum[a[i][cnt[i]]]>mid)

					not_chose[a[i][cnt[i]]]=true,flag=false;

			}

			if(flag) return true;

		}

		return false;

	}



	void main() {

		for(int i=1;i<=n;i++)

			for(int j=1;j<=m;j++)

				input(a[i][j]);

		int l=1,r=n,ans;

		while(l<=r) {

			int mid=l+r>>1;

			if(Judge(mid)) ans=mid,r=mid-1;

			else l=mid+1;

		}

		printf("%d\n",ans);

		return;

	}



}



int main() {

//	freopen("sports.in","r",stdin),

//	freopen("sports.out","w",stdout),

	input(n),input(m);

	if(n<=10&&m<=10) solve30::main();

	else solve70::main();

//	fclose(stdin),fclose(stdout);

	return 0;

}


// Fastest known solution for this problem: