onlineJ杨氏矩阵


题目描述

给定一个n行m列的二维矩阵和一个目标数t,

二维矩阵中对于每一行从左到右不下降(右边的数≥左边的数),对于每一列从上到下不下降(下边的数≥上边的数)。

现要在数组中找到目标数t,并输出其所在位置的行数和列数。

输入

第一行两个整数n, m(1 ≤ n, m ≤ 3000)

接下来输入一个二维矩阵,矩阵内所有数均小于 200000。

最后输入一个整数t(1 ≤ t ≤ 200000)

输出

输出用空格隔开的数表示位置(从1开始计数),答案有唯一解。

1
2
3
4
5
3 4
1 2 3 4
5 6 15 20
7 10 20 25
15
1
2 3

1.暴力法:

==思路==:

使用两个for循环对矩阵进行遍历操作,当遍历到target值时输出其行、列的下标值。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include<iostream>
using namespace std;

int n, m, target;
int num[3005][3005];

int main() {
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= m; ++j) {
scanf("%d", &num[i][j]);
}
}
scanf("%d", &target);
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= m; ++j) {
if (num[i][j] == target) {
printf("%d %d\n", i, j);
return 0;
}
}
}
printf("no find!\n");
return 0;
}

image-20220504175022611

注意:该暴力枚举法的时间复杂度为O(n * m),空间复杂度为O(1)

2.值比较法:

==思路==:

由于矩阵数据的行、列递增性,可以巧取比较法实现target值的寻找:

  1. 从矩阵的左下角or右上角出发,进行对target值的依次比较(以从左下角出发为例)
  2. 如果target值比当前位置的数值大,则向右移动一格(行具有递增性)
  3. 如果target值比当前位置的数值小,则向上移动一格(列具有递减性)
  4. 经过多次移动后,当最后值等于target值时,输出行、列的下标

补充:如果最后的值移动出了矩阵范围,则表示没有找到target值

image-20220504173136902

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include<iostream>
using namespace std;

int n, m, target;
int num[3005][3005];

int main() {
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= m; ++j) {
scanf("%d", &num[i][j]);
}
}
scanf("%d", &target);
int x = n, y = 1;//从左下角开始比较
while (x > 0 && y <= m) {
int cur = num[x][y];
if (cur == target) {
printf("%d %d\n", x, y);
return 0;
}
if (cur > target) {
--x;
} else {
++y;
}
}
printf("no find!\n");
return 0;
}

注意:该方法的时间复杂度为O(n + m),空间复杂度为O(1)