【链表专题】百度真题:环形链表分成三等份
本问题对应课程链接:剑指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;
}
}
}
共以下 22 个回答
补卡(默认链表为3的倍数)
“`c++ getThreeListNode(ListNode* head){ ans; ans; ans;
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
vector
if(head->next == head)//只有一个节点
{
vector
head->next = NULL;
ans.push_back(head);
ans.push_back(NULL);
ans.push_back(NULL);
return ans;
}
if(head->next->next == head)// 只有两个节点
{
vector
ListNode* temp = head->next;
temp->next = NULL;
ans.push_back(temp);
head->next = NULL;
ans.push_back(head);
ans.push_back(NULL);
return ans;
}
//三节点及以上
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
if((count%3) == 0)//节点为3的倍数,用3个指针,第一个每次next一次,第二个两次,第三个三次。
//当第三个到达链表尾时,第一个正好在1/3处,第二个在2/3处
{
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;
ans.push_back(a1);
ans.push_back(a2);
ans.push_back(a3);
}else//节点不为3的倍数,将l1、l2先向前走K步,随后l3再走、直至l3.next==head
{
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 = NULL;
l2->next = NULL;
l3->next = NULL;
ans.push_back(a1);
ans.push_back(a2);
ans.push_back(a3);
}
return ans;
}
int main() {val<<endl;
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 = l7;
l7->next = l1;
vector<ListNode> threeListNode = getThreeListNode(l1);
cout<<“size: “<<threeListNode.size()<<endl;
for(int i=0;i<threeListNode.size();i++){
ListNode head = threeListNode[i];
cout<<“List i = “<<i<<endl;
while(head != NULL){
cout<
head = head->next;
}
}
}
统计节点个数+三个指针同步走
打卡
打卡
改了一个cpp版本的
用模拟的思路来做了一个
自己写了一个根据链表尺寸来分割的函数,挺臃肿的。 非3的倍数的时候没有具体细分 5 = 1 + 1 + 3 还是5 = 1 + 2 + 2,细分函数还有待考量。
时间复杂度O(n) 空间复杂度O(1)。
有点难,先打个卡,后面回来做
有点费头发
”’java
//环形链表分成三等份
public class GetThreeListNode{
public static List GetThreeListNode(ListNode head){
//只有一个结点
if(head.next 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;
}
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{
//节点数不是3的倍数
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;
}
}
”’
二
还是有点难顶的。。。
。。不会做打卡
打卡
时间复杂度:O(n)
空间复杂度:O(1)
不是太明白啥意思
暂未考虑非3的整数倍情况