写算法题目时,java的单目运算符 ++,-- 学习

本文介绍了一个二维数组查找算法,该数组每一行和每一列都按升序排列。文章提供了多种实现方式,包括从右上角开始的递归和循环方法,并详细解释了如何避免栈溢出错误。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

今日写一个算法题目:二维数组中的查找(剑指Offer题目)

题目:在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。

如:

 

找数据10,返回为true,且位于第三行第三列

考虑从右上角开始,用递归的方法找:

代码如下:

public class Test {
    public static void main(String[] args) {
        int[][] matrix = new int[][]{{1, 2, 8, 9}, {2, 4, 9, 12}, {4, 7, 10, 13}, {6, 8, 11, 15}};
        System.out.println("从右上角开始,递归方法找数据: " + (10) + "是否找到: " + findDataRecursively(matrix, 10));
    }

    /*  从右上角开始,递归*/
    public static boolean findDataRecursively(int[][] matrix, int number) {
        if (matrix == null || matrix.length < 1 || matrix[0].length < 1) {
            return false;
        }
        return find(matrix, number, 0, matrix.length - 1);
    }

    public static boolean find(int[][] matrix, int number, int row, int column) {
        if (row >= matrix.length || column < 0) {
            return false;
        }
        int currentData = matrix[row][column];
        if (currentData == number) {
            System.out.println("找到数据,在第 " + (row + 1) + " 行,第 " + (column + 1) + " 列");
            return true;
        } else if (currentData < number) {
            return find(matrix, number, row--, column);//1
        } else {
            return find(matrix, number, row, column++);//2
        }
    }
}

执行程序,程序结果如下:

Exception in thread "main" java.lang.StackOverflowError
	at 第二遍.Test.find(Test.java:30)
	at 第二遍.Test.find(Test.java:30)
	at 第二遍.Test.find(Test.java:30)
        ...

Process finished with exit code 1

看一遍程序的执行过程,没有异常,都是按照顺序执行的,后来debug一下,发现程序执行到 1 处,递归执行时,row并没有减一,导致每次执行递归,传入的参数一样,程序一直递归,导致虚拟机栈溢出。想到,++、--操作是在执行完毕之后才会++、--。即 前++是先自加再使用,而后++是先使用再自加。

比如:

 执行结果
int age=18; 
int num=age++;num=18,age=19
int num=++age;num=19,age=19
int num=age--;num=18,  age=17
int num=--age;num=17,  age=17

 

所以后来改下代码:将1、2处的代码改为--row、++column即可

public class Test {
    public static void main(String[] args) {
        int[][] matrix = new int[][]{{1, 2, 8, 9}, {2, 4, 9, 12}, {4, 7, 10, 13}, {6, 8, 11, 15}};
        System.out.println("从右上角开始,递归方法找数据: " + (10) + "是否找到: " + findDataRecursively(matrix, 10));
    }

    /*  从右上角开始,递归*/
    public static boolean findDataRecursively(int[][] matrix, int number) {
        if (matrix == null || matrix.length < 1 || matrix[0].length < 1) {
            return false;
        }
        return find(matrix, number, 0, matrix.length - 1);
    }

    public static boolean find(int[][] matrix, int number, int row, int column) {
        if (row >= matrix.length || column < 0) {
            return false;
        }
        int currentData = matrix[row][column];
        if (currentData == number) {
            System.out.println("找到数据,在第 " + (row + 1) + " 行,第 " + (column + 1) + " 列");
            return true;
        } else if (currentData < number) {
            return find(matrix, number, --row, column);//1
        } else {
            return find(matrix, number, row, ++column);//2
        }
    }
}

执行结果:

找到数据,在第 3 行,第 3 列
从右上角开始,递归方法找数据: 10是否找到: true

Process finished with exit code 0

后来继续写了,所有的实现方法如下:

    /* 1.1 从右上角开始,递归*/
    public static boolean findDataRightRecursively(int[][] matrix, int number) {
        if (matrix == null || matrix.length < 1 || matrix[0].length < 1) {
            return false;
        }
        return findRight(matrix, number, 0, matrix.length - 1);
    }

    public static boolean findRight(int[][] matrix, int number, int row, int column) {
        if (row >= matrix.length || column < 0) {
            return false;
        }
        int currentData = matrix[row][column];
        if (currentData == number) {
            System.out.println("找到数据" + number + "在第 " + (row + 1) + " 行,第 " + (column + 1) + " 列");
            return true;
        } else if (currentData < number) {
            return findRight(matrix, number, ++row, column);
        } else {
            return findRight(matrix, number, row, --column);
        }
    }

    /* 1.2 从右上角开始,循环*/
    public static boolean findDataRightCircularly(int[][] matrix, int number) {
        if (matrix == null || matrix.length < 1) {
            return false;
        }
        int row = 0;
        int column = matrix[0].length - 1;
        while (row < matrix.length && column >= 0) {
            int currentData = matrix[row][column];
            if (currentData == number) {
                System.out.println("找到数据,在第 " + (row + 1) + " 行,第 " + (column + 1) + " 列");
                return true;
            } else if (currentData < number) {
                row++;
            } else {
                column--;
            }
        }
        return false;
    }

    /* 2.1 从左下角开始,递归*/
    public static boolean findDataLeftRecursively(int[][] matrix, int number) {
        if (matrix == null || matrix.length < 1 || matrix[0].length < 1) {
            return false;
        }
        return findLeft(matrix, number, matrix.length - 1, 0);
    }

    public static boolean findLeft(int[][] matrix, int number, int row, int column) {
        if (row >= matrix.length || column < 0) {
            return false;
        }
        int currentData = matrix[row][column];
        if (currentData == number) {
            System.out.println("找到数据: " + number + " 在第 " + (row + 1) + " 行,第 " + (column + 1) + " 列");
            return true;
        } else if (currentData < number) {
            return findLeft(matrix, number, row, ++column);
        } else {
            return findLeft(matrix, number, --row, column);
        }
    }

    /* 2.2 从左下角开始,循环*/
    public static boolean findDataLeftCircularly(int[][] matrix, int number) {
        if (matrix == null || matrix.length < 1) {
            return false;
        }
        int row = matrix.length - 1;
        int column = 0;
        while (row >= 0 && column < matrix.length) {
            int currentData = matrix[row][column];
            if (currentData == number) {
                System.out.println("找到数据: " + number + " 在第 " + (row + 1) + " 行,第 " + (column + 1) + " 列");
                return true;
            } else if (currentData < number) {
                ++column;
            } else {
                --row;
            }
        }
        return false;
    }

总结:以后写代码注意,只有必须后加时,把++写后面,其他写前面,养成这个习惯。细节毁所有。

java代码实验 2:编递归下降语法分析器 本实验进行递归下降语法分析器的编程与调试。 3.2.1 实验类型 验证型实验 3.2.2 实验目的和要求 通过设计、编制、调试一个递归下降语法分析程序,实现对词法分析程序所提供的单 词序列进行语法检查和结构分析,掌握常用的语法分析方法。通过本实验,应达到以下目 标: 1、掌握从源程序文件中读取有效字符的方法和产生源程序的内部表示文件的方法。 2、掌握词法分析的实现方法。 3、上机调试编出的语法分析程序。 3.2.3 背景知识 递归下降分析程序实现思想简单易懂。程序结构和语法产生式有直接的对应关系。因 为每个过程表示一个非终结符号的处理,添加语义加工工作比较方便。 递归下降分析程序的实现思想是:识别程序由一组子程序组成。每个子程序对应于一 个非终结符号。 每一个子程序的功能是:选择正确的右部,扫描完相应的字。在右部中有非终结符号 ,调用该非终结符号对应的子程序来完成。 自上向下分析过程中,如果带回溯,则分析过程是穷举所有可能的推导,看是否能推 导出待检查的符号串。分析速度慢。而无回溯的自上向下分析技术,当选择某非终结符的 产生,可根据输入串的当前符号以及各产生式右部首符号而进行,效率高,且不易出错。 无回溯的自上向下分析技术可用的先决条件是:无左递归和无回溯。 无左递归:既没有直接左递归,也没有间接左递归。 无回溯:对于任一非终结符号 U 的产生式右部 x1|x2|…|xn,其对应的字的首终结符号 两两不相交。 如果一个文法不含回路(形如 P⇒ + P 的推导),也不含以 ε 为右部的产生式,那么可 以通过执行消除文法左递归的算法消除文法的一切左递归(改后的文法可能含有以 ε 为 右部的产生式)。 文法的左递归消除算法: 1、将文法 G 的所有非终结符排序为 U1 ,U2 ,… ,Un; 2、For(i=1;i++;i≥n) { for j→1 to i-1 把产生式 Ui→Ujα 替换成 Ui→β1α| β2α|…|βmα; 其中:Uj→ β1| β2 |… |βm 消除 Ui 产生式中的直接左递归; } 3、化简改之后的文法,删除多余产生式。 17 文法的直接左递归消除公式: 直接左递归形式:U→Ux|y; 其中:x,y∈(VN∪VT)* ,y 不以 U 打头。 直接左递归的消除: U→yU‟ U‟→xU‟|ε 直接左递归的一般形式:U→Ux1|Ux2|…|Uxm|y1|y2|…|yn; 其中:xi≠ε ,yi都不以 U 打头。 一般形式直接左递归的消除: U→y1U‟| y2U‟ |…| ynU‟ U‟→x1U‟| x2U‟| …| xmU‟|ε 回溯的消除的前提是文法不得含有左递归,可提左因子来消除回溯。 递归下降分析程序的基本架构如下的法: 先定义: 变量:ch:当前符号; 函数:READ(ch):读输入串下一符号; 对于每个非终结符号 U→α 1|α 2|…|α n处理的方法如下: P(U) { if ch∈FIRST(α1 ) then P(α1) //处理 α1 的程序部分。 else if ch∈FIRST(α2 ) then P(α2) //处理 α2 的程序部分。 … else if ch∈FIRST(αn ) then P(αn) else if ch∈FOLLOW(U) then return //处理空产生式情况。 else error } 对于每个右部 α =x1x2…xn的处理架构如下: P(α ) { P(x1 ); //处理 x1 的程序。 P(x2 ); //处理 x2 的程序。 … … … P(xn ); //处理 xn的程序。 } 对于右部中的每个符号 xi; 如果 xi为终结符号: if(ch= =a) READ (ch) //对于终结符,直接将指针前调。 else 18 error 如果 xi为非终结符号,直接调用相应的过程:p (xi)。 3.2.4 实验内容 1、分析对象 分析算术表达式的 BNF 定义如下: 〈算术表达式〉→〈项〉|〈算术表达式〉+〈项〉|〈算术表达式〉-〈项〉 〈项〉→〈因式〉|〈项〉*〈因式〉|〈项〉/〈因式〉 〈因式〉→〈变量〉│(〈算术表达式〉) 〈变量〉→i 用符号表示如下: E→T|E+T|E-T T→F|T*F|T/ F→i│(E) 2、题目: 编递归下降语法分析器。 3、要求: 根据递归下降法分析法,完成上述算术表达式的分析器构造。主要完成: (1) 通知外界键入算术表达式; (2) 控制过程分析算术表达式; (3) 根据分析结果正误,分别通知外界不同的信息。
最新发布
06-07
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值