1. 程式人生 > >劍指offer中 與連結串列有關的程式設計練習題 Java編碼

劍指offer中 與連結串列有關的程式設計練習題 Java編碼

(1)從尾到頭列印連結串列

題目描述

輸入一個連結串列,從尾到頭列印連結串列每個節點的值。
思想:用棧來儲存節點,順序出棧就為從尾到頭列印節點值


     public static void main(String[] arg) {
         ListNode a=new ListNode(0);
         a.next=new ListNode(1);
         a.next.next=new ListNode(2);
         a.next.next.next=new ListNode(3);
         a.next.next.next
.next=new ListNode(4); a.next.next.next.next.next=new ListNode(5); System.out.println("從後向前列印連結串列的節點"); printListFromTailToHead(a); } private static void printListFromTailToHead(ListNode a) { if(a==null) { return ; } Stack<ListNode> stack=new
Stack<ListNode>(); while(a!=null) { stack.push(a); a=a.next; } while(!stack.isEmpty()) { System.out.print(stack.pop().val+" "); } }

這裡寫圖片描述

(2)連結串列中倒數第k個結點

題目描述

輸入一個連結串列,輸出該連結串列中倒數第k個結點。
思路:先計數連結串列的節點,倒數第k個節點,即為正數n-k個節點

     public static void main(String[] arg) {
         ListNode a=new ListNode(0);
         a.next=new ListNode(1);
         a.next.next=new ListNode(2);
         a.next.next.next=new ListNode(3);
         a.next.next.next.next=new ListNode(4);
         a.next.next.next.next.next=new ListNode(5);
         System.out.println("連結串列中倒數第k個結點");
         FindKthToTail(a,5);
     }

    private static void FindKthToTail(ListNode a, int k) {
        if(a==null) {
            return ;
        }
        int count=0;
        ListNode ln=a;
        while(ln!=null) {
            count++;
            ln=ln.next;
        }
        ListNode lo=a;
        for(int i=0;i<count;i++) {
            if(i==k-1) {
                System.out.println(lo.val+"此時,k的值為"+k);
            }
            lo=lo.next;
        }
    }

這裡寫圖片描述

(3)反轉連結串列

題目描述

輸入一個連結串列,反轉連結串列後,輸出連結串列的所有元素。
思路:連結串列操作

     public static void main(String[] arg) {
         ListNode a=new ListNode(0);
         a.next=new ListNode(1);
         a.next.next=new ListNode(2);
         a.next.next.next=new ListNode(3);
         a.next.next.next.next=new ListNode(4);
         a.next.next.next.next.next=new ListNode(5);
         System.out.println("反轉連結串列:");
         ReverseList(a);
     }

    private static void ReverseList(ListNode pHead) {
        if(pHead==null) {
            return ;
        }
        ListNode pre=null;
        ListNode next=null;
        while(pHead!=null) {
            next=pHead.next;//用next來儲存pHead的下一個節點
            pHead.next=pre;//pHead.next指向pre實現反轉
            pre=pHead;//依次移動到下一節點
            pHead=next;
        }
        while(pre!=null) {
            System.out.print(pre.val+" ");
            pre=pre.next;
        }
    }

這裡寫圖片描述

(3)合併兩個排序的連結串列

題目描述

輸入兩個單調遞增的連結串列,輸出兩個連結串列合成後的連結串列,當然我們需要合成後的連結串列滿足單調不減規則。


     public static void main(String[] arg) {
         ListNode a=new ListNode(1);
         a.next=new ListNode(3);
         a.next.next=new ListNode(5);
         a.next.next.next=new ListNode(7);
         a.next.next.next.next=new ListNode(9);
         a.next.next.next.next.next=new ListNode(11);

         ListNode b=new ListNode(0);
         b.next=new ListNode(2);
         b.next.next=new ListNode(4);
         b.next.next.next=new ListNode(6);
         b.next.next.next.next=new ListNode(8);
         b.next.next.next.next.next=new ListNode(10);
         System.out.println("合併連結串列");
         Merge(a,b);
     }

    private static void Merge(ListNode a, ListNode b) {
        if(a==null&&b==null) {
            return ;
        }
        if(a!=null&&b==null) {
            return ;//這裡自己寫,我暫時返回空
        }
        if(a==null&&b!=null) {
            return ;//這裡自己寫,我暫時返回空
        }
        if(a!=null&&b!=null) {
            ListNode p=new ListNode(-1);
            ListNode ln=p;
            while(a!=null&&b!=null) {
                if(a.val<b.val) {
                    ln.next=a;
                    a=a.next;
                }else {
                    ln.next=b;
                    b=b.next;
                }
                ln=ln.next;
            }
            if(a!=null) {
                ln.next=a;
            }
            if(b!=null) {
                ln.next=b;
            }
            while(p.next!=null) {
                System.out.print(p.next.val+" ");
                p.next=p.next.next;
            }
        }
    }

這裡寫圖片描述

(4)複雜連結串列的複製

題目描述

輸入一個複雜連結串列(每個節點中有節點值,以及兩個指標,一個指向下一個節點,另一個特殊指標指向任意一個節點),返回結果為複製後複雜連結串列的head。(注意,輸出結果中請不要返回引數中的節點引用,否則判題程式會直接返回空)

public RandomListNode Clone(RandomListNode pHead)
    {
        if(pHead==null){
            return null;
        }
       RandomListNode p=pHead;
        RandomListNode t=pHead; 
        while(p!=null){//複製節點
           RandomListNode q=new RandomListNode(p.label);
            q.next=p.next;
            p.next=q;
            p=q.next;
        }
        while(t!=null){
            RandomListNode q=t.next;
            if(t.random!=null){
                q.random=t.random.next;
            }
            t=q.next;
        }
        RandomListNode s=new RandomListNode(0);
        RandomListNode s1=s;
        while(pHead!=null){
            RandomListNode q=pHead.next;
            s.next=q;
             pHead.next=q.next;//原來的指向斷開,目的使得pHead可以順利指向源列表的下一節點
            s=s.next;
            pHead=pHead.next;
        }
        return s1.next; 
    }

這裡寫圖片描述

(5)兩個連結串列的第一個公共結點

題目描述

輸入兩個連結串列,找出它們的第一個公共結點。


     public static void main(String[] arg) {
         ListNode a=new ListNode(1);
         a.next=new ListNode(3);
         a.next.next=new ListNode(5);
         a.next.next.next=new ListNode(7);
         a.next.next.next.next=new ListNode(9);
         a.next.next.next.next.next=new ListNode(11);

         ListNode b=new ListNode(5);
         b.next=new ListNode(2);
         b.next.next=new ListNode(4);
         b.next.next.next=new ListNode(6);
         b.next.next.next.next=new ListNode(8);
         b.next.next.next.next.next=new ListNode(10);
         System.out.println("兩個連結串列的第一個公共結點:");
         FindFirstCommonNode(a,b);
     }

    private static void FindFirstCommonNode(ListNode a, ListNode b) {
        if(a==null||b==null) {
            return ;
        }
        ArrayList<Integer> list=new ArrayList<Integer>();
        while(a!=null) {
            list.add(a.val);
            a=a.next;
        }   
        while(b!=null) {
            if(list.contains(b.val)) {
                System.out.print(b.val);
                return ;
            }
            b=b.next;
        }
    }

這裡寫圖片描述

(6)連結串列中環的入口結點

題目描述

一個連結串列中包含環,請找出該連結串列的環的入口結點。
思路:定義兩個節點,同時遍歷一個比一個快一倍,當它們相遇的時候差距為一環的數量,然後將一個置為起點,兩個同時走,相遇的地點即為環的入口。


    public static void main(String[] arg) {
     ListNode a=new ListNode(0);
     a.next=new ListNode(1);
     a.next.next=new ListNode(2);
     a.next.next.next=new ListNode(3);
     a.next.next.next.next=new ListNode(4);
     a.next.next.next.next.next=a.next.next;
     System.out.println("連結串列中環的入口結點為:");
    EntryNodeOfLoop(a);
    }

    private static void EntryNodeOfLoop(ListNode a) {
        if(a==null) {
            return ;
        }
        ListNode p=a;
        ListNode q=a;
        while(q!=null&&q.next!=null) {
            p=p.next;
            q=q.next.next;
            if(p.val==q.val) {
                q=a;
                while(p.val!=q.val) {
                    p=p.next;
                    q=q.next;
                }
                System.out.print(p.val);
                return ;
            }
        }
    }

這裡寫圖片描述

(7)刪除連結串列中重複的結點

題目描述

在一個排序的連結串列中,存在重複的結點,請刪除該連結串列中重複的結點,重複的結點不保留,返回連結串列頭指標。 例如,連結串列1->2->3->3->4->4->5 處理後為 1->2->5

    public static void main(String[] arg) {
         ListNode a=new ListNode(0);
         a.next=new ListNode(1);
         a.next.next=new ListNode(2);
         a.next.next.next=new ListNode(3);
         a.next.next.next.next=new ListNode(4);
         a.next.next.next.next.next=new ListNode(4);
         System.out.println("連結串列中環的入口結點為:");
         deleteDuplication(a);
        }

    private static void deleteDuplication(ListNode a) {
        if(a==null) {
            return ;
        }
        ListNode first=new ListNode(0);
        first.next=a;
        ListNode pre=a;
        ListNode last=first;
        while(pre!=null) {
            if(pre.val==pre.next.val) {
                int ps=pre.val;
                while(pre!=null&&ps==pre.val) {
                    pre=pre.next;
                }
                last.next=pre;
            }else {
                last=pre;
                pre=pre.next;
            }

        }
        while(first.next!=null) {
            System.out.print(first.next.val+" ");
            first.next=first.next.next;
        }   
    }

這裡寫圖片描述