给定一个二维整型矩阵,已知矩阵的每一行都按照从小到大的顺序排列,每一列也都按照从小到大的顺序排列。现在给出一个数,请写一个函数返回该数是否存在于矩阵中。
矩阵中出现的数字与需要查找的数(k)都为0~100000之间的整数,且矩阵的大小在3000*3000以内。
在保证正确性的基础上,请尽量给出比较高效的解法。请列出你的算法时间复杂度与空间复杂度分别是多少?
输入两个整数m,n, 且 0<m<=3000, 0<n<=3000。
接着输入一个vector<vector<int>> matrix矩阵,大小为m行n列,与一个int k,为需要查找的数字。
输出true或者false,true表示该数k存在于该matrix矩阵中,false表示该数k不存在于该matrix矩阵中。
3 3 2 3 5 3 4 7 3 5 8 4
true
4位于矩阵的第二行第二列,故输出true
/* 从左下(或右上)开始遍历, 相等则找到,小于则向右遍历,大于则向上遍历。 时间复杂度O(m+n),空间复杂度O(m*n) */ #include<bits/stdc++.h> using namespace std; int main() { // freopen("input.txt", "r", stdin); int m, n, x, i, j, k; cin >> m >> n; vector<vector<int>> matrix; for(i = 0; i < m; i++) { vector<int> temp; for(j = 0; j < n; j++) { cin >> x; temp.push_back(x); } matrix.push_back(temp); } cin >> k; i = m - 1; j = 0; bool flag = false; while(i >= 0 && j < n) { if(matrix[i][j] == k) { flag = true; break; } else if(matrix[i][j] < k) j++; else i--; } if(flag) cout << "true" << endl; else cout << "false" << endl; return 0; }
/* 以空间换时间 查找过程,时间复杂度O(1),空间复杂度O(N) */ #include<bits/stdc++.h> using namespace std; #define N 100001 bool a[N]; int main() { // freopen("input.txt", "r", stdin); int m, n, x, i, j, k; memset(a, 0, sizeof(a)); scanf("%d%d", &m, &n); for(i = 0; i < m * n; i++) { scanf("%d", &x); a[x] = true; } scanf("%d", &k); if(a[k]) printf("true\n"); else printf("false\n"); return 0; }
import java.io.BufferedReader; import java.io.InputStreamReader; import java.io.IOException; import java.lang.String; public class Main { public static void main(String[] args) throws IOException { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); String strMN; while((strMN = br.readLine()) != null) { String[] mn = strMN.split(" "); int m = Integer.parseInt(mn[0]); int n = Integer.parseInt(mn[1]); int[][] matrix = new int[m][n]; for(int i = 0; i < m; i++){ String[] strRow = br.readLine().trim().split(" "); for(int j = 0; j < n; j++) matrix[i][j] = Integer.parseInt(strRow[j]); } int target = Integer.parseInt(br.readLine().trim()); System.out.println(search(matrix, target)); } } private static boolean search(int[][] arr, int k) { int row = arr.length, col = arr[0].length; int rowStart = 0, colStart = col - 1; while(rowStart < row && colStart >= 0){ if(arr[rowStart][colStart] > k) { colStart --; }else if(arr[rowStart][colStart] < k){ rowStart ++; }else{ return true; } } return false; } }
size = input() m,n = size.split() m = int(m) mySet = set() for i in range(m): newLine = input() nums = newLine.split() for num in nums: mySet.add(num) target = input() print ("true") if target in mySet else print ("false")注意输出是 true 不是True,所以不能直接打印python的布尔值
代码为从左上角
import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); int row = scanner.nextInt(); int column = scanner.nextInt(); int[][] value = new int[row][column]; for (int i = 0; i < row; i++) { for (int j = 0; j < column; j++) { value[i][j] = scanner.nextInt(); } } int aim = scanner.nextInt(); int curR = 0; int curC = column - 1; boolean flag = false; while (curR >= 0 && curR < row && curC >= 0 && curC < column) { if (value[curR][curC] > aim) { curC--; } else if (value[curR][curC] < aim) { curR++; } else { flag = true; break; } } System.out.println(flag); } }
using System; using System.Collections.Generic; using System.Linq; using System.Text.RegularExpressions; //总结目前牛客问题 第一,没有循环输入问题, 第二 有循环输入问题, 第三 输入有多余空格问题 ,第四 中间插入多余空行问题 .... namespace Test0001 { class Program { public static void Main(string[] args) { //string line; //while (!string.IsNullOrEmpty(line = Console.ReadLine())) Func(line); Func(Console.ReadLine()); } public static void Func(string line) { var s1 = line.Trim().Split(' ').Select(x => int.Parse(x)).ToArray(); int n = s1[0], m = s1[1]; int[,] mir = new int[n, m]; for (int j = 0; j < m; j++) { var s2 = Console.ReadLine().Trim().Split(' ').Select(x => int.Parse(x)).ToArray(); for (int i = 0; i < n; i++) { mir[i, j] = s2[i]; } } int key = int.Parse(Console.ReadLine()); int s = 0, e = n - 1; while (s<e) { int mid = (s + e) / 2; int val = mir[mid, 0]; if (e - s == 1) break; if (val > key) { e = mid; } else if(val == key) { Console.WriteLine("true"); return; } else { s = mid; } } //起点 (s,0) Console.WriteLine(Find(s, 0, m, mir, key).ToString().ToLower()); } //比key 大 往左遍历, 比 key小 往下 遍历 public static bool Find(int x, int y, int m, int[,] mir, int key) { if (x < 0 || y >= m) return false; if (mir[x, y] > key) { return Find(x - 1, y, m, mir, key); } else if( mir[x,y] == key) { return true; } else { return Find(x, y + 1, m, mir, key); } } } }根据矩阵的特殊性,从右上或者左下开始遍历寻找皆可,我这里是使用右上角开始,首先二分法快速找到起点之后 用找到的数和Key值比较 如果大了x-- 如果小了 y++ 直到找到为止,最坏情况 m+n次
提供一个Java的合理输入import java.util.Scanner;
public static void main(String[] args) { Scanner scanner = new Scanner(System.in); int m = scanner.nextInt(); int n = scanner.nextInt(); int[][] array = new int[m][n]; for (int i = 0; i < m; i++) { for (int j = 0; j < n ; j++) { array[i][j] = scanner.nextInt(); } } int findNum = scanner.nextInt(); System.out.println(find(array, m / 2, n / 2, findNum)); } private static boolean find(int[][] array, int lm, int cm, int findNum) { int i = array[lm][cm]; if (i == findNum) { return true; } if (i < findNum && lm + 1 < array.length) { if (find(array, lm + 1, cm, findNum)) { return true; } } if (i < findNum && cm + 1 < array[0].length) { if (find(array, lm, cm + 1, findNum)) { return true; } } if (i > findNum && lm - 1 > 0) { if (find(array, lm - 1, cm, findNum)) { return true; } } if (i > findNum && cm - 1 > 0) { if (find(array, lm, cm - 1, findNum)) { return true; } } return false; }
class MainActivity: def main(self): # Read the data m, n = map(int, filter(lambda x: len(x) > 0, input().split(' '))) mat = [[0] * n for _ in range(m)] for rowPtr in range(m): dat = list(filter(lambda x: len(x) > 0, input().split(' '))) dat[0] = dat[0].replace('\u200b', '') dat = map(int, dat) for ptr, num in enumerate(dat): mat[rowPtr][ptr] = num k = int(input()) # Initialization rowPtr = 0 colPtr = n - 1 # Traverse while rowPtr < m and colPtr > -1: if mat[rowPtr][colPtr] == k: print('true') return if mat[rowPtr][colPtr] > k: colPtr -= 1 else: rowPtr += 1 print('false') if __name__ == '__main__': M = MainActivity() M.main()
#include <cstdio> #include <vector> using namespace std; int main() { int m, n, target; scanf("%d%d", &m, &n); vector<vector<int> > matrix(m, vector<int>(n)); for (int i = 0; i < m; ++i) for (int j = 0; j < n; ++j) scanf("%d", &matrix[i][j]); scanf("%d", &target); int px = 0, py = m-1; bool found = false; while (px < n && py > 0 && !found) { if (matrix[py][px] == target) found = true; else if (matrix[py][px] < target) px++; else py--; } printf("%s\n", found?"true":"false"); return 0; }
#include<iostream> #include<vector> using namespace std; int main() { int n,m,k; cin>>m>>n; vector<vector<int>> arr(m,vector<int>(n)); for(int i=0;i<m;i++) for(int j=0;j<n;j++) cin>>arr[i][j]; cin>>k; int i=m-1; int j=0; while(i>=0&&j<n) { if(arr[i][j]>k) i--; else if(arr[i][j]<k) j++; else if(arr[i][j]==k) { cout<<"true"; return 0; } } cout<<"false"; return 0; }
这什么输入输出啊,非常不适应啊....
# -*- coding:utf-8 -8- import sys def main(): lines = sys.stdin.readlines() num=lines[-1].strip() for line in lines[1:-1]: tmp = line.strip().split() if num in tmp:return 'true' return 'false' if __name__=='__main__': print(main())
A了80%,但是不知道问题在哪里。
说一下思路吧,首先使用二分法找到比target大的最小值和比target小的最大值,那么target的范围就在这几行元素之中了,然后遍历这几行,使用二分法查找target,找到就返回true,如果遍历完仍然没有找到target,就返回false。
import java.util.*; public class Main { public boolean is_in_matrix(){ Scanner sc = new Scanner(System.in); String[] s = sc.nextLine().split(" "); int n = Integer.parseInt(s[0]); int m = Integer.parseInt(s[1]); if(n==0) return false; ArrayList<int[]> arr = new ArrayList<>(); for(int i = 0; i<n;i++){ String string = sc.nextLine(); string = string.trim(); String[] chars = string.split(" "); int [] mat = new int[m]; for(int j = 0; j<m;j++){ mat[j] = Integer.parseInt(chars[j]); } arr.add(mat); } int target = sc.nextInt(); int []row_elm = new int[n]; for(int i = 0;i<n;i++){ row_elm[i] = arr.get(i)[0]; } //scan存储比target小的最大值行和比target大的最小值行 int[] scan = find_target(row_elm, target); return find_targetnum(arr,scan,target); } //使用二分查找搜索target private boolean find_targetnum(ArrayList<int[]> arr,int [] scan, int target) { //遍历scan中的几行元素,查看target是否在其中 for(int i = scan[0];i<=scan[1];i++){ int[] arrs = arr.get(i); int low = 0,high = arrs.length-1; while (low<=high){ int mid = (high+low)/2; if(arrs[mid]==target){ return true; } else if(arrs[mid]<target){ low = mid+1; } else { high=mid-1; } } } return false; } private int [] find_target(int[] row_elm,int target) { //求小于等于target的最大值 int [] scan= new int[2]; int i = 0; int j = row_elm.length-1; while (i<j){ int mid = (i+j+1)/2; if(row_elm[mid]<=target){ i=mid; } else { j=mid-1; } } //求大于等于target的最小值 int low = 0 ,high = row_elm.length-1; while (low<high){ int mid = (low+high)/2; if(row_elm[mid]>=target){ high=mid; } else { low= mid+1; } } scan[0] = j; scan[1] = low; return scan; } public static void main(String[] args) { System.out.println(new Main().is_in_matrix()); } }
#include <iostream> (720)#include <vector> using namespace std; int main() { int m, n; cin >> m >> n; vector<vector<int>> nums(m, vector<int>(n)); for (int i = 0; i < m; i++) { for (int j = 0; j < n; j++) { cin >> nums[i][j]; } } int k; cin >> k; int i = m - 1, j = 0; while (i >= 0 && j < n) { int y = nums[i][j]; if (y == k) { cout << "true"; return 0; } if (y < k) j++; else i--; } cout << "false"; return 0; }
def main2(): m, n = map(int, input().split()) k = [] for i in range(m): k.append(list(map(int, input().split()))) t = int(input()) i = 0 j = n-1 while i < m and j < n: if k[i][j] == t: return True elif k[i][j] > t: j -= 1 else: i += 1 return False def main(): m, n = map(int, input().split()) k = [] for i in range(m): k.append(input()) t = input() i = 0 while i < m: if t in k[i]: return True i += 1 return False if __name__ == "__main__": if main(): print("true") else: print("false")
#include <bits/stdc++.h> using namespace std; const int max_mn = 3001; int V[max_mn][max_mn]; // =36MB int main(){ int m,n; cin>>m>>n; //memset(V,0,sizeof(V)); for(int i=0;i<m;i++){ for(int j=0;j<n;j++){ scanf("%d",&V[i][j]); //cin>>V[i][j]; } } int k; cin>>k; bool ans=false; //从右上角开始判定 int i=0,j=n-1; while(i<m and j>=0){ if(V[i][j]==k){ ans = true; break; } if(V[i][j]<k){//第i行pass掉 i=i+1; }else{//第j列被pass掉 j=j-1; } } if(ans) cout<<"true"<<endl; else cout<<"false"<<endl; return 0; }O(2*n)时间复杂度 O(n^2)的空间复杂度