只简要总结最优解思路和一些核心代码
描述:一个二维数组满足每一行从左到右递增,从上到下递增。给定这样数组和一个值,判断其是否在数组中。
思路:从数组右上方开始寻找,如果当前值等于目标值返回,如果当前值大于目标值则剔除该列,如果当前值小于目标值则剔除该行。
int row = 0;
int column = n - 1;
while(row < rows && column >=0){
if(a[row * n + column] == target){
find = true;
break;
}else if(a[row * n + column] > target){
colunm --;
}else{
row ++;
}
}
描述:把字符串中的空格用 %20 替换
思路:先扫描一遍获得空格的个数,这样就可以计算出替换后的数组长度。然后从后往前进行字符串赋值和替换。
思路:(1)使用栈进行打印;
(2)链表翻转后打印;
描述:根据前序和中序序列重建二叉树。
思路:现在前序序列中找到根节点,然后在中序序列中找根节点,中序序列中将根节点分为左右子树,递归构建。
思路:数字进入stack1,如果需要删除元素,将stack1中除了栈底元素外的其他元素弹出并放入第二个栈中,弹出stack1栈底元素,然后再把stack2中的元素弹出至stack1中。
思路:二分查找
如果数组中不存在重复数字,则根据mid值和左指针值比较大小即可。如果mid值大于左指针值则舍弃前半个区间,否则舍弃后半个区间。
如果存在重复数字,如果mid,左右指针的值都相等,那么需要顺序遍历左右指针中间的元素来找到最小值。
思路:(1)使用三个变量进行迭代;
long fib1 = 1;
long fib2 = 0;
long fibn = 0;
for(int i = 2; i <= n ;i ++){
fibn = fib1 + fib2;
fib2 = fib1;
fib1 = fibn;
}
return fibn;
思路:
(1)引入一个flag变量,每次向左移一位进行与运算;
(2)n = n & (n-1); 去掉最低位的1;
思路:多次幂的方式。
double Pow(double base, int n){
if(n == 0) return 1;
if(n == 1) return base;
double result = Pow(base, n >>1);
result *= result;
if(n & 0x1 == 1) return result *= base;
return result;
}
描述:例如给一个整数3 ,需要从1一直打印到最大的三位数999.
思路:(1)用字符串模拟打印过程;
(2)递归打印全排列;
描述:给定一个链表和一个节点,删除该节点
思路:将需要删除节点的下一个节点内容复制到需要删除节点,然后删除下一个节点。注意考虑边界情况:删除节点是尾节点;链表只有一个节点;
思路:两个指针一个从前扫,另外一个从后扫。将判断条件单独写为一个函数以方便扩展。
思路:两个指针,一个指针先走k-1步,然后连个指针一起走。注意:边界情况;
注意:边界情况,时刻注意指针的指向;
注意:链表的长度可能不同;
描述:输入两个二叉树,判断B是否是A的子结构(树的一部分,不同于子树)
思路:先找到根节点相同的节点,然后再递归查找
bool SubTree(root1, root2){
bool result = false;
if(root1 != null && root2 != null){
if(root1.val == root2.val){
result = judge(root1, root2);
}
if(!result){
result = SubTree(root1.left, root2);
}
if(!result){
result = SubTree(root1.right, root2);
}
}
return result;
}
bool judge(root1, root2){
if(root2 == null) return true;
if(root1 == null) return false;
if(root1.val != root2.val) return false;
return judge(root1.left,root2.left) && judge(root1.right, root2.right);
}
描述:输入一个二叉树,输出其镜像
思路:左右相互交换
void Mirror(root){
TreeNode tmp = root.left;
root.left = root.right;
root.right = tmp;
if(root.left){
Mirror(root.left);
}
if(root.right){
Mirror(root.right);
}
}
思路:找规律按照索引进行四个方向的打印即可
思路:利用一个辅助栈,每次压入元素时都将最小值放入辅助栈,每次弹出值都将辅助栈的栈顶元素弹出。
if(min.size() == 0 || value < min.top())
min.push(value);
else
min.push(min.top());
思路:模拟。如果下一个弹出数字是栈顶数字直接弹出,如果不是栈顶元素,把压栈序列中还没有入栈的数字压入辅助栈,直到遇到需要弹出的数字位置。如果所有数字都压入栈了仍然没有找到下一个弹出的数字则不是弹出序列。
思路:使用队列
while(queue.size()){
TreeNode node = queue.pop();
print(node);
if(node.left) queue.offer(node.left);
if(node.right) queue.offer(node.right);
}
思路:找到左右子树结构,然后分别进行判断;
思路:回溯法(扫描节点,期望值,路径,当前值)
终止条件:和为目标值且是叶子节点;
往下遍历:如果左右孩子不为空则递归寻找;
回溯:路径中删除当前节点,当前值中减去当前节点的值;
思路:回溯(结果串,需要打印的开始位置)
思路:(1)基于快排求第 n/2 大数;
(2)摩尔计数法;两个变量,一个存储数字,一个存储出现的次数。如果下一个数字等于存储的数字则次数加一,如果不等于次数减一。每一轮循环都要判断次数,如果次数为0,更新保存的数字并把次数置为1;
int result = a[0];
int times = 1;
for(int i = 1; i < length ;i ++){
if(times == 0){
result = a[i];
times = 1;
}else if (a[i] == result){
times ++;
}else{
times --;
}
}
return result;
思路:(1)基于快排思想
(2)构建一个K大小的堆
思路:(1)一直累和,如果和小于等于0则令和等于当前值,并更新最大值;
int sum = 0;
int max = 0;
for(int i = 0; i < length ; i ++){
if(sum <= 0) sum = a[i];
else sum += a[i];
if(sum > max) max = sum;
}
return max;
(2)动态规划。
状态定义:dp[i]表示以第i个数字结尾的最大和
转移方程: i==0 || dp[i-1]<0 dp[i] = a[i];
dp[i-1] > 0 dp[i]=dp[i-1]+a[i];
思路:寻找规律利用递归
思路:改写大于,小于和等于的形式进行排序
思路:(1)逐个判断是否是丑数;
(2)用数组保存已有的丑数并不断生成;
思路:第一遍使用哈希表进行计数;第二遍寻找第一个出现的字符;
思路:参考归并排序
思路:(1)使用hashset将第一个链表所有节点放入,然后搜索第二链表;
(2)采用两个辅助栈;
(3)先遍历两个链表得到他们的长度然后再比较;
(4)两边遍历,到头之后再从另外一个链表头遍历;
思路:(1)二分查找找第一次出现的位置和最后一次出现的位置;
思路:递归判断
int depth(root){
if(root == null) return 0;
int left = depth(root.left);
int right = depth(root.right);
return left > right ? left + 1 : right + 1;
}
思路:异或运算;
思路:双指针
如果求某个序列等于目标值,双指针,如果连个指针之间的和大于目标值则增大左指针,如果小于目标值则增大右指针,相等之后打印并增大右指针。
思路:先翻转整个句子,然后再翻转每个单词;
旋转一个字符串,两边翻转。
思路:1–6的排列组合问题
思路:采用数字进行模拟
描述:0,n-1个数排成一个环,每次删除第m个数字。
思路:(1)用环形链表模拟;
(2)巧妙的方法
int last(int n , int m){
if(n < 1 || m < 1) return -1;
int last = 0;
for(int i = 2; i <= n ;i ++){
last = (last+m)%i;
}
return last;
}
int add (int a , int b){
int sum;
int carry;
do{
sum = a ^b;
carry = (a&b) <<1;
a = sum;
b = carry;
}while(b != 0);
return a;
}
思路:(1)二叉搜索树,判断根节点值的大小进行;
(2)有父指针相当于求交;
(3)找到根节点到两个节点的路径,求两个链表的最后公共节点;