(说明:本博客中的题目、题目详细说明及参考代码均摘自 “何海涛《剑指Offer:名企面试官精讲典型编程题》2012年”)
题目
在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断是否含有该整数。
进一步的详细说明:
下图中的二维数组就是每行、每列都递增排序。如果在这个数组中查找数字 7,则返回 true;如果查找数字 5,由于数组不含有该数字,则返回 false。
算法设计思想
对于类似上图中的二维数组,选择从右上方(数字 9)或 左下方(数字 6)开始遍历,这样可以保证向单一方向缩小搜索范围;而从左上方(数字 1)或右下方(数字 15)开始遍历,可以朝两个方向进行进一步搜索,从而导致无法缩小范围。
以查找数字 5 为例,
若从左下方(数字 6)开始遍历,则由于数字 5 < 6 ,根据二维数组沿行从左到右递增,沿列从上到下递增,数字 5 可能位于数字 6 的上方或左侧,而数字 6 的左侧无元素,因此数字 5 只能位于数字 6 的上方,从而缩小了搜索范围;
若从左上方(数字 1)开始遍历,则由于数字 5 > 1,根据二维数组沿行从左到右递增,沿列从上到下递增,数字 5 可能位于数字 1 的下方或右侧,而数字 1的下方和右侧均有元素,因此无法缩小搜索范围。
以上说明,找到一个好的起点很重要,其会直接影响算法的可行性。
C++ 实现
#include <iostream>
using namespace std;
// Try to find 'target' from 'matrix' with 'rows' rows and 'cols' columns,
// If found, return true; else return false
bool Find(int* matrix, int rows, int cols, int target)
{
bool found = false;
if (!matrix || rows < 0 || cols < 0) // 易漏点
return found;
int i = 0;
int j = cols-1; // Note: the index of the last element in each row is cols-1. // 易错点
while ((i < rows) && (j >= 0))
{
int current = *(matrix+i*cols+j);
if (target < current)
j--;
else if (target > current)
i++;
else { // target == current
found = true;
break;
}
}
return found;
}
// Display the result whether the target is found.
void display(int* matrix, int rows, int cols, int target)
{
cout << "Target " << target << " is ";
if (Find(matrix, rows, cols, target))
cout << "";
else
cout << "not ";
cout << "found." << endl;
}
void unitest()
{
int mat[] = {1, 2, 8, 9,
2, 4, 9, 12,
4, 7, 10, 13,
6, 8, 11, 15};
// Try to find digits 7 and 5, then display the result
display(mat, 4, 4, 7);
display(mat, 4, 4, 5);
}
int main()
{
unitest();
return 0;
}
Python 实现
#!/usr/bin/python
# -*- coding: utf8 -*-
# Try to find 'target' from 'matrix' with 'rows' rows and 'cols' columns,
# If found, return true; else return false
def find_target(matrix, rows, cols, target):
found = False
if not matrix or rows < 0 or cols < 0: # 易漏点
return found
i, j = 0, cols-1 # 易错点
while i < rows and j >= 0:
current = matrix[i*cols+j]
if target < current:
j -= 1
elif target > current:
i += 1
else: # target == current
found = True
break
return found
def unitest():
mat = [1, 2, 8, 9,
2, 4, 9, 12,
4, 7, 10, 13,
6, 8, 11, 15]
# Try to find digits 7 and 5, then display the result
for target in [7, 5]:
print "Target %d is %s found." % (target, "" if find_target(mat, 4, 4, target) else "not")
if __name__ == "__main__":
unitest()
参考代码
1. targetver.h
#pragma once
// The following macros define the minimum required platform. The minimum required platform
// is the earliest version of Windows, Internet Explorer etc. that has the necessary features to run
// your application. The macros work by enabling all features available on platform versions up to and
// including the version specified.
// Modify the following defines if you have to target a platform prior to the ones specified below.
// Refer to MSDN for the latest info on corresponding values for different platforms.
#ifndef _WIN32_WINNT // Specifies that the minimum required platform is Windows Vista.
#define _WIN32_WINNT 0x0600 // Change this to the appropriate value to target other versions of Windows.
#endif
2. stdafx.h
// stdafx.h : include file for standard system include files,
// or project specific include files that are used frequently, but
// are changed infrequently
//
#pragma once
#include "targetver.h"
#include <stdio.h>
#include <tchar.h>
// TODO: reference additional headers your program requires here
3. stdafx.cpp
// stdafx.cpp : source file that includes just the standard includes
// FindInPartiallySortedMatrix.pch will be the pre-compiled header
// stdafx.obj will contain the pre-compiled type information
#include "stdafx.h"
// TODO: reference any additional headers you need in STDAFX.H
// and not in this file
4. FindInPartiallySortedMatrix.cpp
// FindInPartiallySortedMatrix.cpp : Defines the entry point for the console application.
//
// 《剑指Offer——名企面试官精讲典型编程题》代码
// 著作权所有者:何海涛
#include "stdafx.h"
// 二维数组matrix中,每一行都从左到右递增排序,
// 每一列都从上到下递增排序
bool Find(int* matrix, int rows, int columns, int number)
{
bool found = false;
if(matrix != NULL && rows > 0 && columns > 0)
{
int row = 0;
int column = columns - 1;
while(row < rows && column >=0)
{
if(matrix[row * columns + column] == number)
{
found = true;
break;
}
else if(matrix[row * columns + column] > number)
-- column;
else
++ row;
}
}
return found;
}
// ====================测试代码====================
void Test(char* testName, int* matrix, int rows, int columns, int number, bool expected)
{
if(testName != NULL)
printf("%s begins: ", testName);
bool result = Find(matrix, rows, columns, number);
if(result == expected)
printf("Passed.
");
else
printf("Failed.
");
}
// 1 2 8 9
// 2 4 9 12
// 4 7 10 13
// 6 8 11 15
// 要查找的数在数组中
void Test1()
{
int matrix[][4] = {{1, 2, 8, 9}, {2, 4, 9, 12}, {4, 7, 10, 13}, {6, 8, 11, 15}};
Test("Test1", (int*)matrix, 4, 4, 7, true);
}
// 1 2 8 9
// 2 4 9 12
// 4 7 10 13
// 6 8 11 15
// 要查找的数不在数组中
void Test2()
{
int matrix[][4] = {{1, 2, 8, 9}, {2, 4, 9, 12}, {4, 7, 10, 13}, {6, 8, 11, 15}};
Test("Test2", (int*)matrix, 4, 4, 5, false);
}
// 1 2 8 9
// 2 4 9 12
// 4 7 10 13
// 6 8 11 15
// 要查找的数是数组中最小的数字
void Test3()
{
int matrix[][4] = {{1, 2, 8, 9}, {2, 4, 9, 12}, {4, 7, 10, 13}, {6, 8, 11, 15}};
Test("Test3", (int*)matrix, 4, 4, 1, true);
}
// 1 2 8 9
// 2 4 9 12
// 4 7 10 13
// 6 8 11 15
// 要查找的数是数组中最大的数字
void Test4()
{
int matrix[][4] = {{1, 2, 8, 9}, {2, 4, 9, 12}, {4, 7, 10, 13}, {6, 8, 11, 15}};
Test("Test4", (int*)matrix, 4, 4, 15, true);
}
// 1 2 8 9
// 2 4 9 12
// 4 7 10 13
// 6 8 11 15
// 要查找的数比数组中最小的数字还小
void Test5()
{
int matrix[][4] = {{1, 2, 8, 9}, {2, 4, 9, 12}, {4, 7, 10, 13}, {6, 8, 11, 15}};
Test("Test5", (int*)matrix, 4, 4, 0, false);
}
// 1 2 8 9
// 2 4 9 12
// 4 7 10 13
// 6 8 11 15
// 要查找的数比数组中最大的数字还大
void Test6()
{
int matrix[][4] = {{1, 2, 8, 9}, {2, 4, 9, 12}, {4, 7, 10, 13}, {6, 8, 11, 15}};
Test("Test6", (int*)matrix, 4, 4, 16, false);
}
// 鲁棒性测试,输入空指针
void Test7()
{
Test("Test7", NULL, 0, 0, 16, false);
}
int _tmain(int argc, _TCHAR* argv[])
{
Test1();
Test2();
Test3();
Test4();
Test5();
Test6();
Test7();
return 0;
}
5. 项目 03_FindInPartiallySortedMatrix 下载
百度网盘: 03_FindInPartiallySortedMatrix.zip
参考资料
[1] 何海涛. 剑指 Offer:名企面试官精讲典型编程题 [M]. 北京:电子工业出版社,2012. 38-41.