剑指offer读书笔记(一)

简介:用于记录剑指offer中题目的思路解法,已经遇到过的相似的题目(遇到类似的问题都会在相应的地方更新)

第二章

面试题1:赋值运算符函数
——实现一个赋值运算符函数
解法1:delete原来的指针之后再新new一个(缺点:delete原先的内存之后,在new的时候可能抛出异常,使其为一个空指针,容易导致程序崩溃)
解法2:利用局部变量的生存域,自动释放tmp的指向的内存
在文章实现一个String类中有方法1的详细实现方法

面试题2:实现单例模式
——设计一个只能生成一个实例的类
解法:将构造函数定义为Private之后,定义一个static的类变量,然后通过static函数返回该变量(缺点:过早才创建实例,降低内存的使用率)
相关题目:
- C++如何实现一个不可继承的类

面试题3:数组中的重复数字
——找出数组中的重复数字,数字的范围在1~n-1之间
解法1:由于数组中数字范围在1~n-1之间,利用下标对应i值求法求解(需要修改数组)
解法2:使用二分查找法搜索
相关题目:
- LeetCode:Single Number
- LeetCode:Contains Duplicate

面试题4:二维数组中的查找
——给定一个二维数组,行列都呈递增状态,寻找数num
解法:由于行列都是呈递增状态,所以可以从右上角的数入手,若大于查找的数字,则除去该列;若小于查找的数字,则除去该行。直到查找到该数字

面试题5:替换空格
——给定一个字符串,用”%20”替换出现的空格
解法:获取字符串长度后得到替换空格后的字符串长度,最后从尾部开始复制字符串
相关题目:
- LeetCode:Merge Sorted Array

面试题6:从头到尾打印链表
——输入链表头结点,从尾部输出
解法1(非递归):利用栈的后入先出的特性,将节点值压入栈中后弹出
解法2(递归):利用递归从最后结点开始输出(当链表很长的时候容易导致递归层级很深,从而导致栈溢出)

面试题7:重建二叉树
——输入二叉树的前序和中序的结果,重建该二叉树
解法:由于给了前序遍历与中序遍历,可以确定根节点的值和左右子树部分,再使用递归的方法将左右子树通过递归构造出二叉树
相关题目:
- LeetCode:Convert Sorted Array to Binary Search Tree

面试题8:二叉树的下一个结点
——给定二叉树和节点,找出中序遍历的下一个节点
解法:中序遍历的方法是左节点-根节点-右节点,所以得到节点后,先判断是否是叶节点;若不是,查看是否有右节点,没有的话,返回父节点,查看是否为父节点的右节点;若不是父的右节点,返回父节点;若是根节点,返回父节点;

面试题9:用两个栈实现队列
——使用两个栈实现一个队列,并完成一些函数
解法:由于栈是LIFO,队列为FIFO,所以通过两个栈,可以将栈A的栈底元素变成栈B的栈顶元素再弹出,实现队列
相关题目:
- 用队列来实现栈
- LeetCode:Min Stack

面试题10:斐波那契数列
解法:使用递归的方法,但是同第六题,但递归层次很深时容易栈溢出并且效率不高;可用变量保存f(n-1)和f(n-2)的值,采用非递归的方法来求得f(n)
相关题目:
- 常见的如青蛙跳台阶等

面试题11:旋转数组的最小数字
——将数组最开始的若干元素搬到数组的末尾,称为旋转;找出数组旋转的最小数字
解法:二分法查找(遇到相等的数字容易出问题,所以当数字相等的时候加入一个顺序查找解决问题):两个指针分别指向前端和后端,根据中间元素来判断是否移动前端指针还是后端指针,在两个指针相差1的时候,获得最小数字
相关题目:
- PAT:反转链表
- LeetCode:Rotate Array
- LeetCode:Move Zeroes

面试题12:矩阵中的路径
——给定一个字符串和一个矩阵,判断矩阵中是否存在有改字符串的路径
解法:使用回溯法的递归,每次递归的时候都有四个移动方向,用布尔值来判断是否存在该路径(注意判断该路径是否合法)

面试题13:机器人的移动范围
——机器人在一个mXn的方格中移动,坐标的数位纸盒不能大于k,如k=18时,(35,37)是合法的(3+5+3+7=18),而(35,38)是不合法的(3+5+3+8>18),求机器人能到达多少个格子
解法:与面试题12类似,在移动路径的时候需要一个函数判断该路径是否合法,并且数位之和是否大于k

面试题14:剪绳子
——给一个绳子,将绳子剪成多段,判断怎么剪能实现最大的乘积
解法1:动态规划(f(n)=max(f(i) x f(n-i))),将总问题分成数个子问题,求出子问题的最优解之后,在求出最大值。子问题类似于斐波那契数列,需要求前面的值得到下一个的值,所以可使用递归;非递归的方法还是用变量来保存前面的值,再求解
解法2:暴力求解:判断结论在某一范围内怎么样得到的值为最大,得到方程,直接通过代码实现
相关题目:
- LeetCode:House Robber
- LeetCode:Best Time to Buy and Sell Stock
- PAT:月饼

面试题15:二进制中的1的个数
——输入一个值,判断二进制有多少个数
解法:将整数减去1,则会将最右边的1变成0,之后的0变成1,所以将整数减去1,再与原来相与,最右边的数1都会变成0,则原来有多少个1,就能做多少次这样的操作,所以可以得出有多少个1(常规解法:将数与1相与再向右移动一个位数(与除2等价,但是除法效率更低)来计算存在多少个1,若数位负数会导致死循环,所以需要用一个unsigned来保存1进行计算)
相关题目:
- LeetCode:Sum of Two Integers

第三章

面试题16:数值的整数次方
——实现库函数Power
解法:首先要考虑0的情况;若指数为负数,在求出次方之后,再求其倒数;再求次方的时候,如32次方等于16的次方再平方一次,公式如下
这里写图片描述

面试题17:打印从1打最大的n位数
——输入数字n,输出1到n为的最大进制数
解法1:由于n位可能甚至超出longlong型的大小,所以使用长字符串,对一个字符串进行加1操作,若加到10,则前面一位char也需要加1,以此类推
解法2:使用递归的方法,实现n个数的0-9的全排列
相关题目:
- PAT:A+B=C
- PAT:A除以B

面试题18:删除链表的节点
——给定链表和节点,删除节点
解法1:需要判断该节点是否为头节点,中间节点,尾节点
解法2:删除重复节点:设置两个节点,一个保存前节点q,一个保存移动的节点p,当前节点和p相同时,删除节点,q和p移动;若不同,只移动p
解法2:删除重复节点:使用hashmap,若在之前已经出现过,删除该点
相关问题:
- LeetCode: Delete Node in a Linked List

面试题19:正则表达式匹配
——实现一个函数来进行”.”和”*”的正则表达式的匹配
解法:使用递归的方法,和面试题12和13的解法有相似之处
相关问题:
- PAT:旧键盘

面试题20:表示数值的字符串
——实现一个函数判断是否字符串为一个数值

相关问题:
- PAT:验查身份证
- PAT:福尔摩斯的约会

面试题21:调整数组顺序使奇数位于偶数前面
——实现一个函数,将数组中偶数位于后半段,奇数位于前半段
解法:使用两个前后指针,分别向前移动,判断指向数的奇偶性,将其对调(将判断条件写在另一个函数里面,方便扩展)

面试题22:链表中的倒数第k个节点
——输入一个链表,输出倒数第k个节点的值
解法:使用两个指针,第一个指针先移动k-1次,然后第二个指针跟着一起移动到第一个指针直到链表的尾节点时,输出第二个指针(要注意判断指针是否为nullptr)

面试题23:链表中的环入口
——若链表包含环,找出环的入口
解法:使用快慢指针,若存在换,则快慢指针会相遇,相遇的点就是环入口
相关问题:
- LeetCode: Linked List Cycle

面试题24:反转链表
——得到链表的头节点,反转链表并输出
解法:将节点的前后指针相对调
相关问题:
- LeetCode:Reverse Linked List

面试题25:合并有序链表
——将两个有序的链表合并成一个有序的链表
解法:使用一个新链表,两个指针分表指向链表A和B,判断两个指针的值,符合条件就插入,该指针指向下一位
相关问题:
- LeetCode:Merge k Sorted Lists

面试题26:树的子结构
——输入两棵二叉树,判断是否B为A的子结构
解法:首先在A中寻找和B的根节点相等的节点,然后两个一起遍历,若不是子节点,则寻找下一个和B的根节点相等的节点
相关问题:
- LeetCode:Subtree of Another Tree

你可能感兴趣的:(剑指offer读书笔记(一))