二维数组中的查找(C++和Python实现)

(说明:本博客中的题目题目详细说明参考代码均摘自 “何海涛《剑指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.\n");
    else
        printf("Failed.\n");
}

//  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.

posted @ 2017-09-03 19:38  klchang  阅读(1660)  评论(0编辑  收藏  举报