剑指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;
        }   
    }

这里写图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值