剑指offer题目代码总结

剑指 Offer 26. 树的子结构

二叉树匹配类问题总结

B 属于 A 的一部分也可以,没必要一直匹配到叶子节点

递归解法

剑指offer题目代码总结_第1张图片
recur的返回条件:

当节点 B 为空:说明树 B 已匹配完成(越过叶子节点),因此返回 true ;
当节点 A 为空:说明已经越过树 A 叶子节点,即匹配失败,返回 false;

剑指 Offer 28. 对称的二叉树

1.递归解法

剑指offer题目代码总结_第2张图片

2.非递归解法(队列)

剑指offer题目代码总结_第3张图片

剑指 Offer 27. 二叉树的镜像

1.递归解法

剑指offer题目代码总结_第4张图片

2.非递归解法(栈或队列)

​​剑指offer题目代码总结_第5张图片
剑指offer题目代码总结_第6张图片

剑指 Offer 32 - I. 从上到下打印二叉树

非空的不加入队列
剑指offer题目代码总结_第7张图片

非空的也加入队列,出队之后进行判断
剑指offer题目代码总结_第8张图片

剑指 Offer 32 - II. 从上到下打印二叉树 II

队列(BFS)

安安写法
在这里插入图片描述

精选答案写法 就是对null的处理不太一样
剑指offer题目代码总结_第9张图片

递归DFS实现

剑指offer题目代码总结_第10张图片

剑指 Offer 32 - III. 从上到下打印二叉树 III

队列(BFS)

linkedlist首尾添加
在这里插入图片描述
arraylist首尾添加
剑指offer题目代码总结_第11张图片

递归

剑指offer题目代码总结_第12张图片

双栈法

//Java 安安 2020.3.31
//根节点作为第0行 
class Solution {
    public List<List<Integer>> levelOrder(TreeNode root) {   
        List<List<Integer>> res = new ArrayList<>();

        Stack<TreeNode> s1 = new Stack<>();  //存储奇数行
        Stack<TreeNode> s2 = new Stack<>();  //存储偶数行

        if(root != null) s2.push(root);

        while(!s1.empty() || !s2.empty()) {
            List<Integer> tmp = new ArrayList<>();
            if(!s2.empty()){
                while(!s2.empty()){
                    TreeNode p = s2.pop();
                    tmp.add(p.val);
                    if(p.left != null) s1.push(p.left);
                    if(p.right != null) s1.push(p.right);
                }
                res.add(tmp);
            }

            if(!s1.empty()){
                tmp = new ArrayList<>();
                while(!s1.empty()){
                    TreeNode p = s1.pop();
                    tmp.add(p.val);
                    if(p.right != null) s2.push(p.right);
                    if(p.left != null)  s2.push(p.left);
                }         
                res.add(tmp);
            }
        }
        return res;
    }
}

剑指 Offer 30. 包含min函数的栈

同步

剑指offer题目代码总结_第13张图片

不同步

两个 peek() 方法返回的都是 Integer 类型 ,它们的比较不能用 ==,因为 == 用于包装类型(它们都是对象)的比较,比较的是它们的内存地址,解决方法也很简单:(1)改用 equals() 方法,(2)至少把其中一个变量转成 int 型。
剑指offer题目代码总结_第14张图片

剑指 Offer 29. 顺时针打印矩阵

模拟矩阵路径

剑指offer题目代码总结_第15张图片

按层模拟

剑指offer题目代码总结_第16张图片

剑指 Offer 31. 栈的压入、弹出序列

剑指offer题目代码总结_第17张图片

剑指 Offer 33. 二叉搜索树的后序遍历序列

递归分治

剑指offer题目代码总结_第18张图片

剑指 Offer 34. 二叉树中和为某一值的路径

剑指offer题目代码总结_第19张图片

剑指 Offer 35. 复杂链表的复制

哈希表:存放新旧节点的对应关系

在这里插入图片描述

原地复制

剑指offer题目代码总结_第20张图片

剑指 Offer 38. 字符串的排列

剑指offer题目代码总结_第21张图片

剑指 Offer 39. 数组中出现次数超过一半的数字

剑指offer题目代码总结_第22张图片

剑指 Offer 40. 最小的k个数

大根堆

剑指offer题目代码总结_第23张图片

快排思想

在这里插入图片描述


//快排思想
class Solution {
    public int[] getLeastNumbers(int[] arr, int k) {
        if(arr == null || arr.length == 0 || k <= 0) return new int[0];
        if(k > arr.length) return arr;

        quickSearch(arr, 0, arr.length-1, k);
        int[] res = new int[k];
        for(int i = 0; i < k; i++){
            res[i] = arr[i];
        }
        //System.out.println("最后:" + Arrays.toString(arr));
        return res;
    }

    public void quickSearch(int[] arr, int left, int right, int k){
        int index = quickSort(arr, left, right);
        if(index == k) return;
        else if(index < k)  quickSearch(arr, index+1, right, k);
        else quickSearch(arr, left, index-1, k);
    }

    public int quickSort(int[] arr, int left, int right){

        if(left >= right) return left;
        int i = left;
        int j = right;
        int x = arr[left];

        while(i < j){
            while(i < j && arr[j] >= x){
                j--;
            }
            arr[i] = arr[j];
            while(i < j && arr[i] <= x){
                i++;
            }
            arr[j] = arr[i];        
        }
        arr[i] = x;
        // quickSort(arr, left, i-1);
        // quickSort(arr, i+1, right);
        //说明:因为quickSearch已经进行了递归,所以qucikSort就不递归啦
        return j;
    }
}

剑指 Offer 42. 连续子数组的最大和

剑指offer题目代码总结_第24张图片

剑指 Offer 43. 1~n整数中1出现的次数

剑指offer题目代码总结_第25张图片

剑指 Offer 44. 数字序列中某一位的数字

剑指offer题目代码总结_第26张图片

剑指 Offer 45. 把数组排成最小的数

剑指offer题目代码总结_第27张图片

剑指 Offer 46. 把数字翻译成字符串

剑指offer题目代码总结_第28张图片
dp空间优化:
剑指offer题目代码总结_第29张图片

剑指 Offer 47. 礼物的最大价值

初始dp

剑指offer题目代码总结_第30张图片

空间优化,直接在原数组进行修改

剑指offer题目代码总结_第31张图片

代码简洁

剑指offer题目代码总结_第32张图片

剑指 Offer 48. 最长不含重复字符的子字符串

滑动窗口

在这里插入图片描述

动态规划

在这里插入图片描述

剑指 Offer 49. 丑数

dp

剑指offer题目代码总结_第33张图片
剑指offer题目代码总结_第34张图片

剑指offer题目代码总结_第35张图片

剑指 Offer 50. 第一个只出现一次的字符

哈希表

剑指offer题目代码总结_第36张图片
这个的代码太简洁了
剑指offer题目代码总结_第37张图片

有序哈希表

剑指offer题目代码总结_第38张图片

剑指 Offer 52. 两个链表的第一个公共节点

哈希表法

在这里插入图片描述

双指针 浪漫相遇

剑指offer题目代码总结_第39张图片

剑指 Offer 54. 二叉搜索树的第k大节点

剑指offer题目代码总结_第40张图片

剑指 Offer 55 - I. 二叉树的深度

dfs递归

剑指offer题目代码总结_第41张图片
剑指offer题目代码总结_第42张图片

BFS

在这里插入图片描述

剑指 Offer 55 - II. 平衡二叉树

递归

剑指offer题目代码总结_第43张图片

剪枝优化

剑指offer题目代码总结_第44张图片

剑指 Offer 53 - I. 在排序数组中查找数字 I

安安自己的题解 三种解法
两端都闭的写法(不存在也返回 返回的刚好是插入点的位置)

1. target+0.5 -0.5 左右都可

剑指offer题目代码总结_第45张图片

剑指offer题目代码总结_第46张图片
最后结果:7-3 = 4 所以4有4个

2. target target-1 只能是右边

剑指offer题目代码总结_第47张图片
剑指offer题目代码总结_第48张图片
最后结果:6-2 = 4 所以4有4个

3.target的左右边界

剑指 Offer 53 - II. 0~n-1中缺失的数字

类似于上题的±0.5 因此都是数组中不存在那个数值的情况
剑指offer题目代码总结_第49张图片

剑指 Offer 56 - I. 数组中数字出现的次数

排序+下标遍历 anan

//anan 2020.8.18
class Solution {
    public int[] singleNumbers(int[] nums) {
        //System.out.println(Arrays.toString(nums));
        Arrays.sort(nums);
        //System.out.println(Arrays.toString(nums));

        int[] res = new int[2];
        int length = nums.length;
        int count = 0;
        int i = 0;
        while(i < length-1){
            if(nums[i] == nums[i+1]){
                i+=2;
            }else{
                res[count++] = nums[i];
                i+=1;
            }
        }
        if(nums[length-1] != nums[length-2]){
            res[count++] = nums[length-1];
        }

        return res;
    }
}

异或

剑指offer题目代码总结_第50张图片

剑指offer题目代码总结_第51张图片

剑指 Offer 56 - II. 数组中数字出现的次数 II

剑指offer题目代码总结_第52张图片

剑指 Offer 57. 和为s的两个数字

双指针

剑指offer题目代码总结_第53张图片

二分法+双指针

//anan 2020.8.18  二分法+双指针
class Solution {
    public int[] twoSum(int[] nums, int target) {
        int left = 0;
        int right = leftBound(nums, target);  
        /*
        利用二分法缩小范围
        nums = [2,7,11,15], target = 9             只需要搜索[2,7,11]
        nums = [10,26,30,31,47,60], target = 40    只需要搜索[10,26,30,31,47]
        */
        int[] res = new int[2];

        while(left < right){
            if(nums[left] + nums[right] < target){
                left++;
            }else if(nums[left] + nums[right] > target){
                right--;
            }else{
                res[0] = nums[left];
                res[1] = nums[right];
                break;
            }
        }

        return res;
    }

    //若是数组中有target,返回target第一次出现的位置
    //若是数组中没有target,返回target该插入的位置
    public int leftBound(int[] nums, int target){
        int left = 0;
        int right = nums.length-1;
        while(left <= right){
            int mid = left + (right-left)/2;
            if(nums[mid] < target){
                left = mid+1;
            }else if(nums[mid] > target){
                right = mid-1;
            }else if(nums[mid] == target){
                right = mid-1;
            }
        }

        return (left >= nums.length ? nums.length-1 : left);
    }
}

剑指 Offer 57 - II. 和为s的连续正数序列

双指针

剑指offer题目代码总结_第54张图片

滑动窗口

剑指offer题目代码总结_第55张图片

剑指 Offer 58 - I. 翻转单词顺序

API

双指针

剑指offer题目代码总结_第56张图片

stack+定位单词边界

//anan  用stack 定位单词边界 不用API
class Solution {
    public String reverseWords(String s) {
        int left = 0, right = s.length() - 1;
        // 去掉字符串开头的空白字符
        while (left <= right && s.charAt(left) == ' ') ++left;
        // 去掉字符串末尾的空白字符
        while (left <= right && s.charAt(right) == ' ') --right;

        int i = left;
        int j = left;
        Deque<String> stack = new LinkedList<>();
        StringBuffer sb = new StringBuffer();

        while(i <= j && j <= right){
            while(i <= right && s.charAt(i) == ' ') i++;
            j = i;
            while(j <= right && s.charAt(j) != ' ') j++;
            stack.push(s.substring(i, j));
            i = j;
        }
       
        return String.join(" ", stack);
    }
}

先反转整个字符串,再反转各个单词


class Solution {
    public StringBuilder trimSpaces(String s) {
        int left = 0, right = s.length() - 1;
        // 去掉字符串开头的空白字符
        while (left <= right && s.charAt(left) == ' ') ++left;

        // 去掉字符串末尾的空白字符
        while (left <= right && s.charAt(right) == ' ') --right;

        // 将字符串间多余的空白字符去除
        StringBuilder sb = new StringBuilder();
        while (left <= right) {
            char c = s.charAt(left);

            if (c != ' ') sb.append(c);
            else if (sb.charAt(sb.length() - 1) != ' ') sb.append(c);

            ++left;
        }
        return sb;
    }

    public void reverse(StringBuilder sb, int left, int right) {
        while (left < right) {
            char tmp = sb.charAt(left);
            sb.setCharAt(left++, sb.charAt(right));
            sb.setCharAt(right--, tmp);
        }
    }

    public void reverseEachWord(StringBuilder sb) {
        int n = sb.length();
        int start = 0, end = 0;

        while (start < n) {
            // 循环至单词的末尾
            while (end < n && sb.charAt(end) != ' ') ++end;
            // 翻转单词
            reverse(sb, start, end - 1);
            // 更新start,去找下一个单词
            start = end + 1;
            ++end;
        }
    }

    public String reverseWords(String s) {
        StringBuilder sb = trimSpaces(s);

        // 翻转字符串
        reverse(sb, 0, sb.length() - 1);

        // 翻转每个单词
        reverseEachWord(sb);

        return sb.toString();
    }
}

作者:LeetCode-Solution
链接:https://leetcode-cn.com/problems/reverse-words-in-a-string/solution/fan-zhuan-zi-fu-chuan-li-de-dan-ci-by-leetcode-sol/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

剑指 Offer 58 - II. 左旋转字符串

三次翻转

剑指offer题目代码总结_第57张图片

字符串拼接+求余简化代码

剑指offer题目代码总结_第58张图片

你可能感兴趣的:(LeetCode)