解码方法有几种
参考题解:leetcode
由于有0的存在,所以更好的方法是从后往前遍历,如果起始是0就返回0;
每一位有2种情况
- 0
dp[i]=0
- other 例如226 则该位的解码要么是自己本身要么是跟后面的2连起来成为22,所以是i+1和i+2的解码数加起来
dp[i]=dp[i+1]+dp[i+2]
;如果该位和后面连起来>26
则dp[i]=dp[i+1]
注意找i+1时不要越界
翻转链表内的区间
LeetCode92. 反转链表2
思路:链表分段,最终形态 x x x start [end x x x pre] cur x x x []中是要翻转的部分
- start 指向m之前的那个节点(或者为空,当m就是头节点时)
- end 指向m节点,也即是反转之后成为区间段尾,要与最终的cur相连的节点
- pre 指向cur的前一个节点,最终指向区间段首
- cur 指向当前操作的节点
具体操作:
pre cur cur.next - 用一个
tmp
指向cur.next
cur.next
指向pre
(反转)- 开始下一个,
pre = cur; cur=tmp;
注意,start的初始值为null
,最后要判断是否是从head开始反转的
如果从start==null
说明是从head开始反转,这时head就成为end,而pre成为head
二叉树的中序遍历(迭代方法)
LeetCode 94. 二叉树中序遍历
用递归方法当然很简单,但有一种通过迭代且不需要辅助栈的方法。
Morris遍历算法
- 当遍历到节点x无左孩子时,表示其已经是最左节点,那么加入结果列表,开始遍历x的右子树
- 如果x有左孩子,那么需要遍历其左子树,为了向左遍历到最后仍然能找到根x(左根右),找到其左子树的最右节点(称为predecessor,即中序遍历中x的前一个节点),将它的右孩子指回x。这样将predecessor加入结果列表之后,紧接着就是将x加入结果列表
需要解决的问题一:如何遍历查找predecessor节点?
实际上就是x节点向左走一个,然后一直向右走
predecessor = root.left;
while(predecessor.right!=null){
predecessor = predecessor.right;
}
问题二:找到predecessor之后怎么做?
找到x的前驱节点,那么就应该开始遍历x的左子树了。
问题三:何时将当前根x加入结果?
当x左子树为空时即可,当x左子树遍历完成,最后一个节点即是predecessor,那么它的右孩子是指向x的。
当再次返回x,我们寻找x的predecessor,发现这个节点竟然是有右孩子的,那么就说明左子树已经走完了。把x加入结果集然后开始遍历x的右子树即可。
if(predecessor.right!=null){
res.add(x.val);
//断开链接
predecessor.right=null;
//开始遍历右子树
x=x.right;
}
总体来看,第一个分支为x是否有左孩子,有,则开始上面的一通操作。没有,则直接加入结果集并开始遍历右子树。