文章目录
注意
- 刷题时,尽量不要使用异常捕获,会消耗额外空间,拉低运行速度。
- 出现TLE(Time Limit Exceeded)时,检查是否if写成了while,或者是while没有退出条件,或者是while后面标点错误(多了一个",")
思想
利用5位码点猜生日
字符和整数加减
- ch - ‘A’ //不需要强制转换类型
字符参与运算,字符使用Unicode码
当一个字符和整数相加减运算的时候,字符使用Unicode码参与运算
关于每列输出a个数后换行的思考
- 单独设置换行标志,如设置count=1
- 或者和下标相关联
数独问题
数独边界
已知一个数字的下标[i][j]
,它所在3*3
方框的第一个元素的下标是:[(i/3)*3][(j/3)*3]
主定理(master theorem)
二分查找middle的确定
- 经典二分middle直接用(right+left)/2取中点确定
- 二分思想变形之后,如果是左边界变化的二分,要使用减的方法(right-left)/2+left
回溯法、动态规划、贪婪算法应用场景
- 如果题目要求在二维数组(如迷宫或者棋盘) 上搜索路径,可以尝试使用回溯法,回溯法很适合使用递归代码实现
- 如果面试是求某个问题的最优解,并且问题可以分为多个子问题,可以尝试使用动态规划。在用自上而下的递归思路去分析动态规划问题的时候,会发现子问题之间存在重叠的更小的子问题。为了避免不必要的重复计算,采用自下而上的递归代码来实现,也就是把子问题的最优解先算出来并用数组(一般是二维或者一维数组)保存下来,接下来基于子问题的解计算大问题的解。
- 如果分解子问题的时候可能存在某个特殊的选择,如果采用这个特殊的选择将一定能得到最优解,那么,该问题可能适用于贪婪算法。
递归的时间和空间消耗
- 空间消耗:需要在内存栈中保存参数,临时变量,返回地址
- 时间消耗:内存栈的压入数据和弹出数据都需要时间
return 语句和循环进行语句
- 有返回的函数,先写return作为备注
- 以while为代表的循环,先写while中的循环进行条件,以防后面忘记写,参照《剑指offer》中删除重复节点的非递归写法
先写while中的循环进行条件,以防后面忘记写,参照《剑指offer》中删除重复节点的非递归写法
循环和递归示例(以二分法为例子)
- 非递归
class Solution
{
public int findNum(int[] nums,int k)
{
if(nums.length <= 0 )
return -1;
return helper(nums,k);
}
public int helper(int[] nums,int k )
{
int l = 0;
int r = nums.length-1;
while(l <= r)
{
int m = (l + r)>>1;
if(nums[m] == k)
return m;
else if(nums[m] > k)
r = m - 1;
else
l = m + 1;
}
return -1;
}
}
}
- 递归
class Solution
{
public int findNum(int[] nums,int k)
{
if(nums.length <= 0 )
return -1;
return helper(nums,k,0,nums.length-1);
}
public int helper(int[] nums,int k,int l, int r )
{
if(l <= r) //递归这里是if,而循环这里是while
{
int m = (l + r)>>1;
if(nums[m] == k)
return m;
else if(nums[m] > k)
return helper(nums,k,l,m-1); //注意递归这里一定要有return
else
return helper(nums,k,m+1,r); //注意递归这里一定要有return
}
return -1;
}
}
}