`
mfkvfn
  • 浏览: 18002 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

逆时针矩阵

阅读更多
最近在http://suanfa.group.iteye.com/group/topic/27110看到一个逆时针矩阵。大致意思是说如果给定M*N的矩阵,在矩阵中采用逆时针方式填充数据。比如

3*3矩阵结果是:
1  8  7
2  9  6
3  4  5
3*4矩阵结果是:
1 10  9  8
2 11 12  7
3  4  5  6
4*6矩阵结果是:
1 16 15 14 13 12
2 17 24 23 22 11
3 18 19 20 21 10
4  5  6  7  8  9
6*4矩阵结果是:
1 16 15 14
2 17 24 13
3 18 23 12
4 19 22 11
5 20 21 10
6  7  8  9

这种问题首先想到的是个数学问题,最好的办法是总结出规律,直接定位。如
f(x,y)=z (其中x,y是矩阵的坐标,z是对应的数值,如 f(2,3)=19表示第3行第4列的值是19),只要找到这样的f函数即可。

另外这个方法符合递归的特性,比如最外面一圈的数据(一个长方形)与第二圈的数据(也是一个长方形)有相同的特性,都是按“下-->右-->上-->左”的方式填充的,左上角数据最小,第一行第二个数据最大,...。这样就可以用递归的方式来实现了“先填充外层矩形,如果矩形不是空心的,再递归填充里面的矩阵”。

还有一种方法是按题目的说法(逆时针输出),用模拟的方法来实现,“当前位置填充--->找到下一位置--->当前位置填充--->找到下一位置-->...”由于数据是连续的,每次只要找到“下一个填充位置”就可以了。下一位置怎么找?与当前填充方向有关。即有4种填充策略,每个填充完后返回下一个要使用的策略。

实际应用中应该优先考虑第一种方法,这样效率极高。
第二种方法也还可以,代码应该会比较简洁。
我这里对第三种方法进行了尝试,完整代码如下
public class Dir {
    public class Position{
        public int row; 
        public int col; 
        public Position(int row,int col){
            this.row=row;
            this.col=col;
        }
    }
    public static final Dir DOWN=new Dir(){
        protected Dir getNext() {
            return Dir.RIGHT;
        }
        public Dir fill(int[][] arr,Position pos) {
            int temp=arr[pos.row][pos.col];
            pos.row++;
            //从当前位置往下填充所有为0的单元格,遇到不为0(表示已经填充过了)时停止
            for(int i=pos.row,len=arr.length;i<len;i++){
                if(arr[i][pos.col]==0){
                    arr[i][pos.col]=++temp;
                    pos.row=i;
                }else{
                    break;
                }
            }
            return this.nextDir(arr, pos);
        }
    };
    public static final Dir RIGHT=new Dir(){
        protected Dir getNext() {
            return Dir.UP;
        }
        public Dir fill(int[][] arr,Position pos) {
            int temp=arr[pos.row][pos.col];
            pos.col++;
            //从当前位置往右填充所有为0的单元格,遇到不为0(表示已经填充过了)时停止
            for(int i=pos.col,len=arr[0].length;i<len;i++){
                if(arr[pos.row][i]==0){
                    arr[pos.row][i]=++temp;
                    pos.col=i;
                }else{
                    break;
                }
            }
            return this.nextDir(arr, pos);
        }
    };
    public static final Dir UP=new Dir(){
        protected Dir getNext() {
            return Dir.LEFT;
        }
        public Dir fill(int[][] arr,Position pos) {
            int temp=arr[pos.row][pos.col];
            pos.row--;
            //从当前位置往上填充所有为0的单元格,遇到不为0(表示已经填充过了)时停止
            for(int i=pos.row;i>=0;i--){
                if(arr[i][pos.col]==0){
                    arr[i][pos.col]=++temp;
                    pos.row=i;
                }else{
                    break;
                }
            }
            return this.nextDir(arr, pos);
        }
    };
    public static final Dir LEFT=new Dir(){
        protected Dir getNext() {
            return Dir.DOWN;
        }
        public Dir fill(int[][] arr,Position pos) {
            int temp=arr[pos.row][pos.col];
            pos.col--;
            //从当前位置往左填充所有为0的单元格,遇到不为0(表示已经填充过了)时停止
            for(int i=pos.col;i>=0;i--){
                if(arr[pos.row][i]==0){
                    arr[pos.row][i]=++temp;
                    pos.col=i;
                }else{
                    break;
                }
            }
            return this.nextDir(arr, pos);
        }
    };
    public Dir fill(int[][] arr,Position pos){
        return null;// to be implemented
    }
    /** 下一个方向是什么 */
    protected Dir getNext() {
        return null;// to be implemented
    }
    protected Dir nextDir(int[][] arr,Position pos){
        return (arr[pos.row][pos.col]==arr.length*arr[0].length)?null:this.getNext();
    }
    
}


测试代码如下
public class Test {

    public static void main(String[] args) {
        // 4行6列的数组
        int M = 4, N = 6;
        int[][] arr = new int[M][N];
        arr[0][0] = 1;
        //初始方向向下
        Dir d = Dir.DOWN;
        //初始位置左上角
        Position pos = d.new Position(0,0);
        //开始填充
        do {
            d = d.fill(arr, pos);
        } while (d != null);
        //输出结果
        for (int i = 0; i < M; i++) {
            for (int j = 0; j < N; j++) {
                System.out.print((arr[i][j] < 10 ?" ":"")+arr[i][j]+" ");
            }
            System.out.println();
        }
    }
}


运行结果为:
1 16 15 14 13 12
2 17 24 23 22 11
3 18 19 20 21 10
4  5  6  7  8  9
完全正常。

以上代码中使用了“模板方法模式+变种的单例模式(4个实例)”。还有“匿名内部类”的使用。
0
0
分享到:
评论
2 楼 mfkvfn 2012-03-26  
实际工程中没有意义,纯学术研究,可能跟游戏方面有一点点沾边。
1 楼 handy.wang 2012-03-24  
这个能解决工程中什么实际问题呢?我比较关心这个。
如果是纯学术没有意义。

相关推荐

    动态逆时针数的矩阵

    在IT领域,尤其是在编程中,动态逆时针数的矩阵是一种常见的数据结构问题,它涉及到数组、矩阵操作以及算法设计。在这个场景中,我们看到标题提及的是“动态逆时针数的矩阵”,并且描述中提到是用C++的MFC...

    逆时针蛇形矩阵问题

    逆时针蛇形矩阵是一种特殊的二维数组排列方式,它的特点是元素按照从左上角开始,先向右走,然后向下,接着向左,最后向上,如此反复,形成一个逆时针方向的“S”形路径。在C语言中实现这个功能,需要对数组操作和...

    逆时针螺旋式旋转输出

    逆时针螺旋式输出是一种常见的编程问题,主要涉及到矩阵数据结构的操作。在这个问题中,我们需要将一个二维数组或矩阵按照逆时针方向进行螺旋式的输出。这种操作在数据处理、图像处理以及某些算法实现中都有可能用到...

    从中心开始,逆时针打印 n*n 矩阵

    从中心开始,逆时针打印 n*n 矩阵

    n阶矩阵顺时针逆时针蛇形输出源代码

    n阶矩阵顺时针逆时针蛇形输出源代码 本文将对给定的源代码进行分析,并从中提取出相关的知识点,包括C语言的循环语句、嵌套定义、矩阵的顺时针逆时针蛇形输出等。 知识点1:C语言的循环语句 在给定的源代码中,...

    java 将二维数组顺时针,逆时针排序

    逆时针排序则是从左上角开始,沿着逆时针方向进行。这样的操作常见于游戏编程、图像处理等领域。 本篇讨论的"java 将二维数组顺时针,逆时针排序"主题,主要关注如何实现这两个功能。我们可以采用迭代或递归的方法...

    用Swift3实现n*n阶矩阵逆时针输出

    用Swift3实现n*n阶矩阵逆时针输出

    java实现的顺时针/逆时针打印矩阵操作示例

    Java 实现的顺时针/逆时针打印矩阵操作示例 在 Java 中,实现顺时针/逆时针打印矩阵操作是非常有用的技术,它可以应用于各种数据处理和分析领域。本文将详细介绍 Java 中实现顺时针/逆时针打印矩阵操作的示例代码和...

    对图像进行顺时针逆时针旋转变换,带测试图片

    - 对于旋转,仿射变换矩阵A可以通过原点旋转矩阵R与单位矩阵I相乘得到,其中R是一个2x2的旋转矩阵,其元素取决于旋转角度θ(顺时针为负,逆时针为正)。 2. **旋转矩阵**: - 顺时针旋转矩阵R(θ)可以表示为:...

    完整版图象处理—顺逆时针图片转换.rar

    这个“完整版图象处理—顺逆时针图片转换.rar”压缩包文件很可能包含了一个或者多个程序、工具或教程,用于帮助用户实现这一功能。下面将详细讲解图像处理中的顺时针与逆时针旋转以及相关技术。 1. 图像旋转基础: ...

    Java实现的按照顺时针或逆时针方向输出一个数字矩阵功能示例

    Java实现按照顺时针或逆时针方向输出数字矩阵的功能示例 Java是一种流行的编程语言,广泛应用于各种软件开发中。Java实现按照顺时针或逆时针方向输出数字矩阵的功能是Java编程中的一个重要应用场景。本文将主要介绍...

    逆变换与逆矩阵练习题.doc

    - (1) 逆时针旋转90°的逆变换是顺时针旋转90°。 - (2) 反射变换关于原点的逆变换是其自身。 - (3) 横坐标不变,纵坐标压缩一半的逆变换是纵坐标拉伸至原来的两倍。 2. **逆矩阵的性质**:如果矩阵A的逆为A^-1...

    图象处理—顺逆时针图片转换.zip易语言程序源码资源下载

    3. 计算旋转矩阵:根据旋转角度(顺时针或逆时针)构建旋转矩阵。 4. 应用旋转:遍历图像上的每个像素,使用旋转矩阵将其坐标转换到新的位置。 5. 写入新图像:创建一个新的图像缓冲区,将旋转后的像素写入,生成...

    三维坐标点 旋转矩阵 推导流程

    首先,我们使用右手坐标系进行讨论,其中角度的增加方向是逆时针方向。三维坐标点的旋转可以通过分别绕X、Y、Z轴进行,而每个轴上的旋转都可以用一个二维旋转矩阵来表示。旋转的角度通常称为俯仰角(Pitch)、偏航角...

    图象处理—顺逆时针图片转换.rar

    实现顺逆时针图片转换的核心算法通常是基于矩阵运算的。图像可以看作是一个二维矩阵,每个元素代表一个像素。要旋转图像,我们可以先创建一个新的矩阵来接收旋转后的图像,然后根据旋转中心、旋转角度和原始图像的...

    逆变换与逆矩阵练习题精选.doc

    这个变换可以是绕原点逆时针旋转 90°,也可以是以原点为中心,作反射变换。这些变换的组合可以使得连续进行两次变换的结果与恒等变换的结果相同。 练习题 2: 给定一个矩阵 A,求其逆矩阵是否存在?若存在,求出...

    易语言源码图象处理—顺逆时针图片转换.7z

    顺时针旋转和逆时针旋转涉及到矩阵变换,如旋转变换矩阵,可以通过这个矩阵将每个像素的新坐标计算出来。 对于顺时针旋转,通常是以图像中心为旋转点,逆时针则是相反方向。假设我们有一个宽度为W、高度为H的图像,...

    图象处理—顺逆时针图片转换.e.rar

    这个"图象处理—顺逆时针图片转换.e.rar"压缩包文件可能包含了一系列关于如何实现这种转换的教程、代码示例或者相关软件工具。在这个主题中,我们将探讨图像旋转的基本概念、方法以及实际应用。 首先,图像旋转是...

    易语言源代码_图象处理—顺逆时针图片转换.zip

    《易语言源代码_图象处理—顺逆时针图片转换》 易语言是一种基于中文图形界面的编程语言,它的设计目标是使编程更加简单、直观,尤其适合初学者和非计算机专业人员。在这个压缩包中,我们主要关注的是一个关于图象...

Global site tag (gtag.js) - Google Analytics