基础知识:编程语言、数据结构、算法
一、赋值运算符函数
- 返回值类型声明为引用,并返回 *this,只有返回引用才可以连续赋值。
- 传入参数类型声明为常量引用,避免调用复制构造函数和传入实例。
- 判断传入参数与当前实例 *this 是否相同。
- 释放自身已有内存再分配,避免内存泄漏。
- 在4基础上,为避免释放后分配失败,可以先分配再释放,或者先创建临时实例再交换。
二、实现Singleton模式
public sealed class Singleton {
private Singleton() {}
private static object syncObj = new object();
private static Singleton instance = null;
public static Singleton Instance {
get {
if (instance == null) { // 避免每次调用加锁耗时
lock(syncObj) { // 避免多线程同时调用
if (instance == null) // 不存在则创建
instance = new Singleton();
}
}
return instance;
}
}
}
三、数组中重复的数字
- 找出数组中重复的数字(数组大小为n,其元素为0~n-1)
- 不修改数组找(数组大小为n+1,其元素为1~n)
解:二分查找统计法O(nlogn)
四、二维数组中的查找
- 从左到右递增,从上到下递增
解:找右上角,根据大小关系减列或加行
五、替换空格
- 将字符串中空格替换成%20
解:先遍历确定空格数量,再反向逐一赋值
六、从尾到头打印链表
解:a.反转链表 b.栈 c. 递归
七、重建二叉树
- 输入前序和中序遍历,重建二叉树
八、二叉树的下一个节点
- 给定二叉树和其中之一节点,找出中序遍历序列的下一个节点(含父节点指针)
解:分类讨论(有无右子节点,是否是父节点的左节点等)
九、用两个栈实现队列
十、斐波那契数列
- 求第n项
- 青蛙跳台阶(一次跳1或2级,到第n级共有多少种跳法)
解:等于斐波那契
十一、旋转数组的最小数字
- 把数组最开始若干元素移到末尾即为旋转,输入递增排序的一个旋转,输出旋转数组的最小元素。
解:二分查找,比较左右中元素大小关系判断最小元素位置,特殊情况是若全部相同则只能顺序查找
十二、矩阵中的路径
- 判断矩阵是否存在一条包含某字符串所有字符的路径,不能经过重复元素。
解:回溯法
十三、机器人的运动范围
十四、剪绳子
- 把长为n的绳子剪成m段,每段长最大乘积可能是多少?
解:a.动规(从上而下分析问题,从下而上解决问题) b.贪心(数学)
十五、二进制中1的个数
解:a.右移判断最右位(负数会引起死循环) b.将1左移逐个对比 (循环位数次数)c.减1取与(循环1的次数)
高质量代码:规范性、完整性、鲁棒性
十六、数值的整数次方
- double Power(double base, int exponent)
解:注意特殊情况正负0
十七、打印从1到最大的n位数
解:a.字符串模拟数字加法 b.全排列递归
十八、删除链表的节点
- 给定单向链表头指针和一个节点指针,在O(1)时间内删除该节点
解:复制下个节点信息,包括3种特殊情况 a.只有一个节点 b.非尾节点 c.尾节点 - 删除排序链表中重复的节点
解:头节点可能被删除,函数声明应为ListNode **pHead
十九、正则表达式匹配
- 实现可匹配包含’.‘和’*'的正则表达式函数。
解:状态机
二十、表示数值的字符串
- 判断字符串是否表示数值(包括整数和小数),如+100、5e2、-123、3.1416、-1E-16等,但12e、1a3.14、1.2.3、±5、12e+5.4等都不是。
二十一、调整数组顺序使奇数位于偶数前面
解:需考虑可扩展解法,函数指针
二十二、链表中倒数第k个节点
解:特殊情况,不足k个或空指针等
二十三、链表中环的入口节点
二十四、反转链表
二十五、合并两个排序的链表
解:递归
二十六、树的子结构
思路:画图、举例、分解
二十七、二叉树的镜像
二十八、对称的二叉树
二十九、顺时针打印矩阵
三十、包含min函数的栈
- 实现调用min、push、pop时间复杂度均为O(1)的栈类
解:设立额外辅助栈,每次push min(辅助栈顶,新元素)
三十一、栈的压入、弹出序列
三十二、从上到下打印二叉树
- 不分行从上到下从左到右打印
- 分行从上到下从左到右打印
- 之字形打印
解:12用队列,3用两个栈
三十三、二叉搜索树的后序遍历序列
三十四、二叉树中和为某一值的路径
三十五、复杂链表的复制
解:在原链表每个节点后面复制一个新节点
三十六、二叉搜索树与双向链表
- 将二叉搜索树转成一个排序的双向链表,要求不能创建新节点,只能调整原节点指针方向
三十七、序列化二叉树
三十八、字符串的排列
解:交换、递归、交换
效率:时间与空间的平衡
三十九、数组中出现次数超过一半的数字
解:a.二分法排序,直到找到中位数,时间复杂度O(n) b.遍历记录当前数和频率,当下一个数不相同时减频率,否则加,当次数为0则重设当前数。
四十、最小的k个数
解:a.二分法排序,直到找到第k位,时间复杂度O(n) b.最大堆,红黑树,时间复杂度O(nlogk)
四十一、数据流中的中位数
四十二、连续子数组的最大和
四十三、1~n整数中1出现的次数
四十四、数字序列中某一位的数字
四十五、把数组排成最小的数
四十六、把数字翻译成字符串
解:从右往左
四十七、礼物的最大价值
解:二维数组可优化成一维数组
四十八、最长不含重复字符的子字符串
四十九、丑数
- 只包含因子2、3和5的数称为丑数,求按从小到大顺序的第n个丑数
五十、第一个只出现一次的字符
五十一、数组中的逆序对
解:归并排序,时间复杂度O(nlogn),空间复杂度O(n)
五十二、两个链表的第一个公共节点
能力:知识迁移
五十三、在排序数组中查找数字
- 数字k在排序数组中出现的次数
解:二分法找第一个k和最后一个k,时间复杂度O(logn) - 0~n-1中缺失的数字
- 找到单调递增且元素唯一的数组中,与下标值相等的元素
五十四、二叉搜索树的第k大节点
解:中序遍历
五十五、二叉树的深度
- 求二叉树深度,即最长路径长度
- 判断是否是平衡二叉树
五十六、数组中数字出现的次数
- 一个整型数组中除两个只出现一次的数字外,其他数字都出现了两次,找到这两个数,时间复杂度要求O(n),空间复杂度要求O(1)
解:逐个异或,按异或结果某一位是否为1划分两组,再在每个组求异或 - 一个数组中除一个只出现一次的数字外,其他数字都出现了三次,找到那个数
解:逐个记录每位相加,找到所有不能被3整除的位结果,即表示只出现一次的数
五十七、和位s的数字
- 输入递增数组和数字s,找到和为s的任意一对数
解:双指针 - 所有和为s的连续正数序列
五十八、翻转字符串
- 翻转句中单词顺序,单词内字符顺序不变,标点符号与普通字母相同处理
解:两次翻转:先翻转所有字符,再翻转单词 - 左旋转字符串
五十九、队列的最大值
- 滑动窗口的最大值
- 定义一个队列并实现函数max得到最大值,要求max,push_back,pop_front时间复杂度都是O(1)
六十、n个骰子的点数
六十一、扑克牌中的顺子
六十二、圆圈中最后剩下的数字
六十三、股票的最大利润
六十四、求1+2+…+n
- 要求不能使用乘除法、for、while、if、else、switch、case等关键字及条件判断语句(A?B:C)
解:a.定义n维指针数组,指向使用构造函数++且用static求和的自定义类 b.定义长度为2的指针数组,!!n,虚函数,递归n-1 c.函数指针 d.模板类型
六十五、不用加减乘除做加法
int Add(int num1, int num2) {
while (num2 != 0) {
int sum = num1 ^ num2;
int carry = (num1 & num2) << 1;
num1 = sum;
num2 = carry;
}
return num1;
}
六十六、构建乘积数组
其他知识点
- sizeof(空类型、+构造&析构、+虚函数)
- sizeof(数组、指针、数组退化指针)
- 拷贝构造函数传址
- struct和class区别,c#对应区别
- c#调用顺序:静态构造函数、静态变量、成员变量、构造函数
- 字符串末尾还含有’\0’字符
char s1[] = "hello"; char s2[] = "hello"; // s1 != s2,数组初始地址不同
char *s3 = "hello"; char *s4 = "hello"; // s3 == s4,指针指向同一常量字符串地址
- 3种错误处理方式:返回值、全局变量和异常
- 判断浮点数是否相等不能直接==,应判断是否相差小于设定阈值