【Java版本】剑指offer所有面试题(完整版题解2)

33 篇文章 1 订阅
29 篇文章 3 订阅

剑指offer 11-20题

第十一题-斐波契那数列

image-20220412082937474

public class Test09 {
    public static int F(int n){
        if(n <= 0) return 0;
        if(n == 1 || n ==2) return 1;
        int[] dp = new int[n+1];
        dp[1] = 1;
        dp[2] = 1;
        for(int i =3;i<=n;i++){
            dp[i] = dp[i-1]+dp[i-2];
        }
        return dp[n];
    }

    public static void main(String[] args) {
        System.out.println(F(0));
        System.out.println(F(1));
        System.out.println(F(2));
        System.out.println(F(3));
        System.out.println(F(4));
        System.out.println(F(5));
        System.out.println(F(6));
        System.out.println(F(7));

    }
}

第十二题-矩阵中的路径

image-20220422084716094

import java.lang.reflect.Array;
import java.util.Arrays;

public class Test12_1 {
    /**
     *
     * @param matrix 输入的矩阵
     * @param row 行
     * @param col 列
     * @param str 要搜索的字符
     * @return
     */
    public static  boolean hasPath(char[] matrix,int row,int col,char[] str){
        if (matrix == null || matrix.length != row*col ||str == null || str.length == 0) return  false;

        boolean[] visited = new boolean[row*col];
        Arrays.fill(visited,false);

        //结果记录
        int[] pathLength = {0};
        //以每一个点为起点进行搜索
        for (int i = 0; i< row;i++){
            for (int j = 0; j<col;j++){
                if (hasPathCore(matrix,row,col,str,visited,i,j,pathLength)){
                    return true;
                }
            }
        }
        return false;
    }

    /**
     *
     * @param matrix 输入的矩阵
     * @param rows 行
     * @param cols 列
     * @param str 要寻找的字符
     * @param visited 是否遍历过
     * @param currow 当前处理的行号
     * @param curcol 当前处理的行号
     * @param pathLength 已处理的str中字符的个数
     * @return
     */
    public static boolean hasPathCore(char[] matrix, int rows, int cols, char[] str, boolean[] visited,
                                      int currow, int curcol, int[] pathLength){
        if (pathLength[0] == str.length) return true;
        boolean haspath = false;
        //当前行大于0且小于总行数,当前列大于0且小于总列数,当前字符 == 要处理的字符 没有遍历过当前字符
        if (currow >= 0 && currow<rows && curcol >=0 && curcol < cols && matrix[currow*cols+curcol]  == str[pathLength[0]] && !visited[currow*cols+curcol]){
            visited[currow * cols + curcol] = true;
            pathLength[0]++;

            //回溯
            haspath = hasPathCore(matrix,rows,cols,str,visited,currow,curcol+1,pathLength) ||
                    hasPathCore(matrix,rows,cols,str,visited,currow+1,curcol,pathLength) ||
                    hasPathCore(matrix,rows,cols,str,visited,currow,curcol-1,pathLength) ||
                    hasPathCore(matrix,rows,cols,str,visited,currow-1,curcol,pathLength);
            if (!haspath){
                pathLength[0] --;
                visited[currow*cols+curcol] = false;
            }
        }
        return haspath;
    }

    public static void main(String[] args) {
        //ABCE  //ABCCED
        //SFCS
        //ADEE
        System.out.println(hasPath("ABCESFCSADEE".toCharArray(), 3, 4,
                "ABCCED".toCharArray()) );// true
    }
}

第十三题-机器人的运动范围

image-20220422092712410

import java.lang.reflect.Array;
import java.util.Arrays;

public class Test13_1 {
    /**
     *
     * @param threshold 约束值
     * @param rows 行数
     * @param cols 列数
     * @return
     */
    public static int movingCount(int threshold, int rows, int cols){
        if(threshold< 0 ||rows < 1 ||cols < 1) return  0;
        //变量初始化
        boolean[] visited = new boolean[rows*cols];
        Arrays.fill(visited,false);
        return movingCountCore(threshold,rows,cols,0,0,visited);

    }

    /**
     *
     * @param threshold
     * @param rows
     * @param cols
     * @param currow 当前行
     * @param curcol 当前列
     * @param visited 是否被访问过
     * @return
     */
    public static int movingCountCore(int threshold, int rows, int cols,
                                      int currow, int curcol, boolean[] visited){
        int count = 0;
        if (check(threshold,rows,cols,currow,curcol,visited)){
            visited[currow*cols+curcol] = true;
            count = 1+movingCountCore(threshold,rows,cols,currow+1,curcol,visited) +
                    movingCountCore(threshold,rows,cols,currow,curcol+1,visited) +
                    movingCountCore(threshold,rows,cols,currow-1,curcol,visited) +
                    movingCountCore(threshold,rows,cols,currow,curcol-1,visited);
        }
        return count;
    }

    /**
     * 断机器人能否进入坐标为(row, col)的方格
     *
     * @param threshold 约束值
     * @param rows      方格的行数
     * @param cols      方格的列数
     * @param currow    当前处理的行号
     * @param curcol    当前处理的列号
     * @param visited   访问标记数组
     * @return 是否可以进入,true是,false否
     */
    public static boolean check(int threshold, int rows, int cols,
                                int currow, int curcol, boolean[] visited){
        return curcol >= 0 && curcol < cols && currow >= 0 && currow < rows && !visited[currow*cols+curcol]
                &&(getDigitSum(curcol) + getDigitSum(currow) <= threshold);
    }

    /**
     * 一个数字的数位之和
     * @param number 数字
     * @return 数字的数位之和
     */
    private static int getDigitSum(int number) {
        int result = 0;
        while (number > 0) {
            result += (number % 10);
            number /= 10;
        }

        return result;
    }

    public static void main(String[] args) {
        System.out.println(movingCount(5, 10, 10) );
        System.out.println(movingCount(15, 20, 20) );
    }
}

第十四题-剪绳子

image-20220422094805048

import  java.util.*;
public class Test14_1 {
    public static int maxProductAfterCutting_1(int length){
        if (length == 3) return 3;
        if (length == 2) return 1;
        if (length < 2) return 0;

        int[] dp = new int[length+1];
        dp[0] = 0;
        dp[1] = 1;
        dp[2] = 2;
        dp[3] = 3;

        int max = 0;
        for (int i = 4;i<=length;i++){
            max = 0;
            for(int j = 1; j<= i/2;j++){
                int temp = dp[j] * dp[i-j];
                if (temp > max) max = temp;
                dp[i] = max;
            }
        }
        max = dp[length];
        return max;

    }

    public static int maxProductAfterCutting_2(int length){
        if (length == 3) return 3;
        if (length == 2) return 2;
        if (length < 2) return 0;

        //尽可能的剪长度为3的长度
        int timeof3 = length /3;
        if (length - timeof3*3 == 1)   timeof3 -= 1;
        int timeof2 = (length-timeof3*3)/2;
        return (int)Math.pow(3,timeof3) * (int)Math.pow(2,timeof2);
    }

    public static void main(String[] args) {
        System.out.println(maxProductAfterCutting_1(5));
        System.out.println(maxProductAfterCutting_2(5));
    }
}

第十五题:二进制中1的个数

image-20220412083734045

public class Test10 {
    public static int numberofone(int n){
        int res =0;
        while(n!=0){
            res += (n&1);
            n >>>= 1;
        }
        return  res;
    }
    public static  int numberofone1(int n){
        int res = 0;
        while(n!=0){
            res ++;
            n = (n-1)&n;
        }
        return res;
    }

    public static void main(String[] args) {
        System.out.println(numberofone(0B00000000_00000000_00000000_00000000)); // 0
        System.out.println(numberofone(0B00000000_00000000_00000000_00000001)); // 1
        System.out.println(numberofone(0B11111111_11111111_11111111_11111111)); // -1
        System.out.println(0B01111111_11111111_11111111_11111111 == Integer.MAX_VALUE);
        System.out.println(numberofone(0B01111111_11111111_11111111_11111111)); // Integer.MAX_VALUE
        System.out.println(0B10000000_00000000_00000000_00000000 == Integer.MIN_VALUE);
        System.out.println(numberofone(0B10000000_00000000_00000000_00000000)); // Integer.MIN_VALUE

        System.out.println("");
        System.out.println(numberofone1(0B00000000_00000000_00000000_00000000)); // 0
        System.out.println(numberofone1(0B00000000_00000000_00000000_00000001)); // 1
        System.out.println(numberofone1(0B11111111_11111111_11111111_11111111)); // -1
        System.out.println(numberofone1(0B01111111_11111111_11111111_11111111)); // Integer.MAX_VALUE
        System.out.println(numberofone1(0B10000000_00000000_00000000_00000000)); // Integer.MIN_VALU
    }

}

第十六题-数值的整数次方

image-20220412091448388

public class Test11 {
    public static double power(double base,int e){
        if(base == 0 && e== 0) throw new RuntimeException("invalid");
        //指数为0
        if(e == 0) return 1;
        //指数为1
        if(e == 1) return base;
        //求指数的绝对值
        int exp = e;
        if(exp < 0){
            exp = -exp;
        }
        double res = powerWithUnsigned(base,exp);
        if(e < 0){
            res = 1/res;
        }
        return res;

    }
    public static double powerWithUnsigned(double base,int e){
        if(e == 0) return 1;
        if(e == 1) return base;
        double res = powerWithUnsigned(base,e>>1);
        res = res*res;
        if(e % 2 !=0) //如果是奇数还需要在×一个base
            res *= base;
        return  res;
    }
    public static void main(String[] args) {

        System.out.println(power(2, -4));
        System.out.println(power(2, 4));
        System.out.println(power(2, 0));
        System.out.println(power(0.0000000000000000000001, -1));
        System.out.println(power(0.0000000000000000000001, 1));
        System.out.println(power(0.0000000000000000000001, 0));
        System.out.println(power(0.0000000000000000000000, 0));
    }
}

第十七题-打印1到最大的n位数

image-20220412093040137

import java.util.Arrays;

public class Test12 {

    //打印1到最大的n位数的主方法
    public static void printToMaxOfDigits(int n){
        if(n <= 0){
            System.out.println("invalid");
            return;
        }
        char number[] = new char[n];
        Arrays.fill(number,'0');//数组全部填充为0
        for (int i = 0; i < 10; ++i) {
            number[0] = (char) (i + '0');//首位数字
            printToMaxOfNDigitsRecursively(number, n, 0);
        }
    }
    //利用递归实现1到最大的n位数的全排列
    public static void printToMaxOfNDigitsRecursively(char[] number, int n, int index) {
        if(index == n - 1){//到了最后一位,当前首位数字的全排列结束
            printNumber(number);//打印
            return;
        }
        for (int i = 0; i < 10; ++i) {
            number[index + 1] = (char) (i + '0');//进行全排列
            printToMaxOfNDigitsRecursively(number, n, index + 1);
        }
    }

    //输出
    private  static void printNumber(char[] number) {
        boolean falg = true;
        int nLength = number.length;
        for (int i = 0; i < nLength; ++i) {
            if(falg && number[i]!='0'){//防止首位为0
                falg = false;
            }
            if(!falg){
                System.out.print(number[i]);
            }
        }
        System.out.println();
    }

    public static void main(String[] args) {
        printToMaxOfDigits(2);
    }
}

第十八题-在O(1)时间删除链表节点

image-20220412102017606

public class Test13 {
    public static ListNode deleteNode(ListNode head,ListNode delNode){
        if(head == null || delNode == null) return head;
        if(head == delNode) return head.next;
        if(delNode.next == null){
            ListNode temp = head;
            while(temp.next != delNode){
                temp = temp.next;
            }
            temp.next = null;
        }else{
            delNode.val = delNode.next.val;//把后一个节点值传给待删除节点
            delNode.next = delNode.next.next; //把后一个节点删除
        }
        return head;
    }

    public static void print(ListNode head){
        ListNode temp = head;
        while(temp!=null) {
            System.out.print(temp.val + " ");
            temp = temp.next;
        }
        System.out.println();
    }
    public static void main(String[] args) {


        ListNode head = new ListNode();
        head.val = 1;

        head.next = new ListNode();
        head.next.val = 2;

        head.next.next = new ListNode();
        head.next.next.val = 3;

        head.next.next.next = new ListNode();
        head.next.next.next.val = 4;

        ListNode middle = head.next.next.next.next = new ListNode();
        head.next.next.next.next.val = 5;

        head.next.next.next.next.next = new ListNode();
        head.next.next.next.next.next.val = 6;

        ListNode last =  head.next.next.next.next.next.next = new ListNode();
        head.next.next.next.next.next.next.val = 7;
        

        head = deleteNode(head, null); // 删除的结点为空
        print(head);
        ListNode node = new ListNode();
        node.val = 12;

        head = deleteNode(head, head); // 删除头结点
        print(head);
        head = deleteNode(head, last); // 删除尾结点
        print(head);
        head = deleteNode(head, middle); // 删除中间结点
        print(head);

        head = deleteNode(head, node); // 删除的结点不在链表中
        print(head);
    }

}

第十九题-正则表达式匹配

image-20220422103050128

public class Test19_1 {
    public static boolean match(String input,String pattern){
        if (input == null || pattern == null) {
            return false;
        }

        return matchCore(input, 0, pattern, 0);
    }
    public static boolean matchCore(String string,int i, String pattern,int p){
        if ( i >= string.length() && p >= pattern.length()) return true;

        if (i != string.length() && p >= pattern.length()) return false;

        //p的下一位置的字符为*
        if (p + 1 < pattern.length() && pattern.charAt(p + 1) == '*') {
            // 匹配串已经结束
            if (i >= string.length()) return matchCore(string,i,pattern,p+2);
            else {
                //匹配串没有结束
                if (pattern.charAt(p) == string.charAt(i) || pattern.charAt(p) == '.') {
                    // 匹配串向后移动一个位置,模式串向后移动两个位置,把p看作出现一次
                    return matchCore(string,i+1,pattern,p+2) ||
                            //匹配串向后移动一个位置,模式串不移动,把p看作多次出现
                            matchCore(string,i+1,pattern,p) ||
                            //匹配串不移动,模式串向后移动两个位置 ,把p看做一次都不出现
                            matchCore(string,i,pattern,p+2);
                }else
                    //如果当前字符和匹配的字符不想等,那么匹配向后移位2个,继续匹配
                    return matchCore(string, i, pattern, p+2);
            }
        }
        // 匹配串已经结束,模式串还没有结束,前面判断了模式串没有结束
        if (i >= string.length()) {
            return false;
        }else {
            //匹配串还未结束,如果当前位置的字符和匹配字符相等,则后一继续匹配
            if (string.charAt(i) == pattern.charAt(p) || pattern.charAt(p) == '.')
                return matchCore(string, i+1, pattern, p+1);
        }
        return false;
    }

    public static void main(String[] args) {
//        System.out.println(match("", "") + "[" + true + "]");
//        System.out.println(match("", ".*") + "[" + false + "]");
//        System.out.println(match("", ".") + "[" + false + "]");
//        System.out.println(match("", "c*") + "[" + true + "]");
//        System.out.println();

        System.out.println(match("aaa", "aab*a"));


    }
}

第二十题-表示数值的字符串

image-20220423091213898

public class Test20_1 {
    public static boolean isNumeric(String string) {
        if (string == null || string.length() < 1) return false;
        int index = 0;
        //先判断整数
        if (string.charAt(index) == '+' || string.charAt(index) == '-') {
            index++;
        }
        //已经到达字符串的末尾
        if (index >= string.length()) return false;

        //判断标准
        boolean numeric = true;
        //找到数字部分的下一个位置
        index = scanDigits(string, index);

        //如果没有到达末尾
        if (index < string.length()) {
            //如果是小数点
            if (string.charAt(index) == '.') {
                index++;
                index = scanDigits(string, index);
                //如果已经达到了字符的末尾
                if (index >= string.length()) numeric = true;
                //如果还没有到达,判断是否为指数
                else if (index < string.length() && (string.charAt(index) == 'e' || string.charAt(index) == 'E'))
                    //判断指数是否合法
                    numeric = isExponential(string,index);
                //不是返回false
                else numeric = false;
            }return numeric;
        }
        else return true;
    }

    //扫描字符串中数字部分
    public static int scanDigits(String string, int index) {
        while (index < string.length() && string.charAt(index) >= '0' && string.charAt(index) <= '9')
            index++;
        return index;
    }

    /**
     * 判断指数部分是否合法
     * @param string
     * @param index
     * @return
     */
    public static boolean isExponential(String string, int index) {
        if (index >= string.length() || (string.charAt(index) != 'e' && string.charAt(index) != 'E')) {
            return false;
        }
        index ++;
        if (index >= string.length()) return  false;

        if (string.charAt(index) == '+' ||string.charAt(index) == '-'){
            index ++;
        }
        if (index >= string.length()) return false;

        index = scanDigits(string,index);

        return index >= string.length();
    }

    public static void main(String[] args) {
        System.out.println(isNumeric("100") + "[" + true + "]");
        System.out.println(isNumeric("123.45e+6") + "[" + true + "]");
        System.out.println(isNumeric("+500") + "[" + true + "]");
        System.out.println(isNumeric("5e2") + "[" + true + "]");
        System.out.println(isNumeric("1.79769313486232E+308") + "[" + true + "]");
        System.out.println(isNumeric("12e") + "[" + false + "]");
        System.out.println(isNumeric("1a3.14") + "[" + false + "]");
        System.out.println(isNumeric("1+23") + "[" + false + "]");
        System.out.println();
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小七rrrrr

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值