矩阵螺旋遍历
华为OD机试真题 新系统 华为OD上机考试真题新系统 9月16号 100分题型
华为OD机试新系统真题目录点击查看: 华为OD机试新系统真题题库目录|机考题库 + 算法考点详解
题目内容
给定一个M行N列的矩阵,矩阵中每个元素是一个非负整数,从左上角(0,0)开始,按顺时针螺旋顺序遍历矩阵,对于遍历的每个数字,计算器二进制表示中1的个数,如果1的个数是3的倍数,则记录该数字的坐标。请按照顺序输出满足条件的数字的坐标列表。
螺旋遍历按照从外到内,从(0,0)出发,先向右,遇到边界或以访问元素后,按右->下-> 左->下循环转向。
输入描述
一个二维数字Array[M][N](1 <= M,N <= 10),数字行数为M,列数位N;每个数组元素是由N个非负整数组成的数组,整数范围在0,10\^9中
输出描述
按遍历顺序输出满足条件的坐标,单个格式为(行索引,列索引);如果没有满足条件的数字输出空;数字0按满足条件统计输出。
样例1
输入
3 4
1 2 3 4
5 6 7 8
9 10 11 12
输出
(2,2) (1,2)
题解
思路:模拟
- 按照题意进行模拟执行代码逻辑即可。根据螺旋遍历规律
- 定义
top bottom left right表示本次循环的四个边界- 初始从左至右,碰到右边界,更新上边界范围。转向从上到下
- 碰到下边界时,更新右边界,转向从右至左。
- 碰到左边界时,更新下边界,转向从下到上
- 碰到上边界时,更新左边界,转向从左至右。
- 重复以上逻辑直到将所有元素访问之后,结束
- 定义
- 遍历过程中
二进制移位统计对应二进制1的数量,判断满足3的倍数?满足情况下加入结果数组中
这道题的逻辑和之前考过的一道题逻辑基本一致华为OD机试真题 - 数字螺旋矩阵
C++
cpp
#include <bits/stdc++.h>
#include <vector>
using namespace std;
// 检验二进制1的数量是否为3的倍数
bool check(int num) {
int sum = 0;
while (num != 0) {
if ((num & 1) != 0) {
sum++;
}
num >>= 1;
}
return (sum % 3) == 0;
}
vector<vector<int>> solve(vector<vector<int>>& nums) {
vector<vector<int>> ans;
int m = nums.size();
int n = nums[0].size();
int total = m * n;
int top = 0, bottom = m - 1, left = 0, right = n - 1;
while (top <= bottom && left <= right) {
for (int i = left; i <= right; i++) {
if (check(nums[top][i])) {
ans.push_back({top, i});
}
}
top++;
for (int i = top; i <= bottom ; i++) {
if (check(nums[i][right])) {
ans.push_back({i, right});
}
}
right--;
for (int i = right; i >= left ; i--) {
if (check(nums[bottom][i])) {
ans.push_back({bottom, i});
}
}
bottom--;
for (int i = bottom; i >= top ; i--) {
if (check(nums[i][left])) {
ans.push_back({i, left});
}
}
left++;
}
return ans;
}
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];
}
}
vector<vector<int>> ans = solve(nums);
for (int i = 0; i < ans.size(); i++) {
if (i > 0) {
cout << " ";
}
cout << "(" << ans[i][0] << "," << ans[i][1] << ")";
}
return 0;
}
Java
java
import java.util.*;
public class Main {
// 检验二进制1的数量是否为3的倍数
static boolean check(int num) {
int sum = 0;
while (num != 0) {
if ((num & 1) != 0) {
sum++;
}
num >>= 1;
}
return (sum % 3) == 0;
}
static List<List<Integer>> solve(int[][] nums) {
List<List<Integer>> ans = new ArrayList<>();
int m = nums.length;
int n = nums[0].length;
int top = 0, bottom = m - 1, left = 0, right = n - 1;
while (top <= bottom && left <= right) {
for (int i = left; i <= right; i++) {
if (check(nums[top][i])) {
ans.add(Arrays.asList(top, i));
}
}
top++;
for (int i = top; i <= bottom; i++) {
if (check(nums[i][right])) {
ans.add(Arrays.asList(i, right));
}
}
right--;
for (int i = right; i >= left; i--) {
if (check(nums[bottom][i])) {
ans.add(Arrays.asList(bottom, i));
}
}
bottom--;
for (int i = bottom; i >= top; i--) {
if (check(nums[i][left])) {
ans.add(Arrays.asList(i, left));
}
}
left++;
}
return ans;
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int m = sc.nextInt();
int n = sc.nextInt();
int[][] nums = new int[m][n];
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
nums[i][j] = sc.nextInt();
}
}
List<List<Integer>> ans = solve(nums);
for (int i = 0; i < ans.size(); i++) {
if (i > 0) {
System.out.print(" ");
}
System.out.print("(" + ans.get(i).get(0) + "," + ans.get(i).get(1) + ")");
}
}
}
Python
python
import sys
# 检验二进制1的数量是否为3的倍数
def check(num):
sum = 0
while num != 0:
if (num & 1) != 0:
sum += 1
num >>= 1
return (sum % 3) == 0
def solve(nums):
ans = []
m = len(nums)
n = len(nums[0])
top = 0
bottom = m - 1
left = 0
right = n - 1
while top <= bottom and left <= right:
for i in range(left, right + 1):
if check(nums[top][i]):
ans.append([top, i])
top += 1
for i in range(top, bottom + 1):
if check(nums[i][right]):
ans.append([i, right])
right -= 1
for i in range(right, left - 1, -1):
if check(nums[bottom][i]):
ans.append([bottom, i])
bottom -= 1
for i in range(bottom, top - 1, -1):
if check(nums[i][left]):
ans.append([i, left])
left += 1
return ans
def main():
data = list(map(int, sys.stdin.read().split()))
pos = 0
m = data[pos]
n = data[pos + 1]
pos += 2
nums = []
for i in range(m):
nums.append(data[pos:pos + n])
pos += n
ans = solve(nums)
print(" ".join(f"({x},{y})" for x, y in ans), end="")
if __name__ == "__main__":
main()
JavaScript
js
const readline = require('readline');
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
let lines = [];
rl.on('line', line => {
lines.push(line);
});
rl.on('close', () => {
const data = lines.join(' ').split(/\s+/).map(Number);
let pos = 0;
const m = data[pos++];
const n = data[pos++];
const nums = [];
for (let i = 0; i < m; i++) {
const row = [];
for (let j = 0; j < n; j++) {
row.push(data[pos++]);
}
nums.push(row);
}
// 检验二进制1的数量是否为3的倍数
function check(num) {
let sum = 0;
while (num !== 0) {
if ((num & 1) !== 0) {
sum++;
}
num >>= 1;
}
return (sum % 3) === 0;
}
function solve(nums) {
const ans = [];
const m = nums.length;
const n = nums[0].length;
let top = 0;
let bottom = m - 1;
let left = 0;
let right = n - 1;
while (top <= bottom && left <= right) {
for (let i = left; i <= right; i++) {
if (check(nums[top][i])) {
ans.push([top, i]);
}
}
top++;
for (let i = top; i <= bottom; i++) {
if (check(nums[i][right])) {
ans.push([i, right]);
}
}
right--;
for (let i = right; i >= left; i--) {
if (check(nums[bottom][i])) {
ans.push([bottom, i]);
}
}
bottom--;
for (let i = bottom; i >= top; i--) {
if (check(nums[i][left])) {
ans.push([i, left]);
}
}
left++;
}
return ans;
}
const ans = solve(nums);
console.log(ans.map(([x, y]) => `(${x},${y})`).join(' '));
});
Go
go
package main
import (
"bufio"
"fmt"
"os"
)
// 检验二进制1的数量是否为3的倍数
func check(num int) bool {
sum := 0
for num != 0 {
if (num & 1) != 0 {
sum++
}
num >>= 1
}
return sum%3 == 0
}
func solve(nums [][]int) [][]int {
ans := [][]int{}
m := len(nums)
n := len(nums[0])
top, bottom := 0, m-1
left, right := 0, n-1
for top <= bottom && left <= right {
for i := left; i <= right; i++ {
if check(nums[top][i]) {
ans = append(ans, []int{top, i})
}
}
top++
for i := top; i <= bottom; i++ {
if check(nums[i][right]) {
ans = append(ans, []int{i, right})
}
}
right--
for i := right; i >= left; i-- {
if check(nums[bottom][i]) {
ans = append(ans, []int{bottom, i})
}
}
bottom--
for i := bottom; i >= top; i-- {
if check(nums[i][left]) {
ans = append(ans, []int{i, left})
}
}
left++
}
return ans
}
func main() {
in := bufio.NewReader(os.Stdin)
out := bufio.NewWriter(os.Stdout)
defer out.Flush()
var m, n int
fmt.Fscan(in, &m, &n)
nums := make([][]int, m)
for i := 0; i < m; i++ {
nums[i] = make([]int, n)
for j := 0; j < n; j++ {
fmt.Fscan(in, &nums[i][j])
}
}
ans := solve(nums)
for i := 0; i < len(ans); i++ {
if i > 0 {
fmt.Fprint(out, " ")
}
fmt.Fprintf(out, "(%d,%d)", ans[i][0], ans[i][1])
}
}
C语言
cpp
#include <stdio.h>
#include <stdlib.h>
// 检验二进制1的数量是否为3的倍数
int check(int num) {
int sum = 0;
while (num != 0) {
if ((num & 1) != 0) {
sum++;
}
num >>= 1;
}
return (sum % 3) == 0;
}
typedef struct {
int x;
int y;
} Point;
Point* solve(int** nums, int m, int n, int* ansSize) {
int maxSize = m * n;
Point* ans = (Point*)malloc(sizeof(Point) * maxSize);
*ansSize = 0;
int top = 0, bottom = m - 1;
int left = 0, right = n - 1;
while (top <= bottom && left <= right) {
for (int i = left; i <= right; i++) {
if (check(nums[top][i])) {
ans[*ansSize].x = top;
ans[*ansSize].y = i;
(*ansSize)++;
}
}
top++;
for (int i = top; i <= bottom; i++) {
if (check(nums[i][right])) {
ans[*ansSize].x = i;
ans[*ansSize].y = right;
(*ansSize)++;
}
}
right--;
for (int i = right; i >= left; i--) {
if (check(nums[bottom][i])) {
ans[*ansSize].x = bottom;
ans[*ansSize].y = i;
(*ansSize)++;
}
}
bottom--;
for (int i = bottom; i >= top; i--) {
if (check(nums[i][left])) {
ans[*ansSize].x = i;
ans[*ansSize].y = left;
(*ansSize)++;
}
}
left++;
}
return ans;
}
int main() {
int m, n;
scanf("%d %d", &m, &n);
int** nums = (int**)malloc(sizeof(int*) * m);
for (int i = 0; i < m; i++) {
nums[i] = (int*)malloc(sizeof(int) * n);
for (int j = 0; j < n; j++) {
scanf("%d", &nums[i][j]);
}
}
int ansSize;
Point* ans = solve(nums, m, n, &ansSize);
for (int i = 0; i < ansSize; i++) {
if (i > 0) {
printf(" ");
}
printf("(%d,%d)", ans[i].x, ans[i].y);
}
free(ans);
for (int i = 0; i < m; i++) {
free(nums[i]);
}
free(nums);
return 0;
}