单链表相交问题
题目:给定两个可能有环也可能无环的单链表,头节点head1和head2,请实现一个函数嘛,如果两个链表相交请返回相交的第一个节点,如果不相交,返回null。假设链表长度之和为N,要求时间复杂度达到O(N),额外空间复杂度达到O(1);
1,无环时找到list1 list2点尾节点end1,end2,得到长度l1,l2;,对比end1与end2的地址;若相同,长链表先走差值步,两链表开始遍历,对比内存地址;两个链表在相交点相遇。
相交:两条链表有公共节点
拓展题:判断一个链表是否有环,有环返回入环节点:方法1:使用hash表,每遍历一个点,判断是否在hash表中,若在为有环。方法2:使用快慢指针,若快指针追上慢指针后,快指针回到表头,慢指针留在原地;然后两指针每次走一步,两者在入环节点相遇。
mport java.lang.*;
import java.io.*;
/* Name of the class has to be "Main" only if the class is public. */
public class ListNoLoop
{
public static Node listnoloop (Node head1,Node head2)
{
if(head1==null||head2==null){
return;
}
int l1=1;
int l2=1;//length
Node n1=head1;
Node n2=head2;
while(n1.next!=null){
l1++;
n1=n1.next;
}
while(n2.next!=null){
l2++;
n2=n2.next;
}
int m=(l1-l2)>0?(l1-l2):(l2-l1);
cur1=head1;
cur2=head2;
int j=0;
if(l1-l2>0){
j=l2;
for(int i=0,i<=m,i++){
cur1=cur.next;
}
}
else{
j=l1;
for(int i=0,i<m,i++){
cur2=cur2.next
}
}
for(int i=0,i<j,i++){
while(cur1!=cur2){
cur1=cur1.next;
cur2=cur2.next;
}
}
if (cur1!=n1)
return cur1;
else
return null;
// your code goes here
}
}
都是有环链表时:分为两种情况:
1、两头节点同方向,入环节点唯一
思路:两头节点必然在loop之前,所以可以认为这与第一种情况一致
2、两头节不同方向,入环节点有两个,让其中一个头节点一直跑,在其回到入环节点之前,若没有经过链表2的入环节点则认为两条链表没有相交
二叉树:
先序遍历、中序遍历、后序遍历
采用递归实现遍历:递归序:
先序遍历:第一次到达的节点打印出来,重复到达的不打印;
中序遍历:打印第二次到达的节点,第一第三次到达节点什么都不做;
后序遍历;打印第三次到达的节点,第一次、第二次到达的节点不打印
可以直接将递归序加工
public class dgxu{
public static void dgxu(Node root){
if(root==null){
return;
}
dgxu(head.left);
dgxu(head.right);
}
}
//先序遍历
public class PreOrderRecur{
public static void preorderrecur(Node root){
if(root==null){
return;
}
system.out.print(head.value+” ”);
dgxu(head.left);
dgxu(head.right);
}
}
//中序遍历
public class InOrderRecur{
public static void inorderrecur(Node root){
if(root==null){
return;
}
dgxu(head.left);
system.out.print(head.value+” ”);
dgxu(head.right);
}
}
//后序遍历
public class PosOrderRecur{
public static void posorderrecur(Node root){
if(root==null){
return;
}
dgxu(head.left);
dgxu(head.right);
system.out.print(head.value+” ”);
}
}
非递归实现:使用栈
//先序遍历非递归,使用栈
public class PreOrderUnrecur{
public static void preorderunrecur(Node head){
if(head!=null){
Stack<Node> stack = new Stack<Node>();
stack.add(head);
if(!stack.isEmpty()){
head=stack.pop();
system.out.println(head.value);
while(head.right!=null){
stack.push(head.right);
}
while(head.left!=null){
stack.push(head.left);
}
}
}
}
}
非递归实现后序遍历:改造先序遍历,先压左孩子再压右孩子,点那个所有的节点都进入栈后,再倒入另一个栈中,该栈逐个弹出为后序遍历。
非递归实现中序遍历:整棵树的所有左边界子节点压到栈内,然后弹出节点的同时,打印,并对弹出节点的右子树周而复始 。
//非递归实现中序遍历
public class InOrderUnrecur{
public static void inorderunrecur(Node head){
if(head!=null){
Stack<Node> stack = new Stack<Node>();
while(head!=null||!stack.isEmpty){
if(head!=null){
stack.push(head);
head=head.left;
}
else{
head=stack.pop();
System.out.println(head.value);
head=head.right;
}
}
}
}
}
实现二叉树的宽度有限遍历:
记录某个节点所在得多层数可以利用hashmap来实现,每个节点的层数获得:当前节点的子节点所在的层数为当前层数+1;