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

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

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

参考代码

代码来自于 @西西弗斯的石头 同学(稍作一些修改),当不是 3 的倍数时,还是比较麻烦滴。下面是一个完整的代码,包括测试,你们可以直接粘贴运行。

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

共以下 29 个回答

  • 招舟子 普通 2023年8月25日 上午12:22

    思路:分情况讨论
    伪码:
    public List getThreeListNode(ListNode head){

        ListNode p1=head;
        ListNode p2=head.next;
        ListNode p3=head.next.next;
    
        if(p1==p2||p1==p3) return null;//没有足够的三个节点形成环形链表
    
        while(p3.next!=head){
            p1=p1.next;
            p2=p2.next.next;
            p3=p3.next.next.next;
        }
        //此时,当p3运行到head的上一个节点
        //三个就形成了三等分的链表
    

    }

    0 赞同 0 条回复
  • BOZ 普通 2023年7月4日 下午3:33

    采用多指针方法(3指针,分别是每次走1/2/3跳)
    【时间复杂度】O(n)
    【空间复杂度】O(1)

    class Solution {
    public:
        void triple_divide(ListNode* head, ListNode *divider[]) {
            for (int i = 0; i < 3; i++) divider[i] = head;
            do {
                for (int i = 0; i < 3; i++) {
                    divider[2] = divider[2]->next;
                    if (i < 2) divider[1] = divider[1]->next;
                    if (i < 1) divider[0] = divider[0]->next;
                    if (divider[2] == head) break;
                }
            } while (divider[2] != head);
        }
    
        void print_circle_piece(ListNode *head, ListNode *end) {
            printf("[Circle piece]: ");
            while (head != end) {
                printf("%d ", head->val);
                head = head->next;
            }
            printf("\n");
        }
    };
    
    void test(const vector a) {
        Solution s;
        ListNode *al = makeCircle(a);
        printf("input: \n");
        printCircle(al);
    
        ListNode *divider[3];
        s.triple_divide(al, divider);
        printf("answer: \n");
        s.print_circle_piece(al, divider[0]);
        s.print_circle_piece(divider[0], divider[1]);
        s.print_circle_piece(divider[1], divider[2]);
        assert(divider[2] == al);
    }
    
    int main() {
        test({1, 2, 3, 4, 5, 6});       // ans: (1, 2), (3, 4), (5, 6)
        test({1, 2, 3, 4, 5, 6, 7});    // ans: (1, 2, 3), (4, 5), (6, 7)
        test({1, 2, 3, 4, 5, 6, 7, 8}); // ans: (1, 2, 3), (4, 5, 6), (7, 8)
        test({1, 2});                   // ans: (1), (2), ()
        return 0;
    }
    
    0 赞同 0 条回复
  • 3_🔥 永久会员 2023年7月3日 下午4:30
    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 = l1.next;
                ListNode a3 = l2.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 = l2;
            l2.next = l3;
            l3.next = l4;
            l4.next = l5;
            l5.next = l6;
            l6.next = l1;
    //        l7.next = l1;
            List threeListNode = getThreeListNode(l1);
            // 打印
            for(int i = 0; i < threeListNode.size(); i++){
                ListNode head = (ListNode) threeListNode.get(i);
                System.out.print("链表 " + (i+1) +":");
                while(head != null){
                    System.out.print(head.val+"->");
                    head = head.next;
                }
                System.out.println("null");
            }
        }
    
        // ListNode 内部类,用来演示需要
        public static class ListNode{
            int val;
            ListNode next;
            public ListNode(int x){
                this.val = x;
            }
        }
    }
    

    参考的代码

    1 赞同 0 条回复
  • 憨憨 永久会员 2023年7月3日 上午9:56

    先遍历一遍获取链表总长度,然后分别计算取余和商,根据商和余数得不同分为三种情况
    1.取余为0则为空或者三得倍数此时等分即可
    2.为1则最后一个链表长度+1
    3.为2则倒数后两个长度+1

    public static void main(String[] args) {
    
            Scanner sc =new Scanner(System.in);
            int a=sc.nextInt();
            Node A=toFan(toInt(a));
            Node ta=A;
            while(ta.next!=null){
                ta=ta.next;
            }
            ta.next=A;
    
            Node cur=A;
            int count=1;
            while(cur.next!=A){
                count++;
                cur=cur.next;
            }
            Node A1=null,A2=null,A3=null;
            if(count==1){
                A1=A;
                A1.next=null;
            }else if(count==2){
                A1=A;
                A2=A.next;
                A1.next=null;
                A2.next=null;
            }else{
                int k=count/3;
                int n=count%3;
                cur=A;
                int num=1;
                A1=cur;
                while(cur.next!=A){
                    if(num==k){
                        num=1;
                        break;
                    }
                    cur=cur.next;
                    num++;
    
                }
                A2=cur.next;
                cur.next=null;
                cur=A2;
                if(n==2)k++;
                while(cur.next!=A){
                    if(num==k){
                        break;
                    }
                    cur=cur.next;
                    num++;
                }
                A3=cur.next;
                cur.next=null;
                cur=A3;
                while(cur.next!=A){
                    cur=cur.next;
                }
                cur.next=null;
            }
    
            show(A1);
            show(A2);
            show(A3);
    
    
    //        System.out.print(count);
    
    
    
    
        }
    
    0 赞同 0 条回复
  • 大大 普通 2023年7月1日 下午12:35
    C++语言实现:
    对于是3的倍数的节点数,均分;
    不是3的倍数的节点数,eg:1~10则
    0 1 2 3 4
    5 6 7
    8 9 10
    如果想要实现
    0 1 2 
    3 4 5
    6 7 8 9 10这样的,删除我的代码中if语句的就可以啦(这样的话,在我的代码中是否是3的倍数是没有区分的)
    #include<bits/stdc++.h>
    using namespace std;
    typedef struct Node {
        int val;
        Node *next;
        Node(int x) : val(x), next(NULL) {}
    }Node;
    
    Node* node[3]={NULL};//Node*[] node=new Node*[3];
    
    int Num(Node* A){
        Node* head=A;
        int a=0;
        while(head){
            a++;
            head=head->next;
        }
        return a;
    }
    
    Node* Divide(Node* A){
        Node* head=A;
        while(head->next!=A){
            head=head->next;
        }
        head->next=NULL;
        return A;
    }
    Node** Solve(int x,Node* A){
        Node* head=A;
        Node*tmp=NULL;
        Node* tmp2=NULL;
        node[0]=head;
        int j=1;
        while(j<3){
            for(int i=0;i<x-1;i++){
              head=head->next;
            }
            tmp=head->next;//头
            tmp2=head;//尾
            tmp2->next=NULL;
            node[j++]=tmp;
            head=tmp;
        }
        return node;    
    }
    void Show(Node* A){
        Node* head=A;
        while(head){
            cout<<head->val<<" ";
            head=head->next;
        }
        cout<<endl;
    }
    int main(){
        //创建节点个数时3的倍数的环形链表
        Node* A=new Node(0);
         A->next=new Node(1);
         A->next->next=new Node(2); 
         A->next->next->next=new Node(3);
         A->next->next->next->next=new Node(4); 
         A->next->next->next->next->next=new Node(5);
         A->next->next->next->next->next->next=new Node(6);
         A->next->next->next->next->next->next->next=new Node(7);
         A->next->next->next->next->next->next->next->next=new Node(8);   
        // A->next->next->next->next->next->next->next->next->next=A;  
         A->next->next->next->next->next->next->next->next->next=new Node(9);
         A->next->next->next->next->next->next->next->next->next->next=new Node(10);    
         A->next->next->next->next->next->next->next->next->next->next->next=A;  
    
        //solve
        //将环形链表拆分
        Node** B=NULL;
        A=Divide(A);
        int b=Num(A);
        //if语句内是节点个数不是3的倍数 else语句里是3的倍数
            if(b%3){
                int a=b%3;
                b/=3;
             Node* Ahead=A;
             for(int i=0;i<a-1;i++){
                A=A->next;
             }
             Node* tmp=A->next;//下一个的开头
             Node* tmp2=A;//这一个的尾
             A->next=NULL;
             A=tmp;
             B=Solve(b,A);
             tmp2->next=B[0]; 
             B[0]=Ahead;
            }
        else
        B=Solve(b/3,A);
        for(int i=0;i<3;i++)
        Show(B[i]); 
        return 0;
    }
    
    
    
    
    1 赞同 0 条回复
  • mpweixin用户 普通 2023年6月30日 下午4:11

    使用3个指针,fastTwoNode一次走3step,fastNode一次走2step, slowNode一次走1step;
    当(head fastTwoStep && fastTwoStep != fastNode) || head fastTwoStep.next || head fastTwoStep.next.next时,三个指针到达分割点
    之后就是对链表进行分割

    import java.util.ArrayList;
    import java.util.List;
    
    public class SplitCircleListNode {
        public static void main(String[] args) {
            //1->2->3->4->5->6->7->8 --> 1
            Node node11 = new Node(1);
            Node node12 = new Node(2);
            Node node13 = new Node(3);
            Node node14 = new Node(4);
            Node node15 = new Node(5);
            Node node16 = new Node(6);
            Node node17 = new Node(7);
            Node node18 = new Node(8);
            node11.next = node12;
            node12.next = node13;
            node13.next = node14;
            node14.next = node15;
            node15.next = node16;
            node16.next = node17;
            node17.next = node18;
            node18.next = node11;
    
            List<Node> node = splitCircleListNode(node11);
    
        }
    
        private static List<Node> splitCircleListNode(Node node11) {
            if (node11 == node11.next.next || node11 == node11.next) {
                return null;
            }
    
            Node head = node11;
            Node fastTwoStep = node11;
            Node fastNode = node11;
            Node slowNode = node11;
            while ( true) {
                if ((head == fastTwoStep && fastTwoStep != fastNode)  || head == fastTwoStep.next || head == fastTwoStep.next.next) {
                    break;
                }else {
                    fastTwoStep = fastTwoStep.next.next.next;
                    fastNode = fastNode.next.next;
                    slowNode = slowNode.next;
                }
            }
            //slow 2 fast 4 fastTwo 1
            List<Node> res = new ArrayList<>(10);
            res.add(slowNode);
            Node tmp = slowNode.next;
            Node pre = slowNode;
            while (tmp!=null) {
                if (tmp == fastNode) {
                    pre.next =null;
                    res.add(fastNode);
                    pre = fastNode;
                    tmp = tmp.next;
    
                }else if (tmp == fastTwoStep) {
                    pre.next =null;
                    res.add(fastTwoStep);
                    pre = fastTwoStep;
                    tmp = tmp.next;
                }else if(tmp == slowNode) {
                    pre.next =null;
                    break;
                } else {
                    pre = pre.next;
                    tmp = tmp.next;
                }
    
            }
    
            print(res.get(0));
            print(res.get(1));
            print(res.get(2));
            return res;
    
        }
    
        public static void print(Node head) {
            System.out.println("==============");
            Node tmp = head;
            while (tmp !=null) {
                System.out.println(tmp.getVal() + "->");
                tmp  = tmp.next;
            }
        }
    }
    
    
    0 赞同 0 条回复
  • 张开怀 普通 2023年6月30日 上午9:18

    思路:
    既然要均分为三等份,则需要计算下节点的数量是否为3的倍数
    是:l1、l2、l3三个指针同时走,直至l3.nexthead;
    否:需要将l1、l2先向前走k步,随后l3再走、直至l3.next
    head;
    k = Math.round(count*1.0/3)-1;

    public:
           void GetThreeListNode(){
                  ListNode l0 = new ListNode(0);
                  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);
                  ListNode l8 = new ListNode(7);
                  ListNode l9 = new ListNode(8);
    
                  l0.next=l0;
                  l1.next=l2;
                  l2.next=l3;
                  l3.next=l4;
                  l4.next=l5;
                  l5.next=l6;
                  l6.next=l7;
                  l7.next=l8;
                  l8.next=l1;
                  l9.next=l1;
                  List<ListNode> listNodeList = getThreeListNode(l1);
                  // 打印结果
                  for(int i=1; i<=listNodeList.size(); i++){
                         // System.out.println("第" i "个ListNode");
                         ListNode listNode = listNodeList.get(i-1);
                         while(listNode != NULL){
                                listNode = listNode.next;
                         }
                  }
           }
    
    private:
           List<ListNode> getThreeListNode(ListNode head){
                  // 初始化三个需要返回的链表
                  ListNode l1 = nullptr;
                  ListNode l2 = nullptr;
                  ListNode l3 = nullptr;
                  List<ListNode> list = new ArrayList<>();
    
                  if(head == nullptr){
                         return list;
                  }
                  // 只有一个节点不成环
                  if(head.next == nullptr){
                         list.add(head);
                         return list;
                  }
                  // 结点大于1,统计结点个数
                  int count = 1;
                  ListNode temp = head;
                  while(temp.next!=head){
                         count++;
                         temp = temp.next;
                  }
                  // 自身成环
                  if(count==1){
                         ListNode a1= temp.next;
                         l1 = a1;
                         a1.next = nullptr;
                         list.add(l1);
                         return list;
                  }
                  // 有两个结点且成环
                  if(count == 2){
                         ListNode a1 = temp.next;
                         l1=a1;
                         a1.next=null;
    
                         l2 =temp;
                         temp.next =nullptr;
    
                         list.add(l1);
                         list.add(l2);
                         return list;
                  }
                  // 结点大于3时,先判断结点数是不是3的倍数
                  if(count%3 == 0){
                         l1 = head;
                         l2 = head.next;
                         l3 = head.next.next;
                         ListNode a1;
                         ListNode a2;
                         ListNode a3;
                         while(l3.next != head){
                                l1 = l1.next;
                                l2 = l2.next.next;
                                l3 = l3.next.next.next;
                         }
                         a1 = l1.next;
                         a2 = l2.next;
                         a3 = l3.next;
    
                        l1.next = null;
                        l2.next = null;
                        l3.next = null;
    
                        l1 = a1;
                        l2 = a2;
                        l3 = a3;
                  } else{
                        l1 = head;
                        l2 = head.next;
                        l3 = head.next.next;
                        ListNode a1;
                        ListNode a2;
                        ListNode a3;
    
                        int k = (int)Math.round(count * 1.0/3) - 1;
                        whlie(k != 0){
                               l1 = l1.next;
                               l2 = l2.next.next;
                               k--;
                        } 
                        while(l3.next != head){
                               l3 = l3.next;
                        }
    
                        a1 = l1.next;
                        a2 = l2.next;
                        a3 = l3.next;
    
                        l1.next = nullptr;
                        l2.next = nullptr;
                        l3.next = nullptr;
    
                        l1 = a1;
                        l2 = a2;
                        l3 = a3;
                  }
    
                  list.add(l1);
                  list.add(l2);
                  list.add(l3);
                  return list;
           }
    
    
    0 赞同 0 条回复
  • 泡芙 永久会员 2023年6月28日 下午10:31

    提问:

    1. 输入的链表是否是合法的环形链表
    2. 链表的节点个数是否是3的倍数
    3. 如果链表的节点个数不是3的倍数,剩余的节点是按四舍五入尽量均匀分配,还是让前面一部分的子链表的节点个数多一点,比如10个节点四舍五入是3,则分为3,3,4,11个节点四舍五入是4,则分为4,4,3
    4. 返回的链表都是环形链表吗?

      如果返回的三个链表都是环形链表,其中每个链表的最后一个节点会指向链表的头节点。

    5. 返回的结果列表中的链表顺序与子链表的顺序相同吗

    假设输入的链表是一个合法的环形链表。链表的节点个数是 3 的倍数,并且返回的结果列表中的链表顺序与子链表的顺序相同。

    该算法首先计算链表的长度,如果长度小于3,则无法等分,直接返回空结果。然后,根据链表长度计算每个子链表的长度。接着,通过遍历找到第二个和第三个子链表的头节点,并将链表断开形成三个独立的链表。最后,将三个子链表的头节点添加到结果中并返回。

    public List getThreeListNode(ListNode head) {
        List result = new ArrayList<>();
    
        // 计算链表长度
        int length = getLength(head);
    
        // 计算每个子链表的长度
        int partLength = length / 3;
    
        // 如果链表长度小于3,无法等分,返回空
        if (length < 3 ) {
            return null;
        }
    
        // 定义三个指针分别指向每个子链表的头节点
        ListNode firstHead = head;
        ListNode secondHead = null;
        ListNode thirdHead = null;
    
        // 找到第二个子链表的头节点
        for (int i = 1; i < partLength; i++) {
            head = head.next;
        }
        secondHead = head.next;
    
        // 找到第三个子链表的头节点
        for (int i = 1; i < partLength; i++) {
            head = head.next;
        }
        thirdHead = head.next;
    
        // 断开环形链表
        head.next = null;
    
        // 将三个子链表头节点添加到结果中
        result.add(firstHead);
        result.add(secondHead);
        result.add(thirdHead);
    
        return result;
    }
    
    // 计算链表的长度
    private int getLength(ListNode head) {
        int length = 0;
        ListNode current = head;
        while (current != null) {
            length++;
            current = current.next;
            if (current == head) {
                break; // 遍历到环形链表的起始节点,跳出循环
            }
        }
        return length;
    }
    

    补充:用快慢指针也可以实现,fast 移动两步,slow移动一步,直到快慢指针第一次相遇,这样,fast走过的距离是slow的两倍。第一次相遇之后,将fast重新指向链表的头节点head,slow就在第一次相遇的位置,然后slow和fast同时向前走一步,直到快慢指针再次相遇。此时,slow走过的距离是链表总长度的三分之一。最后,将fast再次重新指向链表的头节点,并将第二次相遇时slow指向的位置作为第一个分割点。如此就能得到三等分的链表

    0 赞同 0 条回复
  • 别恰冰水🧊 永久会员 2023年6月27日 下午4:12
    import java.util.*;
    
    public class GetThreeListNode {
        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 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 (temp.next != head){
                count++;
                temp = temp.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;
            }
            List<ListNode> list= new ArrayList<>();
            if((count%3)==0){
                while(l3.next!=head){
                    l3 = l3.next.next.next;
                    l2 = l2.next.next;
                    l1 = l1.next;
                }
                ListNode a2 = l1.next;
                ListNode a3 = l2.next;
                ListNode a1 = l3.next;
                l1.next = null;
                l2.next = null;
                l3.next = null;
                list.add(a1);
                list.add(a2);
                list.add(a3);
            }else{
                int k = count % 3;
                if (k == 1) {
                    l1 = l1.next;
                    l2 = l2.next;
                    l3 = l3.next;
                    while (l3.next != head) {
                        l3 = l3.next.next.next;
                        l2 = l2.next.next;
                        l1 = l1.next;
                    }
                }
                if (k == 2) {
                    l1 = l1.next;
                    l2 = l2.next.next;
                    l3 = l3.next.next;
                    while (l3.next != head) {
                        l3 = l3.next.next.next;
                        l2 = l2.next.next;
                        l1 = l1.next;
                    }
                }
                ListNode a2 = l1.next;
                ListNode a3 = l2.next;
                ListNode a1 = l3.next;
                l1.next = null;
                l2.next = null;
                l3.next = null;
                list.add(a1);
                list.add(a3);
                list.add(a2);
            }
            return list;
        }
    
    0 赞同 0 条回复
  • HU 普通 2023年6月26日 下午10:04
    function GetThreeListNode(head) {
      // 如果只有一个节点
      if(head.next === head) {
        let res = [];
        // 防止返回一个环形链表
        head.next = null;
        res.push(head);
        res.push(null);
        res.push(null);
        return res;
      }
    
      // 如果只有两个节点
      if(head.next.next === head) {
        let res = [];
        let temp = head.next;
        temp.next = null;
        res.push(temp);
        head.next = null;
        res.push(head);
        res.push(null);
        return res;
      }
    
      // 三个节点以上时
      let l1 = head;
      let l2 = head.next;
      let l3 = head.next.next;
    
      let count = 1;
    
      let temp = head;
    
      while(head !== temp) {
        count++;
        head = head.next;
      }
    
      let res = [];
    
      // 节点是3的倍数,三个指针,走一步,走两步和走三步来进行切分
      if((count % 3) === 0) {
        while(l3.next !== temp) {
          // l1、l2和l3用来等间隔分割
          l3 = l3.next.next.next;
          l2 = l2.next.next;
          l1 = l1.next;
        }
        // a1、a2和a3是等间隔分割后的三个链表的头节点
        let a1 = l3.next;
        let a2 = l2.next;
        let a3 = l1.next;
    
        l1.next = null;
        l2.next = null;
        l3.next = null;
    
        res.push(a1);
        res.push(a2);
        res.push(a3);
      } else {
        // 如果节点不是3的倍数
        // 首先计算k,表示l1和l2最多需要移动的步数
        let k = parseInt(count*1.0/3) - 1;
        while(k--) {
          l2 = l2.next.next;
          l1 = l1.next;
        }
        // 可确保l3是链表的最后一个节点
        while(l3.next !== temp) {
          l3 = l3.next;
        }
    
        let a1 = l3.next;
        let a2 = l2.next;
        let a3 = l1.next;
    
        l1.next = null;
        l2.netx = null;
        l3.next = null;
    
        res.push(a1);
        res.push(a2);
        res.push(a3);
      }
    
      return res;
    }
    

    时间复杂度:O(n)。
    空间复杂度:O(1)。

    0 赞同 0 条回复
  • ~ 普通 2023年6月26日 下午7:39

    class DetachCirCularList {
    public:
    vector<ListNode> getTreeListNode(ListNode head) {
    if (head->next head) {
    vector<ListNode*> result = { head, nullptr, nullptr };
    head->next = nullptr; // 防止返回一个环形链表
    return result;
    }

        if (head->next->next == head) {
            vector<ListNode*> result = { head->next, head, nullptr };
            head->next->next = nullptr; 
            head->next = nullptr;
            return result;
        }
    
        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;
        }
    
        vector<ListNode*> result;
    
        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 = nullptr;
            l2->next = nullptr;
            l3->next = nullptr;
    
            result = { a1, a2, a3 };
        }
        else {
            // 关键点
            int k = count / 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 = nullptr;
            l2->next = nullptr;
            l3->next = nullptr;
    
            result = { a1, a2, a3 };
        }
        return result;
    }
    

    };
    时间复杂度O(N),空间复杂度O(N)

    0 赞同 0 条回复
  • 哈哈哈哈开开心心 普通 2023年6月24日 上午4:37
    # Definition for singly-linked list.
    # class ListNode:
    #     def __init__(self, val=0, next=None):
    #         self.val = val
    #         self.next = next
    class Solution:
        def splitListToParts(self, head: Optional[ListNode], k: int) -> List[Optional[ListNode]]:
            cnt = 0
            cur = head
    
            while cur != head:
                cnt += 1
                cur = cur.next
    
            num_of_more_node_partition = cnt % k
            num_of_nodes_per_partition = cnt // k
    
            res = []
            cur = head
    
            for i in range(k):
                target_num_nodes = num_of_nodes_per_partition
                if num_of_more_node_partition > 0:
                    target_num_nodes  += 1
                    num_of_more_node_partition -= 1
    
                partition = ListNode()
                new_head = partition
                for i in range(target_num_nodes):
                    new_head.next = ListNode(cur.val)
                    new_head = new_head.next
                    cur = cur.next
    
                res.append(partition.next)
    
            return res
    
    0 赞同 0 条回复
  • Yodl. 普通 2023年6月23日 下午1:16

    打卡

    #include <iostream>
    using namespace std;
    
    struct Node {
        int data;
        Node* next;
        Node(int val) : data(val), next(nullptr) {}
    };
    
    void insert(Node*& head, Node*& tail, int val) {
        Node* node = new Node(val);
        if (!head) {
            head = tail = node;
            tail->next = head;
        } else {
            node->next = head;
            tail->next = node;
            tail = node;
        }
    }
    
    void splitCircularList(Node* head, Node*& firstHead, Node*& firstTail, Node*& secondHead, Node*& secondTail, Node*& thirdHead, Node*& thirdTail) {
        if (!head)
            return;
        Node* currNode = head;
        int count = 0;
        while (currNode) {
            count++;
            currNode = currNode->next;
            if (currNode == head)
                break;
        }
        int size = count / 3;
        currNode = head;
        firstHead = firstTail = currNode;
        for (int i = 1; i < size; i++) {
            currNode = currNode->next;
        }
        firstTail = currNode;
        secondHead = secondTail = firstTail->next;
        for (int i = 1; i < size; i++) {
            currNode = currNode->next;
        }
        secondTail = currNode;
        thirdHead = thirdTail = secondTail->next;
        while (currNode->next != head) {
            currNode = currNode->next;
        }
        thirdTail = currNode;
        firstTail->next = secondTail->next = thirdTail->next = head;
        thirdTail->next = nullptr;
    }
    
    void printList(Node* head) {
        if (!head)
            return;
        Node* currNode = head;
        do {
            cout << currNode->data << " ";
            currNode = currNode->next;
        } while (currNode != head);
        cout << endl;
    }
    
    int main() {
        Node* head = nullptr;
        Node* firstHead = nullptr;
        Node* firstTail = nullptr;
        Node* secondHead = nullptr;
        Node* secondTail = nullptr;
        Node* thirdHead = nullptr;
        Node* thirdTail = nullptr;
    
        insert(head, head, 1);
        insert(head, head, 2);
        insert(head, head, 3);
        insert(head, head, 4);
        insert(head, head, 5);
        insert(head, head, 6);
        insert(head, head, 7);
        insert(head, head, 8);
        insert(head, head, 9);
    
        cout << "Original List: ";
        printList(head);
        splitCircularList(head, firstHead, firstTail, secondHead, secondTail, thirdHead, thirdTail);
        cout << "List after split into three parts: " << endl;
        cout << "Part 1: ";
        printList(firstHead);
        cout << "Part 2: ";
        printList(secondHead);
        cout << "Part 3: ";
        printList(thirdHead);
    
        return 0;
    }
    
    0 赞同 0 条回复
  • 残月冷骄阳 普通 2023年6月23日 上午12:47
    //先计算长度,然后分成三段,可能存在未平分情况,提示输出。
        public static List<ListNode> threedivision(ListNode head){
            int length=0;
            ListNode temp = head;
            while (temp!=null){
                length++;
                temp=temp.next;
            }
            if (length%3!=0){
                System.out.println("not divisible by 3");
            }
            ArrayList<ListNode> listNodes = new ArrayList<>();
            ListNode head1 = null;
            ListNode head2 = null;
            ListNode head3 = null;
            for (int i = 1; i <= length; i++) {
                ListNode next = head;
                if (i%3==1){
                    head.next = head1;
                    head1=head;
    
                }else if (i%3==2){
                    head.next=head2;
                    head2=head;
                }else {
                    head.next=head3;
                    head3=head;
                }
                head=next;
            }
            if (head1!=null){
                head1.next=null;
            }
            listNodes.add(head1);
            listNodes.add(head2);
            listNodes.add(head3);
            return listNodes;
        }
    
    0 赞同 0 条回复
  • * 普通 2023年6月22日 下午10:21

    c实现
    int countNodes(ListNode* head) {
    if (head NULL) {
    return 0;
    }

    ListNode* curr = head;
    int count = 0;
    
    do {
        curr = curr->next;
        count++;
    } while (curr != head);
    
    return count;
    

    }

    void divideCircularList(ListNode* head) {
    int count = countNodes(head);
    int i;
    if (count < 3) {
    printf(“Not enough nodes to divide.\n”);
    return;
    }

    int nodesPerPart = count / 3; 
    int remainingNodes = count % 3; 
    
    ListNode* curr = head;
    ListNode* part1End = NULL;
    ListNode* part2End = NULL;
    ListNode* part3End = NULL;
    
    for (i = 1; i <= count; i++) {
        if (i == nodesPerPart) {
            part1End = curr;
        }
    
        if (i == (2 * nodesPerPart) + remainingNodes) {
            part2End = curr;
        }
    
        if (i == (3 * nodesPerPart) + remainingNodes) {
            part3End = curr;
        }
    
        curr = curr->next;
    }
    
    part1End->next = head;
    part2End->next = part1End->next;
    part3End->next = part2End->next;
    
    ListNode* part1Start = head;
    ListNode* part2Start = part1End->next;
    ListNode* part3Start = part2End->next;
    
    printf("Part 1: ");
    curr = part1Start;
    do {
        printf("%d ", curr->val);
        curr = curr->next;
    } while (curr != part1Start);
    
    printf("\nPart 2: ");
    curr = part2Start;
    do {
        printf("%d ", curr->val);
        curr = curr->next;
    } while (curr != part2Start);
    
    printf("\nPart 3: ");
    curr = part3Start;
    do {
        printf("%d ", curr->val);
        curr = curr->next;
    } while (curr != part3Start);
    

    }

    0 赞同 0 条回复
  • mpweixin用户 永久会员 2023年6月22日 下午8:20
    //能平均分3份,就分
    //不能平均,有一条链多1个或者两个结点
    public class 环形链表三等分 {
        public static void main(String[] args) {
            ListNode head = new ListNode(1);
    
            ListNode cur = head;
            int count = 12;
            for(int i = 2;i <= count;i++){
                cur.next = new ListNode(i);
                cur = cur.next;
            }
    
            System.out.println("没成环前的链表:");
            printList(head);
            cur.next = head;//成环
    
            System.out.println("三等分后");
            List<ListNode> threeListNode = getThreeListNode(head);
            for (ListNode listNode : threeListNode) {
                printList(listNode);
            }
    
        }
        public static List<ListNode> getThreeListNode(ListNode head) {
    
            if(head == null){   //空处理
                return new ArrayList<>();
            }
    
            List<ListNode> threeHead = new ArrayList<>();
            int len = getLen(head);
    
            if(len < 3){    //不够3个结点
                if(len == 1){
                    head.next = null;
                    threeHead.add(head);
                    return threeHead;
                }
                if(len == 2){
                  ListNode head1 = head;
                  ListNode head2 = head.next;
                  head1.next = null;
                  head2.next = null;
                  threeHead.add(head1);
                  threeHead.add(head2);
                  return threeHead;
                }
            }
            int remainder = len % 3;
    
            if(remainder == 0){
                //可以3等分,先走几步,使head3 != head,能进循环
                ListNode head1 = head.next;
                ListNode head2 = head.next.next;
                ListNode head3 = head.next.next.next;
    
                while(head3 != head){
                    head1 = head1.next;
                    head2 = head2.next.next;
                    head3 = head3.next.next.next;
                }
    
                //此时,3个指针已经在3等分点,需要分离出3条链
                threeHead.add(head1.next);
                threeHead.add(head2.next);
                threeHead.add(head3.next);
                head1.next = null;
                head2.next = null;
                head3.next = null;
    
            }else{
                //不能3等分,尽量分,但又链肯定会多出结点
                if(remainder == 1){
                    //余1,大家都先走一步,这样保证走3步的指针能顺的指向头
                    ListNode head1 = head.next;
                    ListNode head2 = head.next;
                    ListNode head3 = head.next;
    
                    while(head3 != head){
                        head1 = head1.next;
                        head2 = head2.next.next;
                        head3 = head3.next.next.next;
                    }
    
                    //此时,3个指针已经在3等分点,需要分离出3条链
                    threeHead.add(head1.next);
                    threeHead.add(head2.next);
                    threeHead.add(head3.next);
                    head1.next = null;
                    head2.next = null;
                    head3.next = null;
                }
    
                if(remainder == 2){
                    //余2,大家都先走2不,这样保证走3步的指针能顺利的指向头
                    ListNode head1 = head.next.next;
                    ListNode head2 = head.next.next;
                    ListNode head3 = head.next.next;
    
                    while(head3 != head){
                        head1 = head1.next;
                        head2 = head2.next.next;
                        head3 = head3.next.next.next;
                    }
    
                    //此时,3个指针已经在3等分点,需要分离出3条链
                    threeHead.add(head1.next);
                    threeHead.add(head2.next);
                    threeHead.add(head3.next);
                    head1.next = null;
                    head2.next = null;
                    head3.next = null;
                }
            }
    
            return threeHead;
        }
    
    
        //=================================辅助方法=============================
        //计算环形链表长度
        private static int getLen(ListNode head) {
            if(head == null){
                return 0;
            }
    
            int len = 1;
            ListNode cur = head.next;
    
            while(cur != head){
                len++;
                cur = cur.next;
            }
            return len;
        }
    
        //打印链表
        public static void printList(ListNode head){
            String temp = "";
            while (head != null){
                temp += head.val+"--->";
                head = head.next;
            }
            temp = temp.substring(0,temp.length()-4);
            System.out.println(temp);
        }
        private static class ListNode {
            Integer val;
            ListNode next;
    
            public ListNode() {
            }
    
            public ListNode(Integer val) {
                this.val = val;
            }
    
        }
    
    
    }
    
    0 赞同 0 条回复
  • zll 普通 2023年6月22日 下午7:15

    默认链表长度为3的倍数
    时间复杂度O(n)
    空间复杂度O(1)

    struct ListNode
    {
        int val;
        struct ListNode *next;
    };
    
    void threeDivide(struct ListNode *head, struct ListNode *first, struct ListNode *second, struct ListNode *third)
    {
        if (!head || !head->next)
            return;
        // 默认链表长度为3的倍数
        first = head;
        second = head;
        third = head;
        while (head != third)
        {
            first = first->next;
            second = second->next->next;
            third = third->next->next->next;
        }
        third = second;
        second = first;
        first = head;
    }
    
    0 赞同 0 条回复
  • 伏月三十 普通 2023年6月22日 下午4:01

    public Node threeDivide(){
    // 链表长度小于3
    if (headnull||head.nextnull||head.next.nextnull){
    return head;
    }
    Node first=head.next.next;
    Node second=head.next;
    Node third=head;
    while (first!=head){
    first=first.next.next.next;
    second=second.next.next;
    third=third.next;
    }
    return third;
    }

    0 赞同 0 条回复
  • désire. 普通 2023年6月22日 下午1:53

    看懂了

    0 赞同 0 条回复
  • 江畅 普通 2023年6月22日 上午10:43
    // 先计算环形链表结点数,分配各分段链表的结点数
    // 遍历分段,对应分段点 next 指针域置 nullptr
    #include <iostream>
    #include <vector>
    using namespace std;
    
    struct ListNode {
        int val;
        ListNode *next;
        ListNode() : val(0), next(nullptr) {}
        ListNode(int x) : val(x), next(nullptr) {}
        ListNode(int x, ListNode *next) : val(x), next(next) {}
    };
    
    class Solution {
    public:
        vector<ListNode*> trisectionCLink(ListNode* head) {
    
            if (head == nullptr) { return {}; }
    
            int cnt = 1;
            ListNode* tmp = head;
            while (tmp->next != head) {
                ++cnt;
                tmp = tmp->next;
            }
    
            // 至少有三个节点
            if (cnt < 3) { return vector<ListNode*>{head}; }
    
            int size1, size2, size3;
            if (cnt % 3 == 0) { 
                size1 = cnt / 3; 
                size2 = cnt / 3; 
                size3 = cnt / 3; 
            }
            else if(cnt % 3 == 1) {
                size1 = cnt / 3; 
                size2 = cnt / 3; 
                size3 = cnt / 3 + 1; 
            }
            else {
                size1 = cnt / 3; 
                size2 = cnt / 3 + 1; 
                size3 = cnt / 3 + 1; 
            }
    
            ListNode* head1 = new ListNode(0);
            ListNode* head2 = new ListNode(0);
            ListNode* head3 = new ListNode(0);
    
            head1->next = head;
            ListNode* cur1 = head1;
            while (size1 > 0) { 
                cur1 = cur1->next; 
                --size1;
            }
    
            head2->next = cur1->next;
            ListNode* cur2 = head2;
            while (size2 > 0) {
                cur2 = cur2->next;
                --size2;
            }
    
            head3->next = cur2->next;
            ListNode* cur3 = head3;
            while (size3 > 0) {
                cur3 = cur3->next;
                --size3;
            }
    
            cur1->next = nullptr;  // 取出 head1 链表
            cur2->next = nullptr;  // 取出 head2 链表
            cur3->next = nullptr;  // 取出 head3 链表
    
            ListNode* l1 = head1->next;
            ListNode* l2 = head2->next;
            ListNode* l3 = head3->next;
            delete head1;
            delete head2;
            delete head3;
            return vector<ListNode*>{l1, l2, l3};
        }
    };
    
    int main() {
        Solution s;
        ListNode* node1 = new ListNode(1);
        ListNode* node2 = new ListNode(2);
        ListNode* node3 = new ListNode(3);
        ListNode* node4 = new ListNode (4);
        ListNode* node5 = new ListNode(5);
        ListNode* node6 = new ListNode (6);
    
        node1->next = node2;
        node2->next = node3;
        node3->next = node4;
        node4->next = node5;
        node5->next = node6;
        node6->next = node1;
    
        ListNode* head = node1;
        vector<ListNode*> res = s.trisectionCLink(head);
    
        ListNode* head1 = res[0];
        while (head1 != nullptr) {
            cout << head1->val << "->";
            head1 = head1->next;
        }
        cout << "nullptr" << endl;
    
        ListNode* head2 = res[1];
        while (head2 != nullptr) {
            cout << head2->val << "->";
            head2 = head2->next;
        }
        cout << "nullptr" << endl;
    
        ListNode* head3 = res[2];
        while (head3 != nullptr) {
            cout << head3->val << "->";
            head3 = head3->next;
        }
        cout << "nullptr" << endl;
    
        delete node1, node2, node3, node4, node5, node6;
        return 0;
    
    }
    
    0 赞同 0 条回复
  • 花老爷 普通 2023年6月22日 上午9:57

    1.能三等分,直接分
    2.不能三等分,舍弃最后多出来的节点再三等分
    时间:O(n)
    空间:O(1)

    class Soluction {
        public List<ListNode> divideCircularList(ListNode head) {
            List<ListNode> res = new ArrayList<>();
            // 当节点数小于3时
            if (head == null || head.next == null || head.next.next == null) {
                return res;
            }
            ListNode cur = head.next;
            int len = 1;
            while (cur != head) {
                len++;
                cur = cur.next;
            }
            // 每份的长度
            int subLen = (len - (len % 3)) / 3;
            ListNode pre = null;
            cur = head;
            for (int i = 0; i < 3; i++) {
                for (int j = 0; j < subLen; j++) {
                    pre = cur;
                    cur = cur.next;
                }
                // 将pre.next置为null,划分成一组,更新head,这里的head代表每一组的头节点
                pre.next = null;
                res.add(head);
                head = cur;
            }
            return res;
        }
    }
    
    0 赞同 0 条回复
  • mpweixin用户 普通 2023年6月22日 上午8:42

    C++
    先遍历整个链表,得到链表的长度。
    如果链表的长度正好可以三等份,就用三指针来做,一个走一步,一个走两步,一个走三步。
    如果不可以,那么询问面试官,可以把多出来的第一个给一步,多出来的第二个给二步。

    TC: O(n)
    SC: O(1)

    “`c++
    int numNodes(ListNode* head) {
    if (!head) {
    return 0;
    }
    ListNode* curr = head;
    curr = curr->next;
    int num = 1;
    while (curr != head) {
    num++;
    curr = curr->next;
    }
    return num;
    }

    vector<ListNode> divideIntoThreeParts(ListNode head) {
    int numOfNodes = numNodes(head);
    if (numOfNodes 0) return {NULL, NULL, NULL};

    // head of each list
    ListNode* dummy1 = new ListNode(0);
    ListNode* curr1 = dummy1;
    
    ListNode* dummy2 = new ListNode(0);
    ListNode* curr2 = dummy2;
    
    ListNode* dummy3 = new ListNode(0);
    ListNode* curr3 = dummy3;
    
    ListNode* curr = head;
    
    // iterate each 3 counts
    int currCount = 0;
    ListNode* tmp;
    while (currCount + 3 <= numOfNodes) {
        // store next one first
        // assign to curr1, curr2, curr3 correspondingly
    
    
    // assign to curr1
    tmp = curr->next;
    curr1->next = curr;
    curr1 = curr1->next;
    curr->next = NULL;
    curr = tmp;
    
    // assign to curr2
    tmp = curr->next;
    curr2->next = curr;
    curr2 = curr2->next;
    curr->next = NULL;
    curr = tmp;
    
    // assign to curr3
    tmp = curr->next;
    curr3->next = curr;
    curr3 = curr3->next;
    curr->next = NULL;
    curr = tmp;
    
    currCount += 3;
    

    }

    // If mod 3 is not 0
    int nodesLeft = numOfNodes - currCount;
    if (nodesLeft >= 1) {
    // assign to curr1
    tmp = curr->next;
    curr1->next = curr;
    curr1 = curr1->next;
    curr->next = NULL;
    curr = tmp;
    if (nodesLeft >= 2) {
    // assign to curr2
    tmp = curr->next;
    curr2->next = curr;
    curr2 = curr2->next;
    curr->next = NULL;
    curr = tmp;
    }
    }
    vector<ListNode*>res = {dummy1->next, dummy2->next, dummy3->next};

    return res;

    }

    int main() {
    // init list
    ListNode* node1 = new ListNode(1);
    ListNode* node2 = new ListNode(2);
    ListNode* node3 = new ListNode(3);
    ListNode* node4 = new ListNode(4);
    ListNode* node5 = new ListNode(5);
    ListNode* node6 = new ListNode(6);
    ListNode* node7 = new ListNode(7);
    node1->next = node2;
    node2->next = node3;
    node3->next = node4;
    node4->next = node5;
    node5->next = node6;
    node6->next = node7;
    node7->next= node1;

    // // res
    vector<ListNode>res = divideIntoThreeParts(node1);
    // test
    for (int i = 0; i < res.size(); i++) {
        ListNode curr = res[i];
        cout << "list " << i << ": ";
        while (curr) {
            cout <<  curr->val << "->";
            curr = curr->next;
        }
        cout << "NULL" << endl;
    }
    /*
    Output:
    list 0: 1->4->7->NULL
    list 1: 2->5->NULL
    list 2: 3->6->NULL
    */
    

    }

    “`

    0 赞同 0 条回复
  • 大鑫啊 普通 2023年6月22日 上午1:37

    先参考一下peach同学的逻辑,暂时没想通,后面再复现
    我们这样处理,先给一个函数,计算环形链表的长度,如果长度是三的倍数,证明可以三等分,如果不是三的倍数,那就不能三等分,直接返回null
    或者让前面的节点个数多一些
    比如余1,第一份多1;余2,第二份多1
    根据情况进行处理
    如果可以三等分,三个节点从头节点开始出发,1步 2步 3步,当3步节点回到头节点,三个节点的位置正好是三等分的位置
    如果余1,第一份多1,那就三个一起走一步,再重复上面的过程,回到头节点就结束
    如果余2,前两份多1,就三个指针一起走一步(第一份多1),再让第一个指针和第二个指针一起走一步(第二份多1)

    public class Demo01 {
        private static List<ListNode> list = new ArrayList<>();
    
        public static List<ListNode> getThreeListNode(ListNode head) {
            if (head == null) {
                list.add(null);
                list.add(null);
                list.add(null);
                return list;
            }
            ListNode l1 = head;
            ListNode l2 = l1;
            ListNode l3 = l1;
            int len = getLen(head);
            int count = len % 3;
            if (count == 0) {
                method1(head, l1, l2, l3);
            } else if (count == 1) {
                method2(head, l1, l2, l3);
            } else {
                method3(head, l1, l2, l3);
            }
            return list;
        }
    
        private static void method3(ListNode head, ListNode l1, ListNode l2, ListNode l3) {
            l1 = l1.next.next;
            l2 = l2.next.next;
            l3 = l3.next;
            method(head, l1, l2, l3);
        }
    
        private static void method2(ListNode head, ListNode l1, ListNode l2, ListNode l3) {
            l1 = l1.next;
            l2 = l2.next;
            l3 = l3.next;
            method(head, l1, l2, l3);
        }
    
        private static void method1(ListNode head, ListNode l1, ListNode l2, ListNode l3) {
            l1 = l1.next.next.next;
            l2 = l2.next.next;
            l3 = l3.next;
            method(head, l1, l2, l3);
        }
    
        private static void method(ListNode head, ListNode l1, ListNode l2, ListNode l3) {
            while (l1 != head) {
                l1 = l1.next.next.next;
                l2 = l2.next.next;
                l3 = l3.next;
            }
            list.add(l1);
            list.add(l2);
            list.add(l3);
        }
    
        private static int getLen(ListNode head) {
            int res = 1;
            ListNode temp = head.next;
            while (temp != head) {
                temp = temp.next;
                res++;
            }
            return res;
        }
    
        private static class ListNode {
            Integer val;
            ListNode next;
    
            public ListNode() {
            }
    
            public ListNode(Integer val) {
                this.val = val;
            }
    
            @Override
            public String toString() {
                return "ListNode{" +
                        "val=" + val +
                        '}';
            }
        }
    
        public static void main(String[] args) {
            System.out.println("hello");
            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 (ListNode node : threeListNode){
                System.out.println(node);
            }
        }
    }
    
    
    0 赞同 0 条回复
  • Vow the vow。 普通 2023年6月21日 下午11:28

    设想是将尾部不足三等分的链表丢弃。使用三个快慢指针,node1一次走一个节点,node2一次走两个节点,node3一次走三个节点。这样每次它们之间的间隔就会加一。
    node节点都指向当前链表的尾部,可以很方便地断开链表。
    只遍历了一次链表,时间复杂度:O(n)

    static class Node{
            private int val;
            private Node next;
    
            Node(int val){
                this.val= val;
                next = null;
            }
        }
    
    
        public static void main(String[] args) {
            // 创建链表
            int[] num1 = {1,2,3,4,5,6,7};
            int[] num2 = {1,2};
    
            Node list1;
            Node list2;
    
            list1 = buildList(num1);
            list2 = buildList(num2);
    
            List res = dilive(list2);
            if(res.size() > 0){
                for(Node head : res){
                    Node cur = head;
                    while(cur != null){
                        System.out.print(cur.val + " ");
                        cur = cur.next;
                    }
                    System.out.println();
                }
            }else{
                System.out.println("null");
            }
    
        }
    
        private static List dilive(Node list) {
            List res = new ArrayList<>();
            Node dummyNode = new Node(-1);
            dummyNode.next = list;
            Node node1 = dummyNode,node2 = dummyNode, node3= dummyNode;
            if(!(node3.next != null && node3.next.next != null && node3.next.next.next != null)){
                return res;
            }
            // 不够等分的节点都在node3链表上
            while(node3.next != null && node3.next.next != null && node3.next.next.next != null){
                node3 = node3.next.next.next;
                node2 = node2.next.next;
                node1 = node1.next;
                System.out.println("val:" + node1.val);
            }
            // 拆分(去除尾部的部分)
            res.add(dummyNode.next);
            res.add(node1.next);
            res.add(node2.next);
            node1.next = null;
            node2.next = null;
            node3.next = null;
            return res;
        }
    
    0 赞同 0 条回复
  • jhfuture 普通 2023年6月21日 下午11:15

    1.可以计算出能不能除3,如果能除的话,n为一分的数目,第一个结点+2n,第二个加上1n,第三个即为head结点。
    2.如果不能则求余,如果余1则第一份多1,余2,则第一个结点和第二个结点都加1.

    public static List<Node> inCise(Node node){
            Node tmp=node;
            int length=0;
            while (tmp!=null) {length++;tmp=tmp.next;}
            Boolean isCan=false;
            int oneLength=0;
            int FirstLength=0;
        int sencodeLength=0;
            if (length%3==0){
                isCan=true;
                oneLength=length/3;
                FirstLength=oneLength+oneLength;
                sencodeLength=oneLength;
            }else if (length%3==1){
                oneLength=length/3;
                FirstLength=oneLength+1+oneLength;
                sencodeLength=oneLength;
            } else if (length%3==2) {
                oneLength=length/3;
                FirstLength=oneLength+1+oneLength;
                sencodeLength=oneLength+1;
            }
            Node FirstNode=node;
                    Node SecondNode=node;
                    Node thridNode=node;
                    Node pre=node;
                    for (int i=0;i<FirstLength;i++){
                        pre=FirstNode;
                        FirstNode=FirstNode.next;
                    }
                    pre.next=null;
        Node pre2=node;
        for (int i=0;i<sencodeLength;i++){
            pre2=SecondNode;
            SecondNode=SecondNode.next;
        }
        pre2.next=null;
        ArrayList<Node> nodes = new ArrayList<>();
        nodes.add(new Node(111111));
        nodes.add(FirstNode);
        nodes.add(new Node(22222));
        nodes.add(SecondNode);
        nodes.add(new Node(3333));
        nodes.add(thridNode);
        return nodes;
    }
    }
    
    0 赞同 0 条回复
  • 怀瑾 永久会员 2023年6月21日 下午11:11

    C++实现环形链表分成三等份

    #include <iostream>
    using namespace std;
    
    struct Node {
        int data;
        Node* next;
        Node(int val) : data(val), next(nullptr) {}
    };
    
    void insert(Node*& head, Node*& tail, int val) {
        Node* node = new Node(val);
        if (!head) {
            head = tail = node;
            tail->next = head;
        } else {
            node->next = head;
            tail->next = node;
            tail = node;
        }
    }
    
    void splitCircularList(Node* head, Node*& firstHead, Node*& firstTail, Node*& secondHead, Node*& secondTail, Node*& thirdHead, Node*& thirdTail) {
        if (!head)
            return;
        Node* currNode = head;
        int count = 0;
        while (currNode) {
            count++;
            currNode = currNode->next;
            if (currNode == head)
                break;
        }
        int size = count / 3;
        currNode = head;
        firstHead = firstTail = currNode;
        for (int i = 1; i < size; i++) {
            currNode = currNode->next;
        }
        firstTail = currNode;
        secondHead = secondTail = firstTail->next;
        for (int i = 1; i < size; i++) {
            currNode = currNode->next;
        }
        secondTail = currNode;
        thirdHead = thirdTail = secondTail->next;
        while (currNode->next != head) {
            currNode = currNode->next;
        }
        thirdTail = currNode;
        firstTail->next = secondTail->next = thirdTail->next = head;
        thirdTail->next = nullptr;
    }
    
    void printList(Node* head) {
        if (!head)
            return;
        Node* currNode = head;
        do {
            cout << currNode->data << " ";
            currNode = currNode->next;
        } while (currNode != head);
        cout << endl;
    }
    
    int main() {
        Node* head = nullptr;
        Node* firstHead = nullptr;
        Node* firstTail = nullptr;
        Node* secondHead = nullptr;
        Node* secondTail = nullptr;
        Node* thirdHead = nullptr;
        Node* thirdTail = nullptr;
    
        insert(head, head, 1);
        insert(head, head, 2);
        insert(head, head, 3);
        insert(head, head, 4);
        insert(head, head, 5);
        insert(head, head, 6);
        insert(head, head, 7);
        insert(head, head, 8);
        insert(head, head, 9);
    
        cout << "Original List: ";
        printList(head);
        splitCircularList(head, firstHead, firstTail, secondHead, secondTail, thirdHead, thirdTail);
        cout << "List after split into three parts: " << endl;
        cout << "Part 1: ";
        printList(firstHead);
        cout << "Part 2: ";
        printList(secondHead);
        cout << "Part 3: ";
        printList(thirdHead);
    
        return 0;
    }
    
    0 赞同 0 条回复
  • peach 普通 2023年6月21日 下午7:00

    思路

    • 我们这样处理,先给一个函数,计算环形链表的长度,如果长度是三的倍数,证明可以三等分,如果不是三的倍数,那就不能三等分,直接返回null
      • 或者让前面的节点个数多一些
      • 比如余1,第一份多1;余2,第二份多1
    • 根据情况进行处理
      • 如果可以三等分,三个节点从头节点开始出发,1步 2步 3步,当3步节点回到头节点,三个节点的位置正好是三等分的位置
      • 如果余1,第一份多1,那就三个一起走一步,再重复上面的过程,回到头节点就结束
      • 如果余2,前两份多1,就三个指针一起走一步(第一份多1),再让第一个指针和第二个指针一起走一步(第二份多1)
      • 这样就可以调整好

    代码

    public class Demo01 {
        private static List<ListNode> list = new ArrayList<>();
    
        public static List<ListNode> getThreeListNode(ListNode head) {
            if (head == null) {
                list.add(null);
                list.add(null);
                list.add(null);
                return list;
            }
            ListNode l1 = head;
            ListNode l2 = l1;
            ListNode l3 = l1;
            int len = getLen(head);
            int count = len % 3;
            if (count == 0) {
                method1(head, l1, l2, l3);
            } else if (count == 1) {
                method2(head, l1, l2, l3);
            } else {
                method3(head, l1, l2, l3);
            }
            return list;
        }
    
        private static void method3(ListNode head, ListNode l1, ListNode l2, ListNode l3) {
            l1 = l1.next.next;
            l2 = l2.next.next;
            l3 = l3.next;
            method(head, l1, l2, l3);
        }
    
        private static void method2(ListNode head, ListNode l1, ListNode l2, ListNode l3) {
            l1 = l1.next;
            l2 = l2.next;
            l3 = l3.next;
            method(head, l1, l2, l3);
        }
    
        private static void method1(ListNode head, ListNode l1, ListNode l2, ListNode l3) {
            l1 = l1.next.next.next;
            l2 = l2.next.next;
            l3 = l3.next;
            method(head, l1, l2, l3);
        }
    
        private static void method(ListNode head, ListNode l1, ListNode l2, ListNode l3) {
            while (l1 != head) {
                l1 = l1.next.next.next;
                l2 = l2.next.next;
                l3 = l3.next;
            }
            list.add(l1);
            list.add(l2);
            list.add(l3);
        }
    
        private static int getLen(ListNode head) {
            int res = 1;
            ListNode temp = head.next;
            while (temp != head) {
                temp = temp.next;
                res++;
            }
            return res;
        }
    
        private static class ListNode {
            Integer val;
            ListNode next;
    
            public ListNode() {
            }
    
            public ListNode(Integer val) {
                this.val = val;
            }
    
            @Override
            public String toString() {
                return "ListNode{" +
                        "val=" + val +
                        '}';
            }
        }
    
        public static void main(String[] args) {
            System.out.println("hello");
            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 (ListNode node : threeListNode){
                System.out.println(node);
            }
        }
    }
    
    1 赞同 0 条回复
  • Ming 普通 2023年6月21日 下午4:33

    考虑是否为三等分,不是则让前面多结点。
    特殊情况为:null,1,2
    根据yxy的思想:与面试官讨论
    – 链表是否是三等分的,是的话则三指针,一个走一步,一个走两步,一个走三步,当三步指针回到开始位置则三等分了
    – 否则计算节点数%3的值,余1则这个给一步指针,让三个指针都前走一步再开始。余2则一步和二步指针各拿一个,即让三个指针都前走一步,再让三步和二步指针都前走一步再开始

    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 (temp.next != head){
                count++;
                temp = temp.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!=head){
                    l3 = l3.next.next.next;
                    l2 = l2.next.next;
                    l1 = l1.next;
                }
                ListNode a2 = l1.next;
                ListNode a3 = l2.next;
                ListNode a1 = l3.next;
                l1.next = null;
                l2.next = null;
                l3.next = null;
                list.add(a1);
                list.add(a2);
                list.add(a3);
            }else{
                int k = count % 3;
                if (k == 1) {
                    l1 = l1.next;
                    l2 = l2.next;
                    l3 = l3.next;
                    while (l3.next != head) {
                        l3 = l3.next.next.next;
                        l2 = l2.next.next;
                        l1 = l1.next;
                    }
                }
                if (k == 2) {
                    l1 = l1.next;
                    l2 = l2.next.next;
                    l3 = l3.next.next;
                    while (l3.next != head) {
                        l3 = l3.next.next.next;
                        l2 = l2.next.next;
                        l1 = l1.next;
                    }
                }
                ListNode a2 = l1.next;
                ListNode a3 = l2.next;
                ListNode a1 = l3.next;
                l1.next = null;
                l2.next = null;
                l3.next = null;
                list.add(a1);
                list.add(a3);
                list.add(a2);
            }
    
    
            return list;
        }
    
    0 赞同 0 条回复
  • yxy 普通 2023年6月21日 下午1:30

    与面试官讨论
    – 链表是否是三等分的,是的话则三指针,一个走一步,一个走两步,一个走三步,当三步指针回到开始位置则三等分了
    – 否则计算节点数%3的值,余1则这个给一步指针,让三个指针都前走一步再开始。余2则一步和二步指针各拿一个,即让三个指针都前走一步,再让三步和二步指针都前走一步再开始

    2 赞同 0 条回复

# 回答此问题

后才能回答