《剑指offer第2版》Java题解总结(上)

03-19
20-39《剑指offer第2版》Java题解总结(中)_科技小猎豹的博客-CSDN博客
40-68《剑指offer第2版》Java题解总结(下)-CSDN博客

03-19

03. 数组中重复的数字

数组元素交换。时间On,空间O1.

剑指Offer系列(java版,详细解析) 03. 数组中重复的数字_Hi丶ImViper的博客-CSDN博客

三种语言题解:https://github.com/doocs/leetcode/blob/main/lcof/%E9%9D%A2%E8%AF%95%E9%A2%9803.%20%E6%95%B0%E7%BB%84%E4%B8%AD%E9%87%8D%E5%A4%8D%E7%9A%84%E6%95%B0%E5%AD%97/README.md

04.二维数组中的查找

本题与力扣 240 题同

法二:从左下角或右上角搜索。时间复杂度 O(m+n),空间复杂度 O(1)。为矩阵的行数、列数。

leetcode/lcof/面试题04. 二维数组中的查找 at main · doocs/leetcode · GitHub

05.替换空格

自己遍历比replace()更快

06.从尾到头打印链表

剑指Offer系列(java版,详细解析)06.从尾到头打印链表_Hi丶ImViper的博客-CSDN博客

头插法、栈、递归多种方法。

07. 重建二叉树        本题与主站 105 题重复

测试用例
普通二叉树(完全二叉树;不完全二叉树)
特殊二叉树(所有节点都没有右子节点的二叉树;所有节点都没有左子节点的二叉树;只有一个节点的二叉树)
特殊输入测试(二叉树的根节点为空;输入的前序序列和中序序列不匹配)

力扣只适用于无重复节点二叉树。分治

08.二叉树的下一个节点

中序遍历

09.用两个栈实现队列

leetcode/lcof/面试题09. 用两个栈实现队列 at main · doocs/leetcode · GitHub

10-I.斐波那契数列问题

动态规划力扣

10- II. 青蛙跳台阶问题

11. 旋转数组的最小数字     与主站 154 题相同

力扣

12. 矩阵中的路径( DFS + 剪枝

 力扣​​​​​​

class Solution {
    public boolean exist(char[][] board, String word) {
        char[] words = word.toCharArray();

        // 遍历图
        for(int i = 0; i < board.length; i++) {
            for(int j = 0; j < board[0].length; j++) {

                // 如果找到了,就返回true。否则继续找
                if(dfs(board, words, i, j, 0)) return true;
            }
        }

        // 遍历结束没找到false
        return false;
    }
    boolean dfs(char[][] board, char[] word, int i, int j, int k) {
        // 判断传入参数的可行性 i 与图行数row比较,j与图列数col比较
        // i,j初始都是0,都在图左上角
        // k是传入字符串当前索引,一开始是0,如果当前字符串索引和图当前索引对应的值不相等,表示第一个数就不相等
        // 所以继续找第一个相等的数。题目说第一个数位置不固定,即路径起点不固定(不一定是左上角为第一个数)

        // 如果board[i][j] == word[k],则表明当前找到了对应的数,就继续执行(标记找过,继续dfs 下上右左)
        if(i >= board.length || i < 0 || j >= board[0].length || j < 0 || board[i][j] != word[k]) return false;
        // 表示找完了,每个字符都找到了
        // 一开始k=0,而word.length肯定不是0,所以没找到,就执行dfs继续找。
        if(k == word.length - 1) return true;   

        // 访问过的标记空字符串,“ ”是空格 '\0'是空字符串,不一样的!
        // 比如当前为A,没有标记找过,且A是word中对应元素,则此时应该找A下一个元素,假设是B,在dfs(B)的时候还是-
        // ->要搜索B左边的元素(假设A在B左边),所以就是ABA(凭空多出一个A,A用了2次,不可以),如果标记为空字符串->
        // 就不会有这样的问题,因为他们值不相等AB != ABA。 
        board[i][j] = '\0';

        // 顺序是 下 上 右 左;上面找到了对应索引的值所以k+1
        boolean res = dfs(board, word, i + 1, j, k + 1) || dfs(board, word, i - 1, j, k + 1) || 
                      dfs(board, word, i, j + 1, k + 1) || dfs(board, word, i , j - 1, k + 1);
        
        // 还原找过的元素,因为之后可能还会访问到(不同路径)
        board[i][j] = word[k];

        // 返回结果,如果false,则if(dfs(board, words, i, j, 0)) return true;不会执行,就会继续找
        return res;
    }
}

13.机器人的运动范围

数位和增量公式: 力扣
以下代码为增量公式的三元表达式写法,将整合入最终代码中。

(x + 1) % 10 != 0 ? s_x + 1 : s_x - 8;

14- I. 剪绳子    与主站 343 题相同

动规、数学等等力扣

关于为什么切分为3的优先级最高 可以利用均值不等式求出乘积最大值 L(m)=(n/m)^m 对此式求导(可利用对数法),可以证明当 m=n/e 时,乘积取最大,此时每段绳子的长度为 n/(n/e)=e,自然对数e的值为2.718,显然接近3,所以总体来讲3最好

class Solution {
    public int cuttingRope(int n) {
        if(n <= 3) return n - 1;
        int a = n / 3, b = n % 3;
        if(b == 0) return (int)Math.pow(3, a);
        if(b == 1) return (int)Math.pow(3, a - 1) * 4;
        return (int)Math.pow(3, a) * 2;
    }
}

14- II. 剪绳子 II       大数越界情况下的求余问题

力扣大数求余!力扣

class Solution {
    public int cuttingRope(int n) {
        if(n == 2) return 1;
        if(n == 3) return 2;

        int a = n / 3;
        int b = n % 3;
        // ans * 3 可能在求余之前超出int32的值,所以用long类型
        long ans = 1;
        switch(b) {
            case 0 :
                for(int i = 0; i < a; i++) {
                    ans = ans * 3 % 1000000007 ;
                }
            break;
            case 1 :
                for(int i = 0; i < a - 1; i++) {
                    ans = ans * 3 % 1000000007 ;
                }
                ans = ans * 4  % 1000000007;
            break;
            case 2 :
                for(int i = 0; i < a; i++) {
                    ans = ans * 3 % 1000000007 ;
                }
                ans = ans * 2  % 1000000007;
            break; 
        }
        return (int)ans;
    }
}

15. 二进制中1的个数

力扣,=主站191力扣

public int hammingWeight(int n) {
        int res = 0;
        while(n != 0) {
            res += n & 1;
            n >>>= 1;
        }
        return res;
    }

16. 数值的整数次方

与主站 50 题相同:力扣

快速幂(数论),在普通计算机内,数是用补码表示滴,而这里b = -b 和 b = -n就隐藏着这个坑。int由于补码无法表示+2147483648。b不能用-n赋值,必须用-b 因为b是long的 可以表示+2147483648

力扣K佬题解

17. 打印从1到最大的n位数

String表示大数,全排列dfs。

Integer.parseInt这个接口,会自动把整数前面的0去掉。(此法速度慢)

class Solution {
    char[] num;
    int[] ans;
    int count = 0,n;
    public int[] printNumbers(int n) {
        this.n = n;
        num = new char[n];
        ans = new int[(int) (Math.pow(10, n) - 1)];
        dfs(0);
        return ans;
    }
    private void dfs(int n) {
        if (n == this.n) {
            String tmp = String.valueOf(num);
            int curNum = Integer.parseInt(tmp);
            if (curNum!=0) ans[count++] = curNum;
            return;
        }
        for (char i = '0'; i <= '9'; i++) {
            num[n] = i;
            dfs(n + 1);
        }
    }
}

18. 删除链表的节点

注意各种特殊情况、限制条件。

public ListNode deleteNode(ListNode head, int val) {
        if(head.val == val) return head.next;
        ListNode pre = head, cur = head.next;
        while(cur != null && cur.val != val) {
            pre = cur;
            cur = cur.next;
        }
        if(cur != null) pre.next = cur.next;
        return head;
    }

19. 正则表达式匹配

hard,动规or递归

class Solution {
    public boolean isMatch(String A, String B) {
        int n = A.length();
        int m = B.length();
        boolean[][] f = new boolean[n + 1][m + 1];

        for (int i = 0; i <= n; i++) {
            for (int j = 0; j <= m; j++) {
                //分成空正则和非空正则两种
                if (j == 0) {
                    f[i][j] = i == 0;
                } else {
                    //非空正则分为两种情况 * 和 非*
                    if (B.charAt(j - 1) != '*') {
                        if (i > 0 && (A.charAt(i - 1) == B.charAt(j - 1) || B.charAt(j - 1) == '.')) {
                            f[i][j] = f[i - 1][j - 1];
                        }
                    } else {
                        //碰到 * 了,分为看和不看两种情况
                        //不看
                        if (j >= 2) {
                            f[i][j] |= f[i][j - 2];
                        }
                        //看
                        if (i >= 1 && j >= 2 && (A.charAt(i - 1) == B.charAt(j - 2) || B.charAt(j - 2) == '.')) {
                            f[i][j] |= f[i - 1][j];
                        }
                    }
                }
            }
        }
        return f[n][m];
    }
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值