链表操作算法

单链表操作

判断链表是否有环

  • 思路:通过两个指针,都从头部开始遍历,第一个指针顺着链表进行遍历,另一个指针一次跳过一个进行遍历,若两个指针相交,则表示指针有环

两个链表是否有交点

  • 思路:两个链表的尾节点是否相同

有交点,求第一个交点

  • 思路:求出S1的长度length1,S2的长度length2,较大先走abs(length1-length2),然后一起走,相等即为交点。

求入环点

  • 思路:从链表头和碰撞节点到入口距离相等:

证明如下:

    假设满走的长度为s, 快指针走的长度为2s,环的长度为r,链表长度为L,入口到相遇点为x,环入口为a,则:

    2s = s + nr -> s = nr

    a + x = s = nr (s为相遇点的距离)

    a + x = (n-1)r + r

    a + x = (n-1)r + L-a

    a = (n-1)r + L - a - x

其中:(n-1)r是周期性的,而L- a - x为相遇点到环的入口点的距离。故而由:a = L - a - x,即:链表头和碰撞节点到入口距离相等。

求环的长度

  • 设pos1为碰撞节点,pos2为从碰撞节点开始遍历环的游标,当到达pos1时,则为环的长度。

带环链表的长度

  • 设碰撞节点为pos1,头结点为pos2,则链表的长度为:头结点到入口的长度+环的长度

链表原地逆序

node_t * reverse_list(node_t *head)
{
        node_t *pre = NULL, *pos, *next = NULL, *ret = NULL;

        if (head == NULL)
                return NULL;

        pos = head;
        while(pos) {
                next = pos->next;
                if (next == NULL)
                        ret = pos;

                pos->next = pre;
                pre = pos;
                pos = next;
        }

        return ret;
}

去掉冗余项

问题描述

  • 一个没有排序的链表,比如list={a,l,x,b,e,f,f,e,a,g,h,b,m},请去掉重复项,并保留原顺序,以上链表去掉重复项后为newlist={a,l,x,b,e,f,g,h,m},请写出一个高效算法(时间比空间更重要)。

分析

  • 利用hash_map, key为链表中已经遍历的节点的内容,开始时为空。从链表头开始遍历:若节点内容以存在在hash表中,则将该节点从链表上摘除;若不存在在hash表上,则将节点内容添加到hash表中,继续向后遍历

代码实现

#include <map>
#include <string>
struct list{
    char value;
    struct list *next;
};

void delete_duplicate(struct list *head)
{
    struct list * list = head, *tmp, *prev = head;
    map<char, char>  value_map;
    while(list != NULL){
        if (value_map.find(list->value) != value_map.end()) {
            //冗余
            prev->next = list->next;
            list = list->next;
        } else {
            value_map[list->value] = list->value;
            prev = list;
            list = list->next;
        }    
    }
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值