剑指offer笔记

  • 题目概览数据来自leetcode,截止至2020.08;其实数据没有什么用,干就完了
  • 另外我会对题目进行补充,因为这些题目的变种也常出现,题解思路与注意事项来自leetcode、csdn、简书;来源过多恕不能全部记录来源,请原作者看到后私信我🙏
  • 代码全部为本人在leetcode上的AC代码,均添加了注释。
  • 本文力求还原思维过程,使解题过程生动有逻辑,帮助大家更好地进行思考和面试
    • 行文逻辑为:题目(>题干)>考察点>思路>复杂度

剑指 Offer 03 数组中重复的数字(三种要求)

这道题在原书上绝对不是简单级别啊!
它考察的是程序员的沟通能力,先问面试官要时间/空间需求!!!
只是时间优先,就用字典;
还有空间要求,就用原地置换;
如果面试官要求空间O(1)并且不能修改原数组,得写成二分法。

时间优先 字典解法
时间复杂度为 O(n),空间复杂度为 O(n)

对于 n 长数组中 [0, n] 范围的数字,从头遍历,将值为i的数字放到第i位,若此处已有数字i,代笔i重复。

class Solution {
public:
    int findRepeatNumber(vector<int>& nums) {
        bool flag[nums.size()];				//标志数组,表示数字i是否出现过
        memset(flag, false, sizeof(flag));	//全部置false
        for(int i = 0; i < nums.size(); i++)
            if(flag[nums[i]]){
            	return nums[i];			//若某元素出现过,则返回该数字
            }else{
            	flag[nums[i]] = true;	//遍历并标注已出现
            }
        }
        return -1;	//若从未有重复出现的数字,则返回-1
    }
};

空间O(1) 原地置换
时间复杂度为 O(n),空间复杂度为 O(1)

对于 n 长数组中 [0, n] 范围的数字,不能使用额外空间,就要将出现信息保存在本数组中,将数字的值作为索引,将数字放到自己的位置上,如果数字不重复,那么数组上同一个位置的数字不会出现两次。

我们在遍历数组时将数字进行交换归位,如果复位时某的数组位置已经有了一个值等于索引的元素,代表此处素组

class Solution {
    public int findRepeatNumber(int[] nums) {
        int temp;
        for(int i=0;i<nums.length;i++){//
            while (nums[i]!=i){//如果i位置不是i,则操作,直到是i
                if(nums[i]==nums[nums[i]]){//如果i处数字已经有了一个放置好的,则重复了
                    return nums[i];
                }
                //交换两者
                temp=nums[i];
                nums[i]=nums[temp];
                nums[temp]=temp;
            }
        }
        return -1;
    }
}

空间O(1)且不能修改数组 二分
时间复杂度为 O(nlogn),空间复杂度为 O(1)

  • 代码:
//

采取二分思想,抽屉原理:
对于 n 长数组中 [0, n] 范围的数字,从头遍历,将值为i的数字放到第i位,若此处已有数字i,代笔i重复。

借鉴二分查找的思想,将数字1n拆分成1m和m+1n两部分,如果数字范围1m中数字个数大于m,则重复数字在1m中间,否则重复数字一定在数字范围m+1n中。基于二分查找法不能找到全部的重复数字,例如{2,2,3,3,4,5,6,7}中数字区间为1~2的范围内2出现两次,但1没有出现,不能确定是每个数字出现一个还是某个数字出现两次。

高明解法:
首先将数组一分为二,假设数组有8个元素。那么元素大小都在 0 ~ 7 之间。一分为二,如果没有重复,四个元素在 0 ~ 3 之间,四个在 4 ~ 7 之间。假设数组为arr[8] = {1, 0, 2, 3, 3, 4, 5, 6},统计0 ~ 3 之间的元素有5个, 统计 4 ~ 7 之间的元素有3个。说明,在 0 ~ 3 之间肯定有重复元素。接下来划分 0 ~ 3的5个元素{1, 0, 2, 3, 3}。 0 ~ 1 之间有两个元素, 2~3之间有三个元素。再划分2 ~ 3之间的元素,2有一个,3有两个,所以重复的是元素3。

#include <iostream>
    #include <vector>
    using namespace std;
    class Solution{
    public:
        int duplication(vector<int> vec)
        {
            // 空数组
            int length = vec.size();
            if(vec.size() == 0)
                return -1;

            // 数字超界
            for(int i =0;i<length;++i)
            {
                if(vec[i]<1 || vec[i]>length-1)
                    return -1;
            }
            // 定义数字范围
            int begin = 1;
            int end = length-1;

            // 指定数字范围内的数字个数
            while(begin<=end)
            {
                // 计算数字范围的中点
                int mid = (begin + end)>>1;

                // 统计指定数字范围内的数字个数
                int count = countrange(vec,begin,mid,length);

                if(end > begin)
                {
                    // 更新数字范围
                    if(count>(mid - begin + 1))
                        end = mid;
                    else
                        begin = mid + 1;
                }
                else
                {
                    if(count > 1)
                        return begin;
                    else
                        break;
                }
            }

            return -1;
        }
int countrange(vector<int> vec,int begin,int end,int length)
    {
        int count=0;
        for(int i=0;i<length;++i)
        {
            if(vec[i]>=begin && vec[i]<=end)
                ++count;
        }

        return count;
    }
};

剑指 Offer 04 二维数组中的查找
剑指 Offer 05 替换空格
剑指 Offer 06 从尾到头打印链表
剑指 Offer 07 重建二叉树
剑指 Offer 09 用两个栈实现队列
剑指 Offer 10- I 斐波那契数列
剑指 Offer 10- II 青蛙跳台阶问题
剑指 Offer 11 旋转数组的最小数字
剑指 Offer 12 矩阵中的路径
剑指 Offer 13 机器人的运动范围
剑指 Offer 14- I 剪绳子
剑指 Offer 14- II 剪绳子 II
剑指 Offer 15 二进制中1的个数
剑指 Offer 16 数值的整数次方
剑指 Offer 17 打印从1到最大的n位数
剑指 Offer 18 删除链表的节点
剑指 Offer 19 正则表达式匹配
剑指 Offer 20 表示数值的字符串
剑指 Offer 21 调整数组顺序使奇数位于偶数前面
剑指 Offer 22 链表中倒数第k个节点

剑指 Offer 23 链表中的环(三道题目)

参考:https://blog.csdn.net/lqy971966/article/details/89818680

思想:双指针

  1. 判断成环: 取指针 fast 每次移动两个节点,指针 slow 每次移动一个节点,第一次相遇代表此链表成;
  2. 找环的入口 (区别于链表入口):取两个 slow 指针,一个从 fast 与 slow 第一次相遇点开始,一个从链表入口开始,相遇时即为环入口;
  3. 求环的长度: 在1的基础上继续走并开始记录路程,当 fast 第二次与 slow 相遇时,fast 比 slow 多走了一整圈,此时 fast 路程减去 slow 路程即为环长度;又因为 fast 是 slow 的两倍速度,因此 pathLen(slow) == pathLen(fast)/2 == len(环)

解释:因为存在环,所以两个指针必定相遇在环中的某个节点上。此时 fast 移动的节点数为 x+2y+z,slow 为 x+y,由于 fast 速度比 slow 快一倍,因此 x+2y+z=2(x+y),得到 x=z。

在相遇点,slow 要到环的入口点还需要移动 z 个节点,如果让 fast 重新从头开始移动,并且速度变为每次移动一个节点,那么它到环入口点还需要移动 x 个节点。在上面已经推导出 x=z,因此 fast 和 slow 将在环入口点相遇。

剑指 Offer 24 反转链表
剑指 Offer 25 合并两个排序的链表
剑指 Offer 26 树的子结构
剑指 Offer 27 二叉树的镜像
剑指 Offer 28 对称的二叉树
剑指 Offer 29 顺时针打印矩阵
剑指 Offer 30 包含min函数的栈
剑指 Offer 31 栈的压入、弹出序列
剑指 Offer 32 - I 从上到下打印二叉树
剑指 Offer 32 - II 从上到下打印二叉树 II
剑指 Offer 32 - III 从上到下打印二叉树 III
剑指 Offer 33 二叉搜索树的后序遍历序列
剑指 Offer 34 二叉树中和为某一值的路径
剑指 Offer 35 复杂链表的复制
剑指 Offer 36 二叉搜索树与双向链表
剑指 Offer 37 序列化二叉树
剑指 Offer 38 字符串的排列
剑指 Offer 39 数组中出现次数超过一半的数字
剑指 Offer 40 最小的k个数
剑指 Offer 41 数据流中的中位数
剑指 Offer 42 连续子数组的最大和
剑指 Offer 43 1~n整数中1出现的次数
剑指 Offer 44 数字序列中某一位的数字
剑指 Offer 45 把数组排成最小的数
剑指 Offer 46 把数字翻译成字符串
剑指 Offer 47 礼物的最大价值
剑指 Offer 48 最长不含重复字符的子字符串
剑指 Offer 49 丑数
剑指 Offer 50 第一个只出现一次的字符
剑指 Offer 51 数组中的逆序对
剑指 Offer 52 两个链表的第一个公共节点
剑指 Offer 53 - I 在排序数组中查找数字 I
剑指 Offer 53 - II 0~n-1中缺失的数字
剑指 Offer 54 二叉搜索树的第k大节点
剑指 Offer 55 - I 二叉树的深度
剑指 Offer 55 - II 平衡二叉树
剑指 Offer 56 - I 数组中数字出现的次数
剑指 Offer 56 - II 数组中数字出现的次数 II
剑指 Offer 57 和为s的两个数字
剑指 Offer 57 - II 和为s的连续正数序列
剑指 Offer 58 - I 翻转单词顺序
剑指 Offer 58 - II 左旋转字符串
剑指 Offer 59 - I 滑动窗口的最大值
剑指 Offer 59 - II 队列的最大值
剑指 Offer 60 n个骰子的点数
剑指 Offer 61 扑克牌中的顺子
剑指 Offer 62 圆圈中最后剩下的数字
剑指 Offer 63 股票的最大利润
剑指 Offer 64 求1+2+…+n
剑指 Offer 65 不用加减乘除做加法
剑指 Offer 66 构建乘积数组
剑指 Offer 67 把字符串转换成整数

题目概览

题号名称题解通过率难度
剑指 Offer 03数组中重复的数字103767.5%简单
剑指 Offer 04二维数组中的查找72840.9%简单
剑指 Offer 05替换空格72576.6%简单
剑指 Offer 06从尾到头打印链表70576.1%简单
剑指 Offer 07重建二叉树52968.8%中等
剑指 Offer 09用两个栈实现队列63473.9%简单
剑指 Offer 10- I斐波那契数列60633.3%简单
剑指 Offer 10- II青蛙跳台阶问题46842.0%简单
剑指 Offer 11旋转数组的最小数字67849.9%简单
剑指 Offer 12矩阵中的路径34544.5%中等
剑指 Offer 13机器人的运动范围82449.6%中等
剑指 Offer 14- I剪绳子47254.8%中等
剑指 Offer 14- II剪绳子 II15230.0%中等
剑指 Offer 15二进制中1的个数41073.6%简单
剑指 Offer 16数值的整数次方25032.8%中等
剑指 Offer 17打印从1到最大的n位数44578.8%简单
剑指 Offer 18删除链表的节点51659.0%简单
剑指 Offer 19正则表达式匹配14735.2%困难
剑指 Offer 20表示数值的字符串19520.6%中等
剑指 Offer 21调整数组顺序使奇数位于偶数前面54664.3%简单
剑指 Offer 22链表中倒数第k个节点75778.9%简单
剑指 Offer 23寻找链表中的环(三道题)无资料无资料无资料
剑指 Offer 24反转链表58175.1%简单
剑指 Offer 25合并两个排序的链表36374.1%简单
剑指 Offer 26树的子结构36946.4%中等
剑指 Offer 27二叉树的镜像48378.8%简单
剑指 Offer 28对称的二叉树33957.8%简单
剑指 Offer 29顺时针打印矩阵66845.2%简单
剑指 Offer 30包含min函数的栈26557.5%简单
剑指 Offer 31栈的压入、弹出序列28458.9%中等
剑指 Offer 32 - I从上到下打印二叉树31264.9%中等
剑指 Offer 32 - II从上到下打印二叉树 II35468.9%简单
剑指 Offer 32 - III从上到下打印二叉树 III35258.7%中等
剑指 Offer 33二叉搜索树的后序遍历序列31952.1%中等
剑指 Offer 34二叉树中和为某一值的路径29257.1%中等
剑指 Offer 35复杂链表的复制25771.2%中等
剑指 Offer 36二叉搜索树与双向链表27563.9%中等
剑指 Offer 37序列化二叉树13652.2%困难
剑指 Offer 38字符串的排列30354.2%中等
剑指 Offer 39数组中出现次数超过一半的数字34267.7%简单
剑指 Offer 40最小的k个数93557.6%简单
剑指 Offer 41数据流中的中位数14255.5%困难
剑指 Offer 42连续子数组的最大和45959.8%简单
剑指 Offer 431~n整数中1出现的次数20845.5%中等
剑指 Offer 44数字序列中某一位的数字16638.8%中等
剑指 Offer 45把数组排成最小的数27455.9%中等
剑指 Offer 46把数字翻译成字符串74553.9%中等
剑指 Offer 47礼物的最大价值33568.2%中等
剑指 Offer 48最长不含重复字符的子字符串30345.7%中等
剑指 Offer 49丑数17364.3%中等
剑指 Offer 50第一个只出现一次的字符36760.3%简单
剑指 Offer 51数组中的逆序对37845.8%困难
剑指 Offer 52两个链表的第一个公共节点27963.1%简单
剑指 Offer 53 - I在排序数组中查找数字 I42053.0%简单
剑指 Offer 53 - II0~n-1中缺失的数字51244.2%简单
剑指 Offer 54二叉搜索树的第k大节点37874.0%简单
剑指 Offer 55 - I二叉树的深度44578.8%简单
剑指 Offer 55 - II平衡二叉树32558.1%简单
剑指 Offer 56 - I数组中数字出现的次数49171.7%中等
剑指 Offer 56 - II数组中数字出现的次数 II23879.2%中等
剑指 Offer 57和为s的两个数字26665.8%简单
剑指 Offer 57 - II和为s的连续正数序列120169.0%简单
剑指 Offer 58 - I翻转单词顺序32342.5%简单
剑指 Offer 58 - II左旋转字符串67285.3%简单
剑指 Offer 59 - I滑动窗口的最大值41544.3%简单
剑指 Offer 59 - II队列的最大值71447.9%中等
剑指 Offer 60n个骰子的点数20653.7%简单
剑指 Offer 61扑克牌中的顺子32844.5%简单
剑指 Offer 62圆圈中最后剩下的数字44362.2%简单
剑指 Offer 63股票的最大利润29863.9%中等
剑指 Offer 64求1+2+…+n73885.4%中等
剑指 Offer 65不用加减乘除做加法16155.9%简单
剑指 Offer 66构建乘积数组17958.3%简单
剑指 Offer 67把字符串转换成整数22527.6%中等
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值