定义链表的结构体:
public class Linked{
private int data;
private Linked next;
public void setData(int data){
this.data = data;
}
public int getData(){
return data;
}
public void setNext(Linked next){
this.next = next;
}
public Linked getNext(){
return next;
}
}
合并两个有序链表:
//利用递归实现两个链表的合并
public static Linked mergeTwoList(Linked pHead1, Linked pHead2){
if(pHead1==null){//如果两个链表其中有一个是空,直接返回另一个
return pHead2;
}else if(pHead2 == null){
return pHead1;
}
Linked pHead = null;//新开辟一个链表用来存储合并后的链表
if(pHead1.val <= pHead2.val){
pHead = pHead1;
pHead.next = mergeTwoList(pHead1.next, pHead2);
}else{
pHead = pHead2;
pHead.next = mergeTwoList(pHead1, pHead2.next);
}
return pHead;
}
//利用非递归实现两个链表的合并
public static Linked mergeTwoLists(Linked pHead1, Linked pHead2){
if(pHead1==null){//如果两个链表中有一个为空直接返回
return pHead2;
}else if(pHead2==null){
return pHead1;
}
Linked pHead = null;//声明合并链表的头结点
//将pHead1和pHead2中最小的节点复制给头结点
if(pHead1.val <= pHead2.val){
pHead = pHead1;
pHead1 = pHead1.next;
}else{
pHead = pHead2;
pHead2 = pHead2.next;
}
Linked tmp = pHead;//进行合并
while(pHead1 != null && pHead2 != null){
if(pHead1.val <= pHead2.val){
tmp.next = pHead1;
pHead1 = pHead1.next;
}else{
tmp.next = pHead2;
pHead2 = pHead2.next;
}
tmp = tmp.next;
tmp.next = null;
}
if(pHead1!=null && pHead2==null){
tmp.next = pHead1;
}else if(pHead2!=null && pHead1==null){
tmp.next = pHead2;
}
return pHead;
}
//实现链表的逆序打印
//实现链表的逆序打印
public static void reversePrintListNode(Linked head){
if(head == null){
return;
}
Stack<Integer> stack = new Stack<Integer>();
while(head!=null){
stack.push(head.data);
head = head.next;
}
while(!stack.isEmpty()){
System.out.print(stack.pop()+" ");
}
}
//在O(1)的时间内删除链表中指定节点
//删除链表中指定节点
//对于删除节点,我们的思路就是让该节点的前一个节点指向该节点的下一个节点
public static void deleteNodeForO1(Linked head, Linked toDelete){
if(toDelete == null){
return;
}
if(toDelete.next != null){//要删除的节点不是尾节点
toDelete.data = toDelete.next.data;
toDelete.next = toDelete.next.next;
}else if(head == toDelete){//链表中只有一个节点即是头结点又是尾节点
head = null;
}else{//要删除的节点是尾节点
Linked node = head;
while(node.next!=toDelete){//找到倒数第二个节点
node = node.next;
}
node.next = null;
}
}
//查找单链表中倒数第k个节点或者遍历单链表将结点放入ArrayList中,最后利用list.get()方法得到
//查找单链表中倒数第k个节点
public static Linked findCountDownKNode(Linked head, int k){
if(head == null || k <= 0){
return null;
}
//都指向头结点
Linked preNode = head;
Linked lastNode = head;
for(int i = 1; i < k; i++){//preNode先走k-1步
if(preNode.next != null){
preNode = preNode.next;
}else{
return null;
}
}
while(preNode.next!=null){
//然后一起走,preNode为null,lastNode即为目标
preNode = preNode.next;
lastNode = lastNode.next;
}
return lastNode;
}
//借助于外部存储ArrayList找到链表倒数第k个结点
public static Linked findCountDownKNode(Linked pHead, int k){
if(pHead==null || k < 0){
return null;
}
ArrayList<Linked> list = new ArrayList<Linked>();
while(pHead!=null){
list.add(pHead);
pHead = pHead.next;
}
return list.get(list.size()-k);
}
//实现单链表的逆置
//实现单链表的逆置
public static Linked reverseList(Linked head){
if(head == null){//空直接返回null
return null;
}
if(head.next == null){//一个节点直接返回头节点
return head;
}
Linked pPre = null;//记录前一个节点
Linked p = head;
Linked newHead = null;
while(p!=null){
Linked pNext = p.next;//记录当前节点的下一个节点
if(pNext==null){
newHead = p;
}
p.next = pPre;//这里的方向已经转变
pPre = p;
p = pNext;//将保存的后面的节点作为下一次循环的p
}
return newHead;
}
//删除奇数位置或者偶数位置的单链表
public static Linked deleleNode(Linked head){
Linked l1 = new Linked();
Linked l2 = new Linked();
Linked p1 = l1;
Linked p2 = l2;
Linked p = head.next;
int i = 1;
while(p != null){
if(i%2 == 1){
p1.next = p;
p1 = p1.next;
}else{
p2.next = p;
p2 = p2.next;
}
i++;
p = p.next;
}
p1.next = null;
p2.next = null;
return p1;
}
//判断一个单向链表是否形成了环形结构,定义快慢指针进行解决
public static boolean isCircleList(Linked pHead){
if(pHead == null){
return false;
}
Linked pNode = pHead;//慢指针
Linked qNode = pHead;//快指针
while(qNode.next!=null){
if(qNode.next.next!=null){
qNode = qNode.next.next;
}else{
return false;
}
if(qNode == pNode){
return true;
}
pNode = pNode.next;
}
return false;
}
//找到两个链表中的第一个公共结点,利用栈的先进后出特性找到第一个公共结点
//找到两个链表中的第一个公共结点,利用栈的先进后出特性找到第一个公共结点
public static Linked findCommonLinkedNode(Linked pHead1, Linked pHead2){
if(pHead1 == null || pHead2 == null){//如果有一个链表为空直接返回
return null;
}
//借助于栈存储两个链表
Stack<Linked> stack1 = new Stack<Linked>();
Stack<Linked> stack2 = new Stack<Linked>();
while(pHead1!=null){//将链表1的结点放入栈中
stack1.push(pHead1);
pHead1 = pHead1.next;
}
while(pHead2!=null){//将链表2的结点放入栈中
stack2.push(pHead2);
pHead2 = pHead2.next;
}
Linked l3 = null;//保存公共链表的结点
while(!stack1.isEmpty()){//利用栈的先进后出特性
Linked l1 = stack1.peek();
Linked l2 = stack2.peek();
if(l1==l2){
l3 = stack1.pop();//保存公共结点
stack2.pop();
continue;
}
return l3;//最后一个公共结点
}
return null;
}
//复制复杂链表
public class Node {
public int m_nValue;
public Node m_pNext;
public Node m_pSibling;
public Node() {}
public Node(int m_nValue) {
super();
this.m_nValue = m_nValue;
}
}
public Node clone(Node pHead) {
if (pHead == null) {
return null;
}
HashMap<Node, Node> map = new HashMap<Node, Node>();
Node pClonedHead = new Node(pHead.m_nValue);//复制链表的头结点
Node pNode = pHead, pClonedNode = pClonedHead;
map.put(pNode, pClonedNode);
// 第一步,hashMap保存,原链表节点映射复制链表节点
while (pNode.m_pNext != null) {
pClonedNode.m_pNext = new Node(pNode.m_pNext.m_nValue);
pNode = pNode.m_pNext;
pClonedNode = pClonedNode.m_pNext;
map.put(pNode, pClonedNode);
}
// 第二步:找到对应的m_pSibling
pNode = pHead;
pClonedNode = pClonedHead;
while (pClonedNode != null) {
pClonedNode.m_pSibling = map.get(pNode.m_pSibling);
pNode = pNode.m_pNext;
pClonedNode = pClonedNode.m_pNext;
}
return pClonedHead;
}
//删除链表中重复的结点
//删除链表中重复的结点
public static Linked deleteRepeatNode(Linked pHead){
if(pHead == null){//如果链表为空直接返回
return null;
}
Linked preNode = null;
Linked node = pHead;
while(node!=null){
if(node.next!=null && node.val==node.next.val){
int val = node.val;//结点重复
while(node.next!=null && node.next.val==val){
node = node.next;
}
if(preNode == null){
pHead = node.next;
}else{
preNode.next = node.next;
}
}else{//不重复继续向下走
preNode=node;
}
node = node.next;//指向下一个结点
}
return pHead;
}
//利用快慢指针找到链表的中间结点
//利用快慢指针找到链表的中间结点
public static Linked getMidNode(Linked pHead){
if(pHead == null){
return null;
}
Linked pNode = pHead;//慢指针
Linked qNode = pHead;//快指针
while(qNode.next!=null){
if(qNode.next.next!=null){
pNode = pNode.next;
qNode = qNode.next.next;
}else{
pNode = pNode.next;//处理只有两个结点的情况
}
}
return pNode;
}
//判断链表中环的入口
public Linked EntryNodeOfLoop(Linked pHead) {
HashSet<Linked> set = new HashSet<Linked>();
while (pHead != null) {
if (!set.add(pHead)) {
return pHead;
}
pHead = pHead.next;
}
return null;
}
public Linked EntryNodeOfLoop1(Linked pHead) {
if (pHead == null || pHead.next == null)
return null;
Linked p1 = pHead;
Linked p2 = pHead;
while (p2 != null && p2.next != null) {
p1 = p1.next;
p2 = p2.next.next;
if (p1 == p2) {
p2 = pHead;
while (p1 != p2) {
p1 = p1.next;
p2 = p2.next;
}
if (p1 == p2)
return p1;
}
}
return null;
}