牛客网常见面试题之链表操作

目录

1. 反转链表19

2. 翻转指定区间29

3.k个一组翻转40

4.合并有序链表47

5.合并k个有序00

6.判断是否有环

7.找环的入口18

8.查找倒数第k个28

9.删除倒数第k个32

10.两个链表的第一个节点15

11.链表相加 23

12.判断链表回文33

13.链表奇偶重排51

14. 删除重复元素155

15.删除重复元素202

16.单链表的排序09

总结:


1. 反转链表19
 if(head==null || head.next==null) return head;

        ListNode now =head;
        ListNode next = head.next;

        ListNode n =null;


        while(next!=null){
            now.next=n;
            n=now;
            now=next;
            next=next.next;

        }

        now.next=n;
        return now;
2. 翻转指定区间29
public ListNode reverseBetween (ListNode head, int m, int n) {
        // write code here
        ListNode dummy=new ListNode(-1);
        dummy.next=head;

        ListNode pre=dummy,p=head;
        int index=1;
        while(index!=m){
            pre=pre.next;
            p=p.next;
            index++;
        }

        ListNode tail=p;

        while(index<=n){
            ListNode temp=p;
            p=p.next;
            temp.next=pre.next;
            pre.next=temp;
            index++;
        }

        tail.next=p;

        return dummy.next;
    }
3.k个一组翻转40
public ListNode reverseKGroup (ListNode head, int k) {
        // write code here
        int size=0;
        ListNode p=head;
        while(p!=null){
            size++;
            p=p.next;
        }
        if(size<k) return head;

        int index =1;
        ListNode n=null;
        p=head;

        ListNode temp =p;
        while(index<=k){
            temp=p;
            p=p.next;
            temp.next=n;
            n=temp;
            index++;
        }
        head.next=reverseKGroup(p,k);

        return temp;

    }
4.合并有序链表47
public ListNode Merge (ListNode pHead1, ListNode pHead2) {
        // write code here
        ListNode res=new ListNode(-1),p=res;
        ListNode p1=pHead1,p2=pHead2;

        while(p1!=null && p2!=null){
            if(p1.val<=p2.val){
                p.next=p1;
                p1=p1.next;
            }else{
                p.next=p2;
                p2=p2.next;
            }
            p=p.next;
        }
        if(p1==null){
            p.next=p2;
        }
        if(p2==null){
            p.next=p1;
        }
        return res.next;
    }
5.合并k个有序00
 public ListNode mergeKLists (ArrayList<ListNode> lists) {
        // write code here
        if(lists.size()==0) return null;

        PriorityQueue<ListNode> q=new PriorityQueue<>(lists.size(),(ListNode a,ListNode b)->a.val-b.val);

        ListNode res=new ListNode(-1);
        for(ListNode p:lists){
            if(p!=null)
                q.offer(p);
        }

        ListNode p=res;
        while(!q.isEmpty()){
            ListNode temp=q.poll();
            if(temp.next!=null){
                q.offer(temp.next);
            }
            temp.next=null;
            p.next=temp;
            p=p.next;
        }

        return res.next;
    }
6.判断是否有环
 public boolean hasCycle(ListNode head) {
        if(head==null || head.next==null){
            return false;
        }
        ListNode slow=head,fast=head;

        slow=slow.next;
        fast=fast.next.next;

        while(fast!=null && fast.next!=null){
            if(slow==fast) return true;
            slow=slow.next;
            fast=fast.next.next;
        }

        return false;
        
    }
7.找环的入口18
 public ListNode EntryNodeOfLoop(ListNode head) {
        if(head==null || head.next==null){
            return null;
        }
        ListNode slow=head,fast=head;

        slow=slow.next;
        fast=fast.next.next;

        while(fast!=null && fast.next!=null){
            if(slow==fast) {
                return getEntrance(slow,head);
            }
            slow=slow.next;
            fast=fast.next.next;
        }

        return null;
    }
    public ListNode getEntrance(ListNode p,ListNode head) {
        ListNode slow1=head,slow2=p;
        while(slow1!=slow2){
            slow1=slow1.next;
            slow2=slow2.next;
        }
        return slow1;
    }
8.查找倒数第k个28
public ListNode FindKthToTail (ListNode pHead, int k) {
        // write code here
        if(pHead==null) return null;

        ListNode p1=pHead,p2=pHead;
        while(k--!=0){
            if(p2==null){
                return null;
            }
            p2=p2.next;
            
        }
        while(p2!=null){
            p1=p1.next;
            p2=p2.next;
        }
        return p1;
    }
9.删除倒数第k个32
public ListNode removeNthFromEnd (ListNode pHead, int k) {
        // write code here
        if(pHead==null) return null;

        ListNode p1=pHead,p2=pHead,dummy=new ListNode(-1),p=dummy;
        dummy.next=pHead;
        while(k--!=0){
            if(p2==null){
                return null;
            }
            p2=p2.next;
            
        }
        while(p2!=null){
            p1=p1.next;
            p2=p2.next;
            p=p.next;
        }

        p.next=p.next.next;
        return dummy.next;
    }
10.两个链表的第一个节点15
public ListNode FindFirstCommonNode(ListNode pHead1, ListNode pHead2) {
        if (pHead1 == null || pHead2 == null ) return null;
        int m = getLen(pHead1), n = getLen(pHead2);
        ListNode p1 = pHead1, p2 = pHead2;
        if (m < n) {
            int t = m;
            m = n;
            n = t;
            p1 = pHead2;
            p2 = pHead1;
        }

        while (m != n) {
            p1 = p1.next;
            m--;
        }
        while (p1 != p2) {
            p1 = p1.next;
            p2 = p2.next;
            if (p1 == null || p2 == null) return null;
        }
        return p1;
    }

    private int getLen(ListNode pHead1) {
        // TODO
        int m = 0;
        ListNode p = pHead1;
        while (p != null) {
            m++;
            p = p.next;
        }
        return m;

    }
11.链表相加 23
 public ListNode addInList (ListNode head1, ListNode head2) {
        // write code here
        ListNode p1 = reverse(head1);
        ListNode p2 = reverse(head2);

        ListNode res = new ListNode(-1);
        ListNode p = res;
        int flag = 0;
        while (p1 != null && p2 != null) {
            int t = p1.val + p2.val + flag;
            ListNode temp = new ListNode(t % 10);
            flag = t / 10;
            p.next = temp;
            p = p.next;
            p1=p1.next;
            p2=p2.next;
        }
        while (p1 != null ) {
            int t = p1.val + flag;
            ListNode temp = new ListNode(t % 10);
            flag = t / 10;
            p.next = temp;
            p = p.next;
             p1=p1.next;
        }
        while (p2 != null) {
            int t = p2.val + flag;
            ListNode temp = new ListNode(t % 10);
            flag = t / 10;
            p.next = temp;
            p = p.next;
            p2=p2.next;
        }
        if(flag!=0){
            ListNode temp = new ListNode(flag);
            p.next = temp;
            p = p.next;
        }
        res =res.next;
        return reverse(res);

    }
12.判断链表回文33
public boolean isPail (ListNode head) {
        // write code here
        if(head==null||head.next==null) return true;
        ListNode re=ReverseList(head);
        while(re!=null){
            if(re.val!=head.val) return false;
            re=re.next;
            head=head.next;
        }
        return true;
        
    }

    public ListNode ReverseList (ListNode head) {
        // write code here
      
        ListNode now =head;
        ListNode res = new ListNode(-1);

        while(now!=null){
            ListNode t = new ListNode(now.val);
            t.next=res.next;
            res.next=t;
            now=now.next;
        }

        return res.next;

    }
13.链表奇偶重排51
public ListNode oddEvenList (ListNode head) {
        // write code here

        ListNode temp=new ListNode(-1),p=head,dummy=new ListNode(-1);
        dummy.next=head;
         ListNode pre=dummy,temp_t=temp;
        int index=1;
        while(p!=null){
            if(index%2==0){
                ListNode t=p;
                pre.next=pre.next.next;
                p=p.next;
                index++;
                t.next=null;
                temp_t.next=t;
                temp_t=temp_t.next;

            }else{
                pre=pre.next;
                p=p.next;
                index++;
            }
        }
        pre.next=temp.next;

        return dummy.next;
    }
14. 删除重复元素155
public ListNode deleteDuplicates (ListNode head) {
        // write code here
        if(head==null) return null;
        ListNode p=head,n=p.next;
        while(n!=null){
            if(n.val==p.val){
                n=n.next;
                p.next=p.next.next;
            }
            else{
                p=p.next;
                n=p.next;
            }
        }
        return head;

    }
15.删除重复元素202
public ListNode deleteDuplicates (ListNode head) {
        // write code here
        ListNode dummy=new ListNode(-1);
        dummy.next=head;

        if(head==null) return null;
        ListNode pre=dummy,p=head,n=p.next;
        while(n!=null){
            int flag=0;
            while(n!=null && n.val==p.val){
                n=n.next;
                flag=1;
            }
            if(flag==1){
                pre.next=n;
                p=n;
                if(n==null){
                    break;
                }
                n=p.next;
            }
            else{
                pre=pre.next;
                p=p.next;
                n=p.next;
            }
        }
        return dummy.next;
    }
16.单链表的排序09
 public ListNode sortInList (ListNode head) {
        // write code here
        PriorityQueue<ListNode> q=new PriorityQueue<>((ListNode a,ListNode b)->a.val-b.val);
        ListNode res=new ListNode(-1);
        while(head!=null){
            ListNode t=head;
            head=head.next;
            t.next=null;
            q.offer(t);
        }
        ListNode p=res;
        while(!q.isEmpty()){
             ListNode t=q.poll();
             p.next=t;
             p=p.next;
        }

        return res.next;
       
    }

总结:

1. 链表问题主要在于判空和指针复位;

2.判空主要出现在:

        1. 初始数据可能为空;

        2. 遍历过程中要使用p.val或者p.next的时候p不能为空;

        3.特殊一点的for each 遍历的时候也不能为空;

3.指针复位:

        下一次判断的时候所有指针要复位;

4.删除需要前指针,第一个节点有时候需要虚拟指针来方便统一操作;

5. 主要知识点:

        1.双指针;

        2.快慢指针;

        3.头插法;

        4.指针遍历;

       

题目来源于:

牛客网在线编程_算法篇_面试必刷TOP101

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值