左程云算法Day5

本文探讨了单链表相交问题的解决方案,通过计算链表长度和双指针法找到相交节点。同时,介绍了判断链表是否有环的方法,包括哈希表和快慢指针策略。此外,详细阐述了二叉树的先序、中序和后序遍历,分别给出了递归和非递归的实现方式。最后,提到了二叉树的宽度有限遍历及其实现策略。
摘要由CSDN通过智能技术生成

单链表相交问题

题目:给定两个可能有环也可能无环的单链表,头节点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;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值