链表操作算法

来源:互联网 发布:二部图推荐算法 编辑:程序博客网 时间:2024/04/29 22:43

单链表操作

判断链表是否有环

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

两个链表是否有交点

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

有交点,求第一个交点

  • 思路:求出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;        }        }}



1 0
原创粉丝点击