数据结构-链表题(23.4.18)

110 阅读2分钟

链表连续子序列

两整数序列A和B已经存入到两个单链表中,设计一个算法,判断序列B是否是序列A的连续子序列。

代码

bool subsequence_pd(node *a, node *b) {
    node *sa = a->next, *sb = b->next;
    int first = sb->data;
    while (sa != NULL) {
        if (sa->data == first) {
            node *ssa = sa->next;
            node *ssb = sb->next;
            while (ssb != NULL) {
                if (ssa->data == ssb->data) {
                    ssa = ssa->next;
                    ssb = ssb->next;
                } else break;
            }
            if (ssb == NULL) return true;
        }
        sa = sa->next;
    }
    return false;
}

题解

这道题由于是判断的连续子序列,所以首先让指针sa遍历链表A,直到sa指向结点的data和链表B头结点后第一个结点的data一致,让指针sb同指针sa一样遍历链表B,并每一轮判断结点sa指向的结点的data是否与sb指向的结点的data一致,如果一致则继续遍历,反之则退出循环,让sa从刚才循环开始的结点继续循环。如果链表B顺利遍历完成,则直接返回true,即链表B是链表A的连续子序列。如果链表A遍历完成后仍然没有找到和链表B一样的序列,则返回false。

(本解法时间复杂度为O(n^2),时间复杂度较高,如果使用KMP算法将会降低时间复杂度,由于没有学习到,本题解就先使用最传统的判断子序列的方法)

判断单链表是否成环

单链表有环,是指单链表的最后一个结点的指针指向了链表中的某个结点,试编写算法判断单链表中是否存在环。

代码

bool ring_pd(node *l) {
    node *s = l->next, *s2 = l->next;
    while (s != NULL && s != s2) {
        s = s->next;
        s2 = s->next;
    }
    if (s == NULL) return false;
    else return true;
}

题解

因为在非循环单链表中,遍历完成的条件是判断最后一个结点的next指针是否指向NULL。但如果该链表成环,指针就会在结点间一直遍历无法结束。

要想判断单链表是否成环,我们可以设置两个指针遍历链表,一个指针指向下一个结点,另一个指针指向下下个结点,即一个指针一次遍历一个结点,另一个遍历两个结点。这样,后一个结点就比前一个结点遍历的速度要快,如果链表成环,那么这两个结点肯定会相遇,此时退出循环返回true。如果函数是因为指针的next指向NULL,则代表链表不成环,返回false。