打表技巧和矩阵处理技巧

最小袋子数量

在这里插入图片描述
思路:先用暴力打表方式输出一定数量内的结果,根据结果找到规律

package com.zzf.algorithm;

/**
 * @author zzf
 * @date 2022-02-09
 */
public class AppleMinBags {

    public static int minBags(int apple){
        if(apple < 0){
            return -1;
        }
        //优先从能装8个的袋子开始
        int bag8 = apple / 8;
        int rest = apple - (bag8 * 8);
        while (bag8 >= 0){
            if(rest % 6 == 0){
                return bag8 + (rest / 6);
            }
            //剩余无法装完6的袋子,选择退一步
            else {
                bag8--;
                rest += 8;
            }
        }
        return -1;
    }

    public static void main(String[] args) {
        for(int apple = 1; apple < 200;apple++) {
            System.out.println(apple + " : "+ minBags(apple));
        }

    }
}


发现的规律是从18开始具有明显的分组倾向,每8个一组,而且其中奇数返回结果是-1,其余结果是当前组数+3,18以内的单独处理

package com.zzf.algorithm;

/**
 * @author zzf
 * @date 2022-02-09
 */
public class AppleMinBags {

    public static int minBags(int apple){
        
        //奇数返回-1
        if((apple & 1) !=0){
            return -1;
        }
        if(apple < 18){
            return apple == 0 ? 0 :(apple == 6 || apple == 8) ? 1
                    : (apple == 12 || apple == 14 || apple == 16) ? 2 : -1;
        }
        return (apple - 18) / 8 + 3;
    }

    public static void main(String[] args) {
        for(int apple = 1; apple < 200;apple++) {
            System.out.println(apple + " : "+ minBags(apple));
        }

    }
}


连续整数和的数

在这里插入图片描述
思路:根据暴力大表输出判断200以内的数字是否为连续正数和的数,尝试找出规律,然后再利用规律写出更优的代码

package com.zzf.algorithm;

/**
 * @author zzf
 * @date 2022-02-09
 */
public class MSumToN {
    public static boolean isMSum(int num){
        for (int i = 1; i <= num; i++) {
            int sum = i;
            for (int j = i + 1; j <= num; j++) {
                if(sum + j > num){
                    break;
                }
                if(sum + j == num){
                    return true;
                }
                sum += j;
            }
        }
        return false;
    }

    public static void main(String[] args) {
        for (int num = 1; num < 200; num++) {
            System.out.println(num + " : " + isMSum(num));
        }
    }
}

部分结果
在这里插入图片描述
根据结果可以发现凡是2的幂次方的数字都不满足条件,因此根据这一规律可以得到更优的代码

package com.zzf.algorithm;

/**
 * @author zzf
 * @date 2022-02-09
 */
public class MSumToN {
    public static boolean isMSum(int num){
        
        /*
        num & (num - 1)是判断是否为2的幂次方的位运算操作
        因为num如果是2的幂次方,二进制数中只有1个1
        num-1会把后面的几位反转,&操作得到的会是0
         */
        return (num & (num - 1)) != 0;
    }

    public static void main(String[] args) {
        for (int num = 1; num < 200; num++) {
            System.out.println(num + " : " + isMSum(num));
        }
    }
}

打印之字形矩阵

准备指向左上角开始位置的A点和B点,确定行列边界条件,A点先向右移动一步,B点就向下移动一步,每次AB形成一条斜线,A直到不能向右,就往下,B直到不能向下就向右,最后控制A,B一个不越界就行,加一个控制打印方向的变量,每次AB形成斜线时更新变量,就能做到之字形打印

package com.zzf.algorithm;

/**
 * @author zzf
 * @date 2022-02-09
 */
public class ZigZagPrintMatrix {

    public static void printMatrixZigZag(int[][] matrix){
        int AR = 0;
        int AC = 0;
        int BR = 0;
        int BC = 0;
        int endR = matrix.length - 1;
        int endC = matrix[0].length - 1;
        boolean fromUp = false;
        while(AR != endR +1){
            //打印
            printLevel(matrix,AR,AC,BR,BC,fromUp);
            //统一动的放后
            //A向右移动直到最后一列就向下
            AR = AC == endC ? AR + 1 : AR;
            AC = AC == endC ? AC : AC + 1;
            //B向下移动直到最后一行就向右
            BC = BR == endR ? BC + 1 : BC;
            BR = BR == endR ? BR : BR + 1;
            fromUp = !fromUp;
        }
        System.out.println();
    }

    public static void printLevel(int[][] m,int AR,int AC,int BR,int BC,boolean f){
        //从上往下打印
        if(f){
            while (AR != BR + 1){
                System.out.print(m[AR++][AC--] + " ");
            }

        }
        //从下往上打印
        else{
            while (BR != AR - 1){
                System.out.print(m[BR--][BC++] + " ");
            }
        }
    }

    public static void main(String[] args) {
        int[][] matrix = { { 1, 2, 3, 4 }, { 5, 6, 7, 8 }, { 9, 10, 11, 12 } };
        printMatrixZigZag(matrix);

    }
}

在这里插入图片描述

转圈打印矩阵

思路:准备标记左上角行列和右下角行列的变量,每次打印一条边,从最上条边开始,先向右打印,直到遇到右上角,就向下打印,直到遇到右下角,就向左打印,直到遇到左上角,要注意只有一行或只有一列的特殊情况,按圈打印,由外到内

package com.zzf.algorithm;

/**
 * @author zzf
 * @date 2022-02-09
 */
public class PrintMatrixSpiralOrder {

    public static void spiralOrderPrint(int[][] matrix){
        int tR = 0;
        int tC = 0;
        int dR = matrix.length - 1;
        int dC = matrix[0].length - 1;
        while (tR <= dR && tC <= dC){
            printEdge(matrix,tR++,tC++,dR--,dC--);
        }
    }
    /**
     *
     * @param m
     * @param tR:左上角行
     * @param tC:左上角列
     * @param dR:右下角行
     * @param dC:右下角列
     */
    public static void printEdge(int[][] m,int tR,int tC,int dR,int dC){
        if(tR == dR){ //只有一行的情况
            for (int i = tC; i <= dC; i++) {
                System.out.print(m[tR][i] + " ");
            }
        }
        else if(tC == dC){ //只有一列的情况
            for (int i = tR; i <= dR; i++) {
                System.out.print(m[i][tC] + " ");
            }
        }else {
            //当前列和当前行
            int curC = tC;
            int curR = tR;
            while(curC != dC){
                System.out.print(m[curR][curC] + " ");
                curC++;
            }
            while (curR != dR){
                System.out.print(m[curR][curC] + " ");
                curR++;
            }
            while (curC != tC){
                System.out.print(m[curR][curC] + " ");
                curC--;
            }
            while (curR != tR){
                System.out.print(m[curR][curC] + " ");
                curR--;
            }
        }
    }
    public static void main(String[] args) {
        int[][] matrix = { { 1, 2, 3, 4 }, { 5, 6, 7, 8 }, { 9, 10, 11, 12 },
                { 13, 14, 15, 16 } };
        spiralOrderPrint(matrix);

    }
}

在这里插入图片描述

顺时针原地旋转正方形矩阵90度

思路:按圈处理,从外到内旋转,把一圈的左上角,右上角,右下角,左下角归为4个小组,而且是依次作为一条边起始,旋转就是依次交换这几个位置,而且通过观察,一条边上,以最上面的边的小组为例,要交换的个数=右上角列位置-左上角列位置-1,减1是不包括右上角位置,旋转完一圈后整体缩小到内一圈,一直循环下去,直到把整个正方形矩阵旋转完毕

package com.zzf.algorithm;

/**
 * @author zzf
 * @date 2022-02-09
 */
public class RotateMatrix {


    public static void rotate(int[][] matrix){
        int a = 0;
        int b = 0;
        int c = matrix.length - 1;
        int d = matrix[0].length - 1;
        while(a < c){
            rotateEdge(matrix,a++,b++,c--,d--);
        }
    }
    public static void rotateEdge(int[][] m,int a,int b,int c,int d){
        int tmp = 0;
        for(int i = 0; i< d - b; i++){
            tmp = m[a][b+i];
            //左下角到左上角
            m[a][b+i] = m[c - i][b];
            //右下角到左下角
            m[c - i][b] = m[c][d - i];
            //右上角到右下角
            m[c][d - i] = m[a + i][d];
            //左上角到右上角
            m[a + i][d] = tmp;
        }
    }

    public static void printMatrix(int[][] matrix){
        for (int i = 0; i < matrix.length; i++) {
            for (int j = 0; j < matrix[0].length; j++) {
                System.out.print(matrix[i][j] + " ");
            }
            System.out.println();
        }
    }

    public static void main(String[] args) {
        int[][] matrix = { { 1, 2, 3, 4 }, { 5, 6, 7, 8 }, { 9, 10, 11, 12 }, { 13, 14, 15, 16 } };
        printMatrix(matrix);
        rotate(matrix);
        System.out.println("=========");
        printMatrix(matrix);
    }
}

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值