剑指offer链表专题“(java)

19 篇文章 0 订阅

3.输入一个链表,按链表从尾到头的顺序返回一个ArrayList。
示例1
输入
{67,0,24,58}
返回值
[58,24,0,67]

递归方法
public class Solution {
    public ArrayList<Integer> printListFromTailToHead(ListNode listNode) {
        ArrayList<Integer> res = new ArrayList<>();
        if(listNode != null){
            res = printListFromTailToHead(listNode.next);
            res.add(listNode.val);
        }
        return res;
        }
}

14.输入一个链表,输出该链表中倒数第k个结点。
示例1
输入
1,{1,2,3,4,5}
返回值
{5}

public class Solution { 
    public ListNode FindKthToTail(ListNode head,int k) {
        int count = length(head);
        int i =count-k,icount=0;
        while(head != null){
            if(icount == i) return head;
            head = head.next;
            icount++;
        }
        return null;
    }
    public int length(ListNode head){
       int count =0;
        while(head != null){
            count++;
            head = head.next;
        }
        return count;
    }
}

15.输入一个链表,反转链表后,输出新链表的表头。
示例1
输入
{1,2,3}
返回值
{3,2,1}

//思路
public class Solution {
    public ListNode ReverseList(ListNode head) {
        ListNode pre = null;
        ListNode res = head;
        ListNode next = head.next;
      while(head != null){
        head = pre;
        res = next;
        
      }
        return head;
    }
}
//答案
 public ListNode ReverseList(ListNode head) {
       if(head == null) return null;
       if(head.next == null) return head;
        ListNode pre = null;
        ListNode res = head;
        ListNode next = null;
      while(res != null){
        next = res.next;
        res.next = pre;
          
        pre = res;
        res = next;
      }
        return pre;
    }

25.输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针random指向一个随机节点),请对此链表进行深拷贝,并返回拷贝后的头结点。(注意,输出结果中请不要返回参数中的节点引用,否则判题程序会直接返回空)

   public RandomListNode Clone(RandomListNode pHead) {
        if(pHead == null) {
            return null;
        }
        RandomListNode curNode = pHead;
        RandomListNode nextNode = null;
        //1、复制每个结点,如复制结点A得到A1,将结点A1插到结点A后面;
        while (curNode != null) {
            RandomListNode cloneNode = new RandomListNode(curNode.label);
            nextNode = curNode.next;
            cloneNode.next = nextNode;
            curNode.next = cloneNode;
            curNode = nextNode;
        }
       
        
        curNode = pHead;
        //2、重新遍历链表,复制老结点的随机指针给新结点,如A1.random = A.random.next;
        while(curNode != null) {
            // 为什么是random.next,因为原结点后面紧跟复制的结点
            curNode.next.random = (curNode.random == null ? null : curNode.random.next);
            curNode = curNode.next.next;
        }

        //3、拆分链表,将链表拆分为原链表和复制后的链表
        curNode = pHead;
        RandomListNode cloneHead = pHead.next;
        RandomListNode cloneNode = null;
        while (curNode != null) {
            cloneNode = curNode.next;
            curNode.next = cloneNode.next;
            // 如果cloneNode.next为空的话
            cloneNode.next =  (cloneNode.next == null ? null : cloneNode.next.next);
            curNode = curNode.next;
        }
        return cloneHead;
    }

36.输入两个链表,找出它们的第一个公共结点。(注意因为传入数据是链表,所以错误测试数据的提示是用其他方式显示的,保证传入数据是正确的)

 public ListNode FindFirstCommonNode(ListNode pHead1, ListNode pHead2) {
        ListNode p1 = pHead1;
        ListNode p2 = pHead2;
        while(p1 != p2){
            p1 = (p1 != null)?p1.next:pHead2;
            p2 = (p2 != null)?p2.next:pHead1;
            
        }
        return p1;
    }

46.首先,让小朋友们围成一个大圈。然后,他随机指定一个数m,让编号为0的小朋友开始报数。每次喊到m-1的那个小朋友要出列唱首歌,然后可以在礼品箱中任意的挑选礼物,并且不再回到圈中,从他的下一个小朋友开始,继续0…m-1报数…这样下去…直到剩下最后一个小朋友,可以不用表演,请你试着想下,哪个小朋友会得到这份礼品呢?(注:小朋友的编号是从0到n-1)
如果没有小朋友,请返回-1
示例1
输入
5,3
返回值
3

 public int LastRemaining_Solution(int n, int m) {
        if(n ==0) return -1;
        int res =0;
        for(int i=2; i<=n; i++){
            res = (res +m)%i;
        }
        return res;
    }

55.给一个链表,若其中包含环,请找出该链表的环的入口结点,否则,输出null。

//思路
    public ListNode EntryNodeOfLoop(ListNode pHead)
    {
        ListNode res = null;
        res = Entrynode(pHead,pHead.next);
        return res;
    }
    public ListNode Entrynode(ListNode p1,ListNode p2){
        if(p1 == null || p2 == null) return null;
        while(p1 != p2){
            p1 = p1.next;
            p2 = p2.next.next;
        }
        return p2;
    }
     public ListNode EntryNodeOfLoop(ListNode pHead)
    {
        if(pHead == null || pHead.next == null || pHead.next.next ==null) return null;
        ListNode p1 = pHead;
        ListNode p2 = pHead;
        while(p1 !=  null && p1.next != null && p1.next.next != null){
            p1 = p1.next;
            p2 = p2.next.next;
            if(p1 == p2){
                p1 = pHead;
                while(p1 != p2){
                    p1 = p1.next;
                    p2 = p2.next;
                }
                    if(p1 == p2){
                        return p1;
                    }
                }
     }
        return null;
    }

56.在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针。 例如,链表1->2->3->3->4->4->5 处理后为 1->2->5
示例1
输入
{1,2,3,3,4,4,5}
返回值
{1,2,5}

思路
  public ListNode deleteDuplication(ListNode pHead)
    {
        if(pHead == null) return null;
        if(pHead.next == null) return pHead;
        ListNode pre = pHead;
        while(pre != null && pre.next != null){
            if(pre.val == pre.next.val){
                pre.next = pre.next.next;
            }
            pre = pre.next;
        }
        return pre;
    }  
      public ListNode deleteDuplication(ListNode pHead) {
        if(pHead == null) return null;
        if(pHead.next == null) return pHead;
        ListNode pre = new ListNode(0);
        pre.next = pHead;
        ListNode p = pHead;
        ListNode cur = pre;
        while(p!= null && p.next != null){
            if(p.val == p.next.val){
                int val = p.val;
                while(p != null && p.val == val) 
                    p = p.next;
                    cur.next = p;
                }else{
                    cur= p;
                    p = p.next;
                }
            }
        return pre.next;
    }
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值