【链表专题】百度真题:环形链表分成三等份

本问题对应课程链接:剑指offer刷题第五期

要求:

1、请打卡你的解题代码,如果能简单说一下思路则简单说一下思路。
2、给出你代码所用的时间复杂度和空间复杂度

参考代码

下面是一个完整的代码,包括测试,你们可以直接粘贴运行。

import java.util.*;

public class GetThreeListNode {
    // 核心方法
    // 当节点是 3 的倍数,则均分,当不为3的倍数,比如 1 2 3 4 5 6 7,则分成
    // l1:1 2   l2:3 4   l3:5 6 7
    public static List getThreeListNode(ListNode head){
        //只有一个节点
        if(head.next==head){
            List list = new ArrayList<>();
            head.next = null;//防止返回一个环形链表
            list.add(head);
            list.add(null);
            list.add(null);
            return list;
        }
        // 只有两个节点
        if(head.next.next == head){
            List list = new ArrayList<>();
            ListNode temp =head.next;
            temp.next = null;
            list.add(temp);
            head.next = null;
            list.add(head);
            list.add(null);
            return list;
        }
        ListNode l1 = head;
        ListNode l2 = head.next;
        ListNode l3 = head.next.next;
        int count =1;
        ListNode temp = head;
        // 统计节点个数
        while (head.next!=temp){
            count++;
            head = head.next;
        }
       // System.out.println(count);
        List list= new ArrayList<>();
        // 节点是3的倍数,三个指针,走一步,走两步,走三步来进行切分
        if((count%3)==0){
            while(l3.next!=temp){
                l3 = l3.next.next.next;
                l2 = l2.next.next;
                l1 = l1.next;
            }
            ListNode a1 = l3.next;
            ListNode a2 = l2.next;
            ListNode a3 = l1.next;
            l1.next = null;
            l2.next = null;
            l3.next = null;
            list.add(a1);
            list.add(a2);
            list.add(a3);
        }else{
            int k = (int) Math.round(count*1.0/3)-1;
            while (k!=0){
                l2 = l2.next.next;
                l1 = l1.next;
                k--;
            }
            while(l3.next!=temp){
                l3 = l3.next;
            }
            ListNode a1 = l3.next;
            ListNode a2 = l2.next;
            ListNode a3 = l1.next;
            l1.next = null;
            l2.next = null;
            l3.next = null;
            list.add(a1);
            list.add(a3);
            list.add(a2);
        }


        return list;
    }



    // 测试
    public static void main(String[] args) {
        ListNode l1 = new ListNode(0);
        ListNode l2 = new ListNode(1);
        ListNode l3 = new ListNode(2);
        ListNode l4 = new ListNode(3);
        ListNode l5 = new ListNode(4);
        ListNode l6 = new ListNode(5);
        ListNode l7 = new ListNode(6);
        l1.next = l1;
        //l2.next = l1;
//        l3.next = l4;
//        l4.next = l1;
//        l5.next = l6;
//        l6.next = l7;
//        l7.next = l1;
        List threeListNode = getThreeListNode(l1);
        // 打印
        for(int i = 0; i < threeListNode.size(); i++){
            ListNode head = threeListNode.get(i);
            System.out.println("链表 i = " + i);
            while(head != null){
                System.out.println(head.val);
                head = head.next;
            }
        }
    }

    // ListNode 内部类,用来演示需要
    public static class ListNode{
        int val;
        ListNode next;
        public ListNode(int x){
            this.val = x;
        }
    }
}

共以下 17 个回答

  • sincere 普通 2023年10月15日 下午9:13

    参照题解写的,大概明白流程意思了

    public class GetThreePart {
    
        public static List<ListNode> divideToThree(ListNode head) {
            List<ListNode> list = new ArrayList<>();
            if (head.next == head) {
                head.next = null;// 避免环形列表
                list.add(head);
                list.add(null);
                list.add(null);
                return list;
            }
            if (head.next.next == head) {
                ListNode tmp = head.next;
                tmp.next = null;
                list.add(tmp);
                head.next = null;
                list.add(head);
                list.add(null);
                return list;
            }
            ListNode node1 = head;
            ListNode node2 = head.next;
            ListNode node3 = head.next.next;
            // 统计节点个数
            int count = 1;
            ListNode tmp = head;
            while (tmp.next != head) {
                count++;
                tmp = tmp.next;
            }
            System.out.println("节点个数:" + count);
            if ((count % 3) == 0) {// 刚好为3的倍数 则按照固定间隔取值
                while (node3.next != head) {
                    node3 = node3.next.next.next;
                    node2 = node2.next.next;
                    node1 = node1.next;
                }
            } else {
                int i = (int) Math.round(count * 1.0 / 3) - 1;
                while (i != 0) {
                    node2 = node2.next.next;
                    node1 = node1.next;
                    i--;
                }
                while (node3.next != head) {
                    node3 = node3.next;
                }
            }
            ListNode t1 = node1.next;
            ListNode t2 = node2.next;
            ListNode t3 = node3.next;
            node1.next = null;
            node2.next = null;
            node3.next = null;
            list.add(t1);
            list.add(t2);
            list.add(t3);
            return list;
        }
    
        public static void main(String[] args) {
            ListNode l0 = new ListNode(0);
            ListNode l1 = new ListNode(1);
            ListNode l2 = new ListNode(2);
            ListNode l3 = new ListNode(3);
            ListNode l4 = new ListNode(4);
            ListNode l5 = new ListNode(5);
            ListNode l6 = new ListNode(6);
            ListNode l7 = new ListNode(7);
            ListNode l8 = new ListNode(8);
            l0.next = l1;
            l1.next = l2;
            l2.next = l3;
            l3.next = l4;
            l4.next = l5;
            l5.next = l6;
            l6.next = l0;
            //l7.next = l0;
            //l8.next = l0;
            List<ListNode> list = divideToThree(l1);
            for (int i = 0; i < list.size(); i++) {
                ListNode node = list.get(i);
                System.out.println("链表i=" + i);
                while (node != null) {
                    System.out.println(node.val);
                    node = node.next;
                }
            }
        }
    
        static class ListNode {
            int val;
            ListNode next;
    
            public ListNode(int val) {
                this.val = val;
            }
        }
    }
    
    0 赞同 0 条回复
  • mpweixin用户 普通 2023年10月13日 下午5:35

    打卡的答案很多是不是都写错了,这是个环形链表,获取长度判断还用的nullptr

    0 赞同 0 条回复
  • 谁仁 普通 2023年8月24日 下午4:05

    int getLength(struct node * head)
    {
    int length=0;
    struct node * curr = head;
    while( curr != NULL)
    {
    length++;
    curr = curr->next;
    if(curr head)
    break;
    }
    return length;
    }

    struct node ** splitListToparts(struct node * head,int k,int returnSize)
    {
    struct node ** result = (struct node *)malloc(k
    sizeof(struct node));
    int length = getLength(head);
    int quotient = length/k;
    int remain = length%k;

    struct node * curr = head;
    
    for(int i = 0;i < k;i++)
    {
        result[i] = curr;//结果存进result,然后往下遍历
        int size = quotient + (i < remain ? 1:0);//判断size,是否需要+1
        for(int j = 1;j<size ;j++)//等分存进去result
        {
            curr = curr->next;
        }
        if(curr != NULL)
        {
            struct node * nextt = curr->next;//往下遍历
            curr->next = NULL;
            curr = next;
        }
    
    }
    * returnSize = k;
    return result;//返回结果
    

    }//时间复杂度O(n),空间复杂度O(k)

    0 赞同 0 条回复
  • mpweixin用户 普通 2023年8月23日 下午10:12

    时间复杂度:O(n),空间复杂度:O(n)
    特殊分类,一个,两个,三个及以上,余1,余2,三个指针用1:2:3的速度走

    0 赞同 0 条回复
  • sc_Yang 普通 2023年8月21日 下午9:17
    // 法1:
    // 三个指针轮流赋值指向相邻节点。
    // 第一个节点给第一个链表,第二个节点给第二个链表,第三个节点给第三个链表
    // 第k个节点给(k%3)个链表(k从0开始,链表序号也从0开始)
    /*========================================================*/
    // 法2:
    // 按长度三等分。
    // 先对链表进行长度计数,然后把分段获取“头指针”,最终获取三个“头”
    class Solution {
    public:
      int getLength(ListNode * head) {
        int length = 0;
        while (head != NULL) {
          length++;
          head = head->next;
        }
        return length;
      }
      vector< ListNode* > splitList2Parts(ListNode* head, int k) {
        int listlength = getLength(head);
        int partlength = listlength / k;
        int remainder = listlength % k;
        vector< ListNode* > ans;
    
        ListNode* curr = head, *prev = NULL;
    
        while(head) {
          int single_part_length = partlength;
          ans.push_back(curr);
          while (single_part_length >0) {
            prev = curr;
            curr = curr->next;
            single_part_length--;
          }
    
          if (remainder >0) {
            remainder--;
            prev = curr;
            curr = curr->next;
          }
          prev->next = NULL;
          head = curr;
        }
    
        return ans;
      }
    };
    
    
    
    0 赞同 0 条回复
  • Marc 普通 2023年8月19日 下午10:44

    3个指针,如果不是3的倍数需要判断

    0 赞同 0 条回复
  • 天亮说晚安 普通 2023年8月19日 下午2:42

    可以用三个快慢指针,最快的指针距离头结点不足三个或正好到头结点即可等分

    0 赞同 0 条回复
  • mpweixin用户 普通 2023年8月19日 上午12:59

    //通过遍历将链表一次存入3个链表中。
    //时间复杂度为o(n)
    //空间复杂度为o(1)
    class Solution {
    public:
    ListNode* partition(ListNode* head, int x) {
    int sum=0;
    ListNode *Count=head;
    while(Count){
    Count=Count->next;
    sum++;
    }
    //sum % 3 取余。等0,等1,等于2;
    ListNode *l1=new ListNode(0);
    ListNode *l2=new ListNode(0);
    ListNode *l3=new ListNode(0);
    ListNode *p1 =l1;
    ListNode *p2 =l2;
    ListNode *p3 =l3;

        while(head){
            if(head->next==NULL){
                p1->next=new ListNode(head->val);
                head=head->next;
                p1=p1->next;
                continue;
            }else if(head->next->next==NULL){
                p1->next=new ListNode(head->val);
                head=head->next;
                p1=p1->next;
                p2->next=new ListNode(head->val);
                head=head->next;
                p2=p2->next;
                continue;
            }else{
                p1->next=new ListNode(head->val);
                head=head->next;
                p1=p1->next;
                p2->next=new ListNode(head->val);
                head=head->next;
                p2=p2->next;
                p3->next=new ListNode(head->val);
                head=head->next;
                p3=p3->next;
            }
    
        }
        vector <ListNode> *ans;
        ans.push_back(l1);
        ans.push_back(l2);
        ans.push_back(l3);
    
        return ans;
    
    }
    

    };

    0 赞同 0 条回复
  • 木木 普通 2023年8月17日 下午5:40

    時間複雜度: O(n) 空間複雜度: O(k) from chatgpt, 因為res會需要存 k段 linked list
    先知道整段list多長
    計算切成k段之後 一段的長度
    計算除不盡的部份是幾個node
    開始切分linked list 第一段要額外加上除不盡的node

    
    class Solution {
    public:
      int getLength(ListNode * head) {
        int length = 0;
        while (head != NULL) {
          length++;
          head = head->next;
        }
        return length;
      }
      vector< ListNode* > splitList2Parts(ListNode* head, int k) {
        int listlength = getLength(head);
        int partlength = listlength / k;
        int remainder = listlength % k;
        vector< ListNode* > ans;
    
        ListNode* curr = head, *prev = NULL;
    
        while(head) {
          int single_part_length = partlength;
          ans.push_back(curr);
          while (single_part_length >0) {
            prev = curr;
            curr = curr->next;
            single_part_length--;
          }
          
          if (remainder >0) {
            remainder--;
            prev = curr;
            curr = curr->next;
          }
          prev->next = NULL;
          head = curr;
        }
    
        return ans;
      }
    };
    
    
    0 赞同 0 条回复
  • 一个人的风海吹了两遍 普通 2023年8月17日 下午3:44
        //环形链表分为三等分
        public ListNode SepList(ListNode head){
            ListNode cur = head;
            int len = 0;
            while (cur!=null){
                len++;
                cur=cur.next;
            }
            if(len<3)
                return head;
    
            int partSize = len / 3;
            int remainder = len - partSize*2;
            int num = partSize;
    
            ListNode head1 = head;
            ListNode tail1 = head1;
            while (num!=0){
                tail1 = tail1.next;
                num--;
            }
    
            ListNode head2 = tail1.next;
            ListNode tail2 = head2.next;
            //tail1.next=null;
            num = partSize;
            while (num!=0){
                tail2 = tail2.next;
                num--;
            }
    
            ListNode head3 = tail2.next;
            ListNode tail3 = head3.next;
            //tail1.next=null;
            num = remainder;
            while (num!=0){
                tail3 = tail3.next;
                num--;
            }
            return head;
        }
    
    0 赞同 0 条回复
  • mpweixin用户 永久会员 2023年8月16日 下午4:42

    ListNode* divideLinkedList(ListNode* head) {
    if (!head || !head->next || !head->next->next) {
    // 链表节点数小于3,无法分成三等份
    return nullptr;
    }

    // 计算链表长度
    int length = 0;
    ListNode* current = head;
    while (current) {
        length++;
        current = current->next;
    }
    
    int partSize = length / 3;  // 每个等份的长度
    int remainder = length % 3; // 剩余的节点数量
    
    if (partSize == 0) {
        // 链表长度不够分成三等份
        return nullptr;
    }
    
    // 找到分割点
    current = head;
    for (int i = 1; i < partSize + (remainder > 0); i++) {
        current = current->next;
    }
    
    // 切断链表,形成三等份
    ListNode* part1End = current;
    ListNode* part2Start = current->next;
    current = part2Start;
    for (int i = 1; i < partSize + (remainder > 1); i++) {
        current = current->next;
    }
    ListNode* part2End = current;
    ListNode* part3Start = current->next;
    
    // 断开各等份的连接
    part1End->next = nullptr;
    part2End->next = nullptr;
    // 剩下的部分由环形链表
    return part3Start;
    

    }

    0 赞同 0 条回复
  • 小肸 永久会员 2023年8月15日 下午10:26

    “`java
    public List getThreeListNode(ListNode head) {
    ListNode dummyHead = new ListNode(-1);
    dummyHead.next = head;
    ListNode p1 = dummyHead, p2 = dummyHead, p3 = dummyHead;
    //利用步差,p3走最前面,只用判断p3。少于3个节点或者比三的倍数多出一个、两个节点视情况讨论
    while (p3.next != head && p3.next.next != head && p3.next.next.next != head) {
    p3 = p3.next.next.next;
    p2 = p2.next.next;
    p1 = p1.next;
    }
    List
    res = new ArrayList<>(3);
    if (p1 != dummyHead && p2 != dummyHead && p3 != dummyHead) {
    res.add(p1);
    res.add(p2);
    res.add(p3);
    }
    return res;
    }
    ““

    0 赞同 0 条回复
  • c 普通 2023年8月15日 下午1:23

    时间复杂度O(n),空间复杂度O(1)

    public static List<ListNode> spliteThree(ListNode head){
            List<ListNode> list = new ArrayList<>();
            if (head.next == head){
                head.next=null;
                list.add(head);
                list.add(null);
                list.add(null);
                return list;
            }
            if (head.next.next == head){
                ListNode n=head.next;
                head.next=null;
                n.next=null;
                list.add(head);
                list.add(n);
                list.add(null);
                return list;
            }
            ListNode node1 = head;
            ListNode node2 = head.next;
            ListNode node3 = head.next.next;
            while (node3.next!=head){
                if (node3.next.next==head){
                    node3=node3.next;
                } else if (node3.next.next.next == head) {
                    node2=node2.next;
                    node3=node3.next.next;
                }else {
                    node1=node1.next;
                    node2=node2.next.next;
                    node3=node3.next.next.next;
                }
            }
            node3.next=null;
            node3=node2.next;
            node2.next=null;
            node2=node1.next;
            node1.next=null;
            list.add(head);
            list.add(node2);
            list.add(node3);
            return list;
        }
    
    0 赞同 0 条回复
  • 别扒拉我 普通 2023年8月14日 下午11:19

    快中慢三指针

    0 赞同 0 条回复
  • mpweixin用户 永久会员 2023年8月14日 下午9:18

    快中慢3个指针,慢指针一次走一步,中指针一次走2步,快指针,一次走3步
    时间复杂度O(n);空间复杂度O(1)

    public class Solution_trisec {
        public List trisect(ListNode head) {
            List<ListNode> list = new ArrayList<>();
            //链表为空直接返回空list
            if (head == null) {
                return list;
            }
            //链表只有一个元素的,list里面只有一个head
            if (head.next == head) {
                list.add(head);
                list.add(null);
                list.add(null);
            }
            //链表只有2个元素的,list就两个元素,head以及head.next
            if (head.next.next == head) {
                list.add(head);
                list.add(head.next);
                list.add(null);
            }
            ListNode slow = head, medium = head.next, fast = head.next.next;
            //链表长长度大于3的;若长度不为3的倍速,要么最后一段少分点(余2),要么最后一段多分点(余1)
            while (fast != head) {
                if (fast.next == head) {
                    break;
                } else if (fast.next.next == head) {
                    medium = medium.next;
                    fast = head;
                    break;
                } else if (fast.next.next.next == head) {
                    fast = fast.next.next;
                    medium = medium.next;
                } else {
                    slow = slow.next;
                    medium = medium.next.next;
                    fast = fast.next.next.next;
                }
            }
            list.add(slow);
            list.add(medium);
            list.add(fast);
            return list;
        }
    }
    
    0 赞同 0 条回复
  • 辰北、 普通 2023年8月14日 下午5:38

    //c 多的话,每份多分一个;刚好则不管;
    struct ListNode *getIntersectionNode(struct ListNode *headA){
    struct ListNode *pL=headA;
    struct ListNode *p1=NULL;
    struct ListNode *p2=NULL;
    struct ListNode *p3=NULL;
    int n=1;
    while(pL->next=headA){
    pL=pL->next;
    n++;
    }
    int length=0;
    length=n/3;
    if((n%3)!=0){
    if(n%3=2){
    length1=length+1;
    length2=length+1;
    length3=length;
    }
    else {
    length1=length+1;
    length2=length;
    length3=length;
    }
    else{
    length1=length;
    length2=length;
    length3=length;
    }
    while(length1=<0){
    p1=pL;
    pL=pL->next;
    length–;
    }while(length2=<0){
    p2=pL;
    pL=pL->next;
    length–;
    }while(length3=<0){
    p3=pL;
    pL=pL->next;
    length–;
    }

    return p1,p2,p3;
    

    }

    1 赞同 0 条回复
  • Jou Siankwa 普通 2023年8月14日 下午3:17
    import java.util.ArrayList;
    import java.util.LinkedList;
    import java.util.List;
    
    public class GetThreeListNode {
        public static void main(String[] args) {
            ListNode l1 = new ListNode(1);
            ListNode l2 = new ListNode(2);
            ListNode l3 = new ListNode(3);
            ListNode l4 = new ListNode(4);
            ListNode l5 = new ListNode(5);
            ListNode l6 = new ListNode(6);
            ListNode l7 = new ListNode(7);
            ListNode l8 = new ListNode(8);
            ListNode l9 = new ListNode(9);
            ListNode l10 = new ListNode(10);
            ListNode l11 = new ListNode(11);
            l1.next = l2;
            l2.next = l3;
            l3.next = l4;
            l4.next = l5;
            l5.next = l6;
            l6.next = l7;
            l7.next = l8;
            l8.next = l9;
            l9.next = l10;
            l10.next = l11;
            l11.next = l1;
            List<ListNode> threeListNode = getThreeListNode(l1);
    
            // 打印
            for(int i = 0; i < threeListNode.size(); i++){
                ListNode head = threeListNode.get(i);
                System.out.println("链表 i = " + i);
                while(head != null){
                    System.out.println(head.val);
                    head = head.next;
                }
            }
        }
        public static List<ListNode> getThreeListNode(ListNode head){
            if(head==null){
                List<ListNode> list = new ArrayList<>();
                list.add(null);
                list.add(null);
                list.add(null);
                return list;
            }
            ListNode l1 = head;
            ListNode l2 = head.next;
            ListNode l3 = head.next.next;
            int count =1;
            ListNode temp = head;
            while (head.next!=temp){
                count++;
                head = head.next;
            }
            if (count==1){
                List<ListNode> list = new ArrayList<>();
                temp.next = null;
                list.add(temp);
                list.add(null);
                list.add(null);
                return list;
            }
            if(count == 2){
                List<ListNode> list = new ArrayList<>();
                ListNode a =temp.next;
                temp.next = null;
                list.add(temp);
                a.next = null;
                list.add(a);
                list.add(null);
                return list;
            }
            System.out.println(count);
            List<ListNode> list= new ArrayList<>();
            if((count%3)==0){
                while(l3.next!=temp){
                    l3 = l3.next.next.next;
                    l2 = l2.next.next;
                    l1 = l1.next;
                }
                ListNode a1 = l3.next;
                ListNode a2 = l2.next;
                ListNode a3 = l1.next;
                l1.next = null;
                l2.next = null;
                l3.next = null;
                list.add(a1);
                list.add(a2);
                list.add(a3);
            }else{
                int k = (int) Math.round(count*1.0/3)-1;
                while (k!=0){
                    l2 = l2.next.next;
                    l1 = l1.next;
                    k--;
                }
                while(l3.next!=temp){
                    l3 = l3.next;
                }
                ListNode a1 = l3.next;
                ListNode a2 = l2.next;
                ListNode a3 = l1.next;
                l1.next = null;
                l2.next = null;
                l3.next = null;
                list.add(a1);
                list.add(a3);
                list.add(a2);
            }
    
    
            return list;
        }
    }
    
    0 赞同 0 条回复

# 回答此问题

后才能回答