参考连接思路,从头到尾实现了链表的相关操作。[http://blog.csdn.net/fightforyourdream/article/details/16843303]
通过集中式的训练,对于链表类题目有了比较系统的认识和理解,很有帮助,便于以后巩固复习,后边几个例子没有进行测试。。
package com.xpn.linklist;
import java.awt.HeadlessException;
import java.util.HashMap;
import java.util.Stack;
/**
* http://blog.csdn.net/luckyxiaoqiang/article/details/7393134 轻松搞定面试中的链表题目
* http://www.cnblogs.com/jax/archive/2009/12/11/1621504.html 算法大全(1)单链表
*
* 目录:
* 1. 求单链表中结点的个数: getListLength
* 2. 将单链表反转: reverseList(遍历),reverseListRec(递归)
* 3. 查找单链表中的倒数第K个结点(k > 0): reGetKthNode
* 4. 查找单链表的中间结点: getMiddleNode
* 5. 从尾到头打印单链表: reversePrintListStack,reversePrintListRec(递归)
* 6. 已知两个单链表pHead1 和pHead2 各自有序,把它们合并成一个链表依然有序: mergeSortedList, mergeSortedListRec
* 7. 判断一个单链表中是否有环: hasCycle
* 8. 判断两个单链表是否相交: isIntersect
* 9. 求两个单链表相交的第一个节点: getFirstCommonNode
* 10. 已知一个单链表中存在环,求进入环中的第一个节点: getFirstNodeInCycle, getFirstNodeInCycleHashMap
* 11. 给出一单链表头指针pHead和一节点指针pToBeDeleted,O(1)时间复杂度删除节点pToBeDeleted: delete
*
*/
public class Main {
private static class Node {
int val;
Node next;
public Node(int val) {
this.val = val;
}
}
/**
* @param args
*/
public static void main(String[] args) {
Node n1 = new Node(1);
Node n2 = new Node(2);
Node n3 = new Node(3);
Node n4 = new Node(4);
Node n5 = new Node(5);
n1.next = n2;
n2.next = n3;
n3.next = n4;
n4.next = n5;
printList(n1);
Node n21 = new Node(1);
Node n22 = new Node(2);
Node n23 = new Node(3);
Node n24 = new Node(4);
Node n25 = new Node(5);
n21.next = n22;
n22.next = n23;
n23.next = n24;
n24.next = n25;
//printList(getMiddleNode(n1));
printList(mergeSortedListRec(n1,n21));
System.out.println();
/*reversePrintListRec(n1);
reversePrintListStack(n1);*/
}
//1. 求单链表中结点的个数: getListLength
private static int getListLength(Node head) {
int len=0;
Node cur=head;
while(cur!=null){
len++;
cur=cur.next;
}
return len;
}
private static void printList(Node head) {
while(head!=null){
System.out.print(head.val+ " ");
head=head.next;
}
System.out.println();
}
//2. 将单链表反转: reverseList(遍历),reverseListRec(递归)
private static Node reverseList(Node head) {
if(head==null||head.next==null)
return head;
Node pre=new Node(0);//保存前面已经逆序的节点
Node cur=head;//当前节点
Node tmp=null;//保存当前节点的下一个节点
while(cur!=null){
tmp=cur.next;
cur.next=pre;
pre=cur;
cur=tmp;
}
head.next=null;
return pre;
}
private static Node reverseListRec(Node head) {
if(head==null||head.next==null)
return head;
Node rehead =reverseList(head.next);
head.next.next=head;
head.next=null;
return rehead;
}
//3. 查找单链表中的倒数第K个结点(k > 0): reGetKthNode
private static Node reGetKthNode(Node head,int k){
if(head==null||k<=0)
return null;
Node slow=head;
Node fast=head;
while(0<k--){
if(fast==null)
return null;
fast=fast.next;
}
while(fast!=null){
fast=fast.next;
slow=slow.next;
}
return slow;
}
//4. 查找单链表的中间结点: getMiddleNode
private static Node getMiddleNode(Node head) {
if(head==null||head.next==null||head.next.next==null)
return head;
Node slow=head;
Node fast=head;
while(fast.next!=null&&fast.next.next!=null){
fast=fast.next.next;
slow=slow.next;
}
return slow;
}
//5. 从尾到头打印单链表: reversePrintListStack,reversePrintListRec(递归)
private static void reversePrintListStack(Node head){
if(head==null)
return;
Stack<Node> stacks=new Stack<Node>();
Node cur=head;
while (cur!=null) {
stacks.push(cur);
cur=cur.next;
}
while(!stacks.empty()){
System.out.print(stacks.pop().val+" ");
}
System.out.println();
}
private static void reversePrintListRec(Node head){
if(head==null)
return;
reversePrintListRec(head.next);
System.out.print(head.val+" ");
}
//6. 已知两个单链表pHead1 和pHead2 各自有序,把它们合并成一个链表依然有序: mergeSortedList, mergeSortedListRec
private static Node mergeSortedList(Node pHead1,Node pHead2) {
if(pHead1==null)
return pHead2;
if(pHead2==null){
return pHead1;
}
Node dummy=new Node(0);
Node cur=dummy;//保存整合的链表
Node p1=pHead1;
Node p2=pHead2;
while(p1!=null&&p2!=null){
if(p1.val<p2.val){
cur.next=p1;
p1=p1.next;
}else {
cur.next=p2;
p2=p2.next;
}
cur=cur.next;
}
if(p1!=null){
cur.next=p1;
}
if(p2!=null){
cur.next=p2;
}
return dummy.next;
}
private static Node mergeSortedListRec(Node pHead1,Node pHead2) {
if(pHead1==null)
return pHead2;
if(pHead2==null)
return pHead1;
Node dummy=new Node(0);
if(pHead1.val>pHead2.val){
dummy.next=pHead2;
pHead2.next=mergeSortedListRec(pHead1, pHead2.next);;
}else {
dummy.next=pHead1;
pHead1.next=mergeSortedListRec(pHead1.next, pHead2);;
}
return dummy.next;
}
//7. 判断一个单链表中是否有环: hasCycle
private static boolean hasCycle(Node head){
if(head==null||head.next==null||head.next.next==null)
return false;
Node slow=head;
Node fast=head;
while(fast!=null&&fast.next!=null){
if(fast==slow){
return true;
}
slow=slow.next;
fast=fast.next.next;
}
return false;
}
//8. 判断两个单链表是否相交: isIntersect 思路:最后一个必定相交
private static boolean isIntersect(Node head1,Node head2){
if(head1==null||head2==null)
return false;
while(head1.next!=null){
head1=head1.next;
}
while (head2.next!=null) {
head2=head2.next;
}
if(head1==head2){
return true;
}
return false;
}
//9. 求两个单链表相交的第一个节点: getFirstCommonNode,思路:计算长度,
private static Node getFirstCommonNode(Node head1,Node head2){
if(head1==null||head2==null)
return null;
int len1=0;
Node tail1=head1;
while(tail1!=null){
tail1=tail1.next;
len1++;
}
int len2=0;
Node tail2=head2;
while(tail2!=null){
tail2=tail2.next;
len2++;
}
if(tail1!=tail2){//不相交的情况
return null;
}
int k;
if(len1>len2){
k=len2-len1;
while(0<k--){
head1=head1.next;
}
}else {
k=len1-len2;
while(0<k--){
head2=head2.next;
}
}
while(head1!=head2){
head1=head1.next;
head2=head2.next;
}
return head1;
}
//10. 已知一个单链表中存在环,求进入环中的第一个节点: getFirstNodeInCycle, getFirstNodeInCycleHashMap
private static Node getFirstNodeInCycle(Node head){
Node slow=head;
Node fast=head;
while(slow!=fast){
if(slow==null||fast.next==null)
return null;
slow=slow.next;
fast=fast.next.next;
}
Node p1=head;
while(p1!=slow){
p1=p1.next;
slow=slow.next;
}
return p1;
}
private static Node getFirstNodeInCycleHashMap(Node head){
HashMap<Node, Boolean> maps=new HashMap<Node, Boolean>();
Node cur=head;
while(cur!=null){
if(maps.get(cur)){
return cur;
}
maps.put(cur, true);
cur=cur.next;
}
return null;
}
//11. 给出一单链表头指针pHead和一节点指针pToBeDeleted,O(1)时间复杂度删除节点pToBeDeleted: delete
//变换思路,交换值,然后删除
private static void delete(Node head,Node pToBeDeleted){
if(head==null||pToBeDeleted==null){
return;
}
if(pToBeDeleted.next==null){
//遍历
Node dummy=new Node(0);
Node pre=dummy;
pre.next=head;
while(pre.next!=pToBeDeleted){
pre=pre.next;
}
pre.next=pToBeDeleted.next;
head=dummy.next;
}else {
Node tmpNode=pToBeDeleted.next;
pToBeDeleted.val=tmpNode.val;
pToBeDeleted.next=tmpNode.next;
}
}
}