L2-002. 链表去重

题目链接:点击打开链接

题意:中文题意;

题解:强模拟。

详细看代码注解(详细):

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <cmath>
using namespace std;

struct node   //记录初始链表 
{
    int key;    
    int next; // 下一个的位置 
}a[101000];

struct node2   // 储存删除后的链表 
{
    int address;  // 自己的位置 
    int key;
}b[101000];

int m=0;  // 记录有多少个被删除的 
int vis[100100]={0};

void delet(int pre,int next)   // 一个dfs pre是上一个的地址,next是当前地址 
{
    int f=0;
    if(next==-1)  // 若当前的地址为 -1 返回 
        return ;
    if(vis[abs(a[next].key)]==0)  // 若 当前地址的值为未出现过 ,标记一下 
    {
        vis[abs(a[next].key)]=1;
    }
    else // 出现的话就删除这个节点 
    {
        a[pre].next=a[next].next; // 删除节点很简单,把当前的next,赋值给上一个next。 
        b[m].address=next;  // 删除列表的中m的的地址赋值为next 
        b[m].key=a[next].key;  // 
        m++;
        f=1; //标记一下 
    }
    if(f)
        delet(pre,a[next].next); // 若删除节点,下一次的pre为这次的pre。下次的next为这次next 
    else
        delet(next,a[next].next); // 若未删除节点 ,下一次的pre为这次的next。下次next为这次next  
}

void print1(int start)
{
    if(start==-1)
        return ;
    if(a[start].next==-1)
        printf("%05d %d %d\n",start,a[start].key,a[start].next);
    else
        printf("%05d %d %05d\n",start,a[start].key,a[start].next);
    print1(a[start].next);
}

void print2()
{
    for(int i=0;i<m-1;i++)
    {
        printf("%05d %d %05d\n",b[i].address,b[i].key,b[i+1].address);
    }
    printf("%05d %d -1\n",b[m-1].address,b[m-1].key);
}

int main()
{
    int n,start,tstart,key,tnext;
    scanf("%d%d",&start,&n);
    while(n--)
    {
        scanf("%d%d%d",&tstart,&key,&tnext);   // 把数组下标变成自己的地址 
        a[tstart].key=key;
        a[tstart].next=tnext;
    }
    delet(-1,start);  //开始判重函数 

    print1(start);
    if(m>1)
        print2();

    return 0;
}

### 关于L2-002链表测试用例解决方案 对于给定的单链表 \( L_1 \rightarrow L_2 \rightarrow \cdots \rightarrow L_{n-1} \rightarrow L_n \),为了将其新排列为 \( L_n \rightarrow L_1 \rightarrow L_{n-1} \rightarrow L_2 \rightarrow \cdots \)[^1],可以采用如下算法: #### 方法概述 该问题可以通过三步来解决:找到中间节点、反转后半部分链表以及合并两部分。 #### 找到中间节点 通过快慢指针的方法寻找链表的中间位置。当快指针到达链表末端时,慢指针正好位于链表中部。 ```python def find_middle_node(head): slow = fast = head while fast and fast.next: slow = slow.next fast = fast.next.next return slow ``` #### 反转后半部分链表 一旦找到了中间节点,就可以切断前半部与后半部之间的连接,并对后半部分执行反转操作。 ```python def reverse_list(node): prev = None curr = node while curr: next_temp = curr.next curr.next = prev prev = curr curr = next_temp return prev ``` #### 合并两部分 完成上述步骤之后,分别从前向后遍历这两段链表,在每一步都将来自第二段的一个结点插入到由第一段构成的新序列之中。 ```python def reorderList(head): if not head or not head.next: return mid = find_middle_node(head) l1 = head l2 = mid.next mid.next = None # 切断前后半部分链接 l2 = reverse_list(l2) dummy = ListNode(0) current = dummy flag = True while l1 or l2: if flag: current.next = l1 l1 = l1.next else: current.next = l2 l2 = l2.next flag = not flag current = current.next return dummy.next ``` 此方法不仅解决了题目中的要求,还保持了原链表结构不变的同时实现了所需变换。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值