zoukankan      html  css  js  c++  java
  • 二维矩阵求极小值

    问题描述

    给定一个不包含重复元素的N行M列二维矩阵,求矩阵的极小值。极小值的定义如下:若一个值是极小值,四连通方向上的的不越界的邻居都比它大。

    思路

    二维比较难想,我们从一维说起。
    对于一维数组来说,如何寻找极小值?
    二分法,找到中间位置x,如果x-1处的元素比x+1处的元素小,那么0~x-1之间必然存在一个极小值,从而缩小了范围。

    升到二维,这个问题等价于。在平原上,寻找一个坑。这其实非常简单,我们只需要任选一点,从这个点出发始终朝着低处走,一定能够找到极小值点。

    升到二维,首先也要想到分治法,降低复杂度。
    对于矩阵较长的那个轴,二分之,切一刀。在刀痕处寻找极小值,极小值所在的那一侧必然是包含极小值的。

    总之,这个问题只有一个思路:目前发现的最小值所在的区域一定包含极小值。关键在于划分区域的时候要严格保证最小值不会流出区域。

    代码

    import java.util.Random;
    
    class Main {
    int[][] a;
    Random r = new Random();
    
    void generate() {
        int rows = r.nextInt(10) + 5;
        int cols = r.nextInt(10) + 5;
        a = new int[rows][cols];
        int b[] = new int[rows * cols];
        for (int i = 0; i < b.length; i++) b[i] = i;
        for (int i = 0; i < b.length; i++) {
            int next = r.nextInt(b.length - i) + i;
            int temp = b[i];
            b[i] = b[next];
            b[next] = temp;
        }
        for (int i = 0; i < rows; i++) {
            for (int j = 0; j < cols; j++) {
                a[i][j] = b[i * cols + j];
            }
        }
    }
    
    class Pos {
        int x, y;
        int value;
    
        Pos(int x, int y, int value) {
            this.x = x;
            this.y = y;
            this.value = value;
        }
    }
    
    boolean legal(int x, int y) {
        return x >= 0 && y >= 0 && x < a.length && y < a[0].length;
    }
    
    int dir[][] = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}};
    
    boolean isMinimum(int i, int j) {
        for (int k = 0; k < dir.length; k++) {
            int x = i + dir[k][0];
            int y = j + dir[k][1];
            if (legal(x, y)) {
                if (a[x][y] < a[i][j]) {
                    return false;
                }
            }
        }
        return true;
    }
    
    Pos good(int fx, int fy, int tx, int ty, Pos min) {
        if (fx + 1 == tx && fy + 1 == ty) return new Pos(fx, fy, a[fx][fy]);
        if (tx - fx < ty - fy) {//二分长轴
            int my = (ty + fy) >> 1;
            for (int i = fx; i < tx; i++) {
                if (a[i][my] < min.value) {
                    min.x = i;
                    min.y = my;
                    min.value = a[i][my];
                }
            }
            int minx = min.x, miny = min.y;
            for (int i = 0; i < dir.length; i++) {
                int x = minx + dir[i][0], y = miny + dir[i][1];
                if (legal(x, y) && a[x][y] < min.value) {
                    min.x = x;
                    min.y = y;
                    min.value = a[x][y];
                }
            }
            if (min.y >= my) {
                return good(fx, my, tx, ty, min);
            } else {
                return good(fx, fy, tx, my, min);
            }
        } else {
            int mx = (tx + fx) >> 1;
            for (int i = fy; i < ty; i++) {
                if (a[mx][i] < min.value) {
                    min.x = mx;
                    min.y = i;
                    min.value = a[mx][i];
                }
            }
            int minx = min.x, miny = min.y;
            for (int i = 0; i < dir.length; i++) {
                int x = minx + dir[i][0];
                int y = miny + dir[i][1];
                if (legal(x, y) && a[x][y] < min.value) {
                    min.x = x;
                    min.y = y;
                    min.value = a[x][y];
                }
            }
            if (min.x >= mx) {
                return good(mx, fy, tx, ty, min);
            } else {
                return good(fx, fy, mx, ty, min);
            }
        }
    }
    
    
    Main() {
        for (int t = 0; t < 100; t++) {
            generate();
            Pos p = good(0, 0, a.length, a[0].length, new Pos(-1, -1, Integer.MAX_VALUE));
            for (int i = 0; i < a.length; i++) {
                for (int j = 0; j < a[i].length; j++) {
                    System.out.printf(String.format("%4d", a[i][j]));
                }
                System.out.println();
            }
            System.out.println(p.x + " " + p.y + " " + p.value);
            if (!isMinimum(p.x, p.y)) {
                throw new RuntimeException("error");
            }
        }
    }
    
    public static void main(String[] args) {
        new Main();
    }
    }
    
  • 相关阅读:
    python开发_html_html处理
    python开发_logging_日志处理
    IIS 7 应用程序池自动回收关闭的解决方案
    C#流水号生成汇总(四)
    通过内存盘提高MSMQ的消息吞吐能力
    c#分页工具类,完美实现List分页
    IIS 未能从程序集“System.ServiceModel, Version=3.0.0.0, Culture=neutral,
    win7电脑遇到端口被占用的情况该如何查看并将其关闭
    如何创建内存盘
    IP地址便捷修改器 V3.5 绿色版
  • 原文地址:https://www.cnblogs.com/weiyinfu/p/9574260.html
Copyright © 2011-2022 走看看