算法整理-单链表相关

参考连接思路,从头到尾实现了链表的相关操作。[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;
        }
    }

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值