zoukankan      html  css  js  c++  java
  • 算法很美(四)

    四、多维数组与矩阵

    1、顺时针打印二维数组

    顺时针打印二维数组:
    1 2 3 4
    5 6 7 8
    9 10 11 12
    13 14 15 16
    输出:1 2 3 4 8 12 16 15 14 13 9 5 6 7 11 10

    public class PrintTwoDArr {
        public static void main(String[] args) {
            int[][] matrix = {
                    {1,2,3,4},
                    {5,6,7,8},
                    {9,10,11,12},
                    {13,14,15,16},
            };
            print(matrix);
        }
    
        static void print(int[][] matrix) {
            //左上角行、左上角列、右下角行、右下角列
            int leftUpRow = 0, leftUpCol = 0, rightDownRow = matrix.length - 1, rightDownCol = matrix[0].length - 1;
            while (leftUpRow<=rightDownRow && leftUpCol<=rightDownCol) {
                int r = leftUpRow, c = leftUpCol;
                //上面一条边
                while (c <= rightDownCol) {
                    System.out.print(matrix[r][c++] + "  ");
                }
                //恢复
                c = rightDownCol;
                r++;
                //右边的一条边
                while (r <= rightDownRow) {
                    System.out.print(matrix[r++][c] + "  ");
                }
                //恢复
                r = rightDownRow;
                c--;
                //下面的一条边
                while (c >= leftUpCol) {
                    System.out.print(matrix[r][c--] + "  ");
                }
                //恢复
                c = leftUpCol;
                r--;
                //左边的一条边
                while (r > leftUpRow) {
                    System.out.print(matrix[r--][c] + "  ");
                }
                leftUpRow++;
                leftUpCol++;
                rightDownRow--;
                rightDownCol--;
            }
        }
    }
    

    2、零所在的行列清零

    矩阵中含有某个元素0,将其所在的行和列清零
    1 2 3 4
    5 6 0 8
    9 0 11 12
    13 14 15 16
    输出:
    1 0 0 4
    0 0 0 0
    0 0 0 0
    13 0 0 16

    public class CleanZeroInTwoDArr {
        public static void main(String[] args) {
            int[][] matrix = {
                    {1,2,3,0},
                    {5,6,0,8},
                    {9,0,11,12},
                    {13,14,15,16},
            };
            solve(matrix);
            printMatrix(matrix);
        }
    
        public static void solve(int[][] matrix) {
            int M = matrix.length;
            int N = matrix[0].length;
            //记录哪些行出现0
            int[] rowRecord = new int[M];
            //记录哪些列出现0
            int[] colRecord = new int[N];
            for (int i = 0; i < M; i++) {
                for (int j = 0; j < N; j++) {
                    if (matrix[0][0]==0){
                        //标记
                        rowRecord[i]=1;
                        colRecord[j]=1;
                    }
                }
            }
            for (int row = 0; row < M; row++) {
                for (int col = 0; col < N; col++) {
                    //当前的行或列,被标记了,这个元素就应该变为0
                    if (rowRecord[row] ==1 || colRecord[col] ==1) {
                        matrix[row][col] = 0;
                    }
                }
            }
        }
    
        public static void printMatrix(int[][] matrix) {
            for (int[] arr: matrix) {
                for (int e:arr) {
                    System.out.print(e+"	");
                }
                System.out.println();
            }
        }
    }
    

    一点小疑惑:这道题我检查了很多遍,甚至在码云上扣下了源代码来对比,但我的编译器输出仍然是原来一模一样的数组,也没有报错,所以还是学习下思路吧,求大家看后给我个评论呀。

    3、Z字形打印二维数组

    Z字形打印数组,相当于打印斜线

    img

    public class PrintMatrixZ {
        public static void main(String[] args) {
            int[][] matrix = {
                    {1,2,3,4},
                    {5,6,7,8},
                    {9,10,11,12},
                    {13,14,15,16},
            };
            print(matrix);
        }
    
        private static void print(int[][] matrix) {
            int r=0, m=matrix.length;
            int c=0, n=matrix[0].length;
            boolean l2r = true;  //左到由left to right
            while (r<m && c<n) {
                //左下到右上的斜线
                if (l2r) {
                    System.out.print(matrix[r][c]+"  ");
                    //在第一行,列未到边界,只能向右走
                    if (r==0 && c<n-1) {
                        l2r = !l2r;  //切方向
                        c++;
                        continue;
                    }
                    //现在最后一列,只能向下走
                    else if (r>0 && c==n-1) {
                        l2r = !l2r;
                        r++;
                        continue;
                    }else {
                        //继续上坡
                        r--;
                        c++;
                    }
                }
                //反之,下坡
                else {
                    System.out.print(matrix[r][c]+"  ");
                    //走到第一列,只能向下走
                    if (c==0 &&r<m-1) {
                        l2r = !l2r;
                        r++;
                        continue;
                    }
                    //到最后一行,只能右走
                    else if (r==m-1) {
                        l2r = !l2r;
                        c++;
                        continue;
                    }else {
                        //下坡
                        r++;
                        c--;
                    }
                }
            }
        }
    }
    

    4、子数组最大累加和

    给定一个数组arr,返回子数组最大累加和

    如:arr={1,-2,3,5,-2,6,-1} 所有的子数组中[3,5,-2,6]累加最大和12,则返回12

    public class MaxSubArray {
        //暴力解法O(n²)
        static void findByForce(int[] arr) {
            int maxSum = arr[0];
    
            for (int j = 0; j < arr.length; j++) {
                int sum = arr[j]; //某个元素为子数组的第一个元素
                int maxOfJ = sum;
                for (int i = j+1; i < arr.length; i++) {
                    sum += arr[i]; //累加后续元素
                    if (sum >maxOfJ) {
                        maxOfJ = sum;
                    }
                }
                if (maxOfJ>maxSum) {
                    maxSum =maxOfJ;
                }
            }
            System.out.println(maxSum);
        }
    
        //递推法O(n)
        static int findByDp(int[] arr) {
            int sumJ = arr[0]; //前J个元素的最大贡献值
            int max= sumJ;
            int left=0, right=0;
            for (int j = 1; j < arr.length; j++) {
                if (sumJ>=0) { //左子表的最大和为正,继续向后累加
                    sumJ += arr[j];
                }else {
                    sumJ = arr[j];
                    left = j;  //丢弃前部分和的同时,更新left
                }
                if (sumJ>max) {
                    max = sumJ;
                    right = j; //更新max的同时更新right
                }
            }
            return max;
        }
    
        public static void main(String[] args) {
            int[] arr = {1,-2,3,5,-2,6,-1};
            findByForce(arr);
            findByDp(arr);
        }
    }
    

    5、子矩阵最大累加和

    给定一个矩阵matrix, 其中的值有正、有负、有零,返回子矩阵最大累加和

    如:给出matrix

    -1 -1 -1

    -1 2 2

    -1 -1 -1

    其中最大累加和的子矩阵是2 2

    所以返回4

    import java.util.Arrays;
    
    public class MaxSubMatrix {
        public static void main(String[] args) {
            int[][] matrix = {
                    {-1, -1, -1},
                    {-1, 2, 2},
                    {-1, -1, -1}
            };
            int res = maxSum(matrix);
            System.out.println(res);
        }
    
        private static int maxSum(int[][] matrix) {  //O(N^3)
            int beginRow = 0; //以它为起始行
    
            final int M = matrix.length;
            final int N = matrix[0].length;
    
            int[] sums = new int[N]; //按列求和
            int max = 0; //历史最大子矩阵和
            while (beginRow < M) { //起始行
                for (int i = beginRow; i < M; i++) { //从起始行到第i行
                    //按列累加
                    for (int j = 0; j < N; j++) {
                        sums[j] += matrix[i][j];
                    }
                    //累加完成
                    //求出sums的最大和子数组
                    int t = MaxSubArray.findByDp(sums);
                    if (t > max) {
                        max = t;
                    }
                }
                //另起一行作为起始行,把sums清零
                Arrays.fill(sums,0); //将sums的每个元素设为0
                beginRow++;
            }
            return max;
        }
    }
    
  • 相关阅读:
    PAT A1023 Have Fun with Numbers (20) [⼤整数运算 高精度]
    算法笔记-数学问题-高精-大整数
    PAT A1130 Infix Expression (25) [中序遍历]
    PAT A1130 Infix Expression (25分) [二叉树中序遍历 中缀表达式]
    PAT A1129 Recommendation System (25) [set的应⽤,运算符重载]
    PAT A1118 Birds in Forest (25) [并查集]
    PAT A1124 Raffle for Weibo Followers (20分) [map vector]
    C++ STL
    PAT A1121 Damn Single (25) [map set hash]
    算法笔记-易错记录
  • 原文地址:https://www.cnblogs.com/wangzheming35/p/12510621.html
Copyright © 2011-2022 走看看