// Original C++ solution (slower):
//周♂雨扬是最强的！！！

//大佬祝您AK

//沈哲♂贝是最强的！！！

/*#include<iostream>

#include<algorithm>

#include<cmath>

#include<cstring>

#include<fstream>

using namespace std;

int n,m;

int a[403][403];

int point[403],vis[403],tong[403];

inline bool pd(int x){

	while(1){

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

			int j=point[i];

			while(j<=m){

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

					j++;

				}else{

					point[i]=j;

					tong[a[i][j]]++;

					break;

				}

			}

			if(j==m+1){

				return 0;

			}

		}

		bool yes=false;

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

			if(tong[i]>x){

				yes=true;

				vis[i]=1;

			}

			tong[i]=0;

		}

		if(yes==false){

			return 1;

		}

	}

	return 1;

}

int main(){

	cin>>n>>m;

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

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

			cin>>a[i][j];

		}

	}

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

		vis[i]=0;

	}

	int ans=m;

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

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

			tong[i]=0;

		}

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

			int j=point[i];

			while(j<=m){

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

					j++;

				}else{

					point[i]=j;

					tong[a[i][j]]++;

					break;

				}

			}

			if(j>=m+1){

				break;

			}

		}

		int nowans=0,now;

		bool yes=false;

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

			if(tong[i]>nowans&&!vis[i]){

				now=i;

				nowans=tong[i];

			}

		}

		cout<<nowans<<endl;

		vis[now]=1;

		ans=min(ans,nowans);

	}

	cout<<ans<<endl;

	int l=1,r=m;

	while(l<r){

		int mid=(l+r)/2;

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

			point[i]=1;

		}

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

			vis[i]=0;

		}

		if(pd(mid)){

			r=mid;

		}else{

			l=mid+1;

		}

	}

	bool yes=false;

	if(pd(r)){

		yes=true;

		cout<<r<<endl;

	}else{

		yes=true;

		cout<<l<<endl;

	}

	if(yes==false){

		cout<<m<<endl;

	}

	return 0;

}



in:

4 5

5 1 3 4 2

2 5 3 1 4

2 3 1 4 5

2 5 4 3 1

out:

2



in:

3 3

2 1 3

2 1 3

2 1 3

out:

3



*/

//沈♂哲贝是最强的！！！

//大佬祝您AK

//周♂雨扬是最强的！！！

#include<string.h>

#include<iostream>

#include<math.h>

#include<algorithm>

using namespace std;

int a[303][303],point[303],tong[303];

int n,m,ans;

bool vis[303],yes;

int main(){

	cin>>n>>m;

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

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

			cin>>a[i][j];

		}

	}

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

		point[i]=1;

		tong[a[i][1]]++;

	}

	yes=1,ans=1e9;

	while(yes){

		int k=0;

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

			if(tong[i]>tong[k]){

				k=i;

			}

		}

		ans=min(ans,tong[k]);

		vis[k]=1;

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

			while(vis[a[i][point[i]]]){

				tong[a[i][point[i]]]--;

				point[i]++;

				tong[a[i][point[i]]]++;

			}

			if(point[i]!=m+1){

				yes&=true;

			}else{

				yes&=false;

			}

		}

	}

	cout<<ans<<endl;

	return 0;

}

/*



in:

4 5

5 1 3 4 2

2 5 3 1 4

2 3 1 4 5

2 5 4 3 1

out:

2



in:

3 3

2 1 3

2 1 3

2 1 3

out:

3



*/

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

#include<algorithm>

#include<cstring>

using namespace std;

const int inf=1e8,maxn=305;

inline int read(){int x=0,f=1; char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-') f=-1; ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f;}

int n,m,ans,cnt[maxn],a[maxn][maxn];

bool cho[maxn];

inline void init(){

	n=read(); m=read();

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

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

			a[i][j]=read();

		}

	}

	ans=inf;

	memset(cho,1,sizeof(cho));

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

		memset(cnt,0,sizeof(cnt));

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

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

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

					cnt[a[i][j]]++;

					break;

				}

			}

		}

		int mx=0;

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

			if ((!mx)||(mx&&cnt[mx]<cnt[i])){

				mx=i;

			}

		}

		cho[mx]=0;

		ans=min(cnt[mx],ans);

	}

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

}

int main(){

	init();

	return 0;

}

// Fastest known solution for this problem: