随手练——S(n)=O,判断一个链表是否为“回文”

Posted czc1999

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了随手练——S(n)=O,判断一个链表是否为“回文”相关的知识,希望对你有一定的参考价值。

方法一:T(n)=O(n),S(n)=O(n)

走完一遍链表,每个值入栈,之后再走一遍链表,和每次弹出的栈顶进行比较。

核心:

LNode *p = l->next;
    while (p) {
        s.push(p->data);
        p = p->next;
    }
    p = l->next;
    while (p) {
        if (p->data != s.top()) {
            cout << "fuck" << endl;
            break;
        }
        s.pop();
        p = p->next;
    }
    if (!p)cout << "666" << endl;

完整:

技术分享图片
#include <iostream>
#include <stack>
using namespace std;
typedef struct LNode {
    struct LNode *next;
    int data;
}*LinkList;
LinkList init() {
    LinkList l = (LinkList)malloc(sizeof(LNode));
    l->next = NULL;
    return l;
}

void push_back(LinkList l,int x) {
    LNode *p = l;
    LNode *s= (LNode *)malloc(sizeof(LNode));
    s->data = x;
    while (p->next) {
        p = p->next;
    }
    s->next = p->next;
    p->next = s;
}

int main() {
    int n;
    stack<int>s;
    LinkList l = init();
    cin >> n;
    for (int i = 0; i < n; i++) {
        int t; 
        cin >> t;
        push_back(l, t);
    }
    LNode *p = l->next;
    while (p) {
        s.push(p->data);
        p = p->next;
    }
    p = l->next;
    while (p) {
        if (p->data != s.top()) {
            cout << "fuck" << endl;
            break;
        }
        s.pop();
        p = p->next;
    }
    if (!p)cout << "666" << endl;
    return  0;
}
View Code

 

方法二:T(n)=O(n),S(n)=O(n)

用一个鬼畜(二倍速)指针,一个正常指针,当鬼畜指针到最后NULL时,正常指针正好到中间的位置(奇数),或者前半部分最后一个(偶数),然后将后半部分入栈,再一遍进行比较。

核心:

LNode *p = l->next,*pp=l->next;
    while (pp&&pp->next) {        
        p = p->next;
        pp = pp->next->next;
    }
    p = p->next;//数据为偶数的话,p是停在前半部分最后一个,数据为奇数的话,跳过中间一个没问题
    while (p) {
        s.push(p->data);
        p = p->next;
    }
    p = l->next;
    while (!s.empty()) {
        if (p->data != s.top()) {
            cout << "fuck" << endl;
            break;
        }
        p = p->next; s.pop();
    }
    if (s.empty())cout << "666" << endl;

完整代码:

技术分享图片
#include <iostream>
#include <stack>
using namespace std;
typedef struct LNode {
    struct LNode *next;
    int data;
}*LinkList;
LinkList init() {
    LinkList l = (LinkList)malloc(sizeof(LNode));
    l->next = NULL;
    return l;
}

void push_back(LinkList l,int x) {
    LNode *p = l;
    LNode *s= (LNode *)malloc(sizeof(LNode));
    s->data = x;
    while (p->next) {
        p = p->next;
    }
    s->next = p->next;
    p->next = s;
}

int main() {
    int n;
    stack<int>s;
    LinkList l = init();
    cin >> n;
    for (int i = 0; i < n; i++) {
        int t; 
        cin >> t;
        push_back(l, t);
    }
    LNode *p = l->next,*pp=l->next;
    while (pp&&pp->next) {        
        p = p->next;
        pp = pp->next->next;
    }
    p = p->next;//数据为偶数的话,p是停在前半部分最后一个,数据为奇数的话,跳过中间一个没问题
    while (p) {
        s.push(p->data);
        p = p->next;
    }
    p = l->next;
    while (!s.empty()) {
        if (p->data != s.top()) {
            cout << "fuck" << endl;
            break;
        }
        p = p->next; s.pop();
    }
    if (s.empty())cout << "666" << endl;
    return  0;
}
View Code

 

方法三:T(n)=O(n),S(n)=O(1)

同样用一个鬼畜(二倍速)指针,一个正常指针,不过这次,对后半部分 链表 进行反转

两个方向进行 遍历,到中间结束,这个过程中把原来反转的后半部分链表反转回去

链表反转:

 

void reverse(LinkList l) {
    LNode *pre = NULL, *p = l->next;
    while (p) {
        LNode *t = p->next;
        p->next = pre;
        pre = p;
        p = t;
    }
    l->next = pre;
}

 

核心:(这里反转是没有头结点的,要注意。代码量稍微长了一点,过段时间看该费点劲了)

LNode *p = l->next,*pp=l->next;
    while (pp&&pp->next) {        
        p = p->next;pp = pp->next->next;
    }
    p = p->next;//和上一解法相同
    LNode *pre = NULL;
    while (p) {
        LNode *t = p->next;
        p->next = pre;
        pre = p;
        p = t;
    }
    p = l->next;
    LNode *q = pre;
    pre = NULL;
    while (q) {
        if (p->data != q->data) sign = 1;//需要反转,不能break
        LNode *t = q->next;
        q->next = pre;
        pre = q;
        q = t;
        p = p->next;
    }
    p->next = pre;

完整代码:

技术分享图片
#include <iostream>
#include <stack>
using namespace std;
typedef struct LNode {
    struct LNode *next;
    int data;
}*LinkList;

void push_back(LinkList l, int x) {
    LNode *p = l;
    LNode *s = (LNode *)malloc(sizeof(LNode));
    s->data = x;
    while (p->next) {
        p = p->next;
    }
    s->next = p->next;
    p->next = s;
}

LinkList init() {
    LinkList l = (LinkList)malloc(sizeof(LNode));
    l->next = NULL;
    int n;
    cin >> n;
    for (int i = 0; i < n; i++) {
        int t;
        cin >> t;
        push_back(l, t);
    }
    return l;
}




int main() {
    int n; int sign = 0;
    LinkList l = init();
    LNode *p = l->next,*pp=l->next;
    while (pp&&pp->next) {        
        p = p->next;pp = pp->next->next;
    }
    p = p->next;//和上一解法相同
    LNode *pre = NULL;
    while (p) {
        LNode *t = p->next;
        p->next = pre;
        pre = p;
        p = t;
    }
    p = l->next;
    LNode *q = pre;
    pre = NULL;
    while (q) {
        if (p->data != q->data) sign = 1;//需要反转,不能break
        LNode *t = q->next;
        q->next = pre;
        pre = q;
        q = t;
        p = p->next;
    }
    p->next = pre;

    if (!sign)
        cout << "666" << endl;
    else
        cout << "fuck" << endl;
    return  0;
}
View Code

 

以上是关于随手练——S(n)=O,判断一个链表是否为“回文”的主要内容,如果未能解决你的问题,请参考以下文章

判断链表的回文结构

左神算法书籍《程序员代码面试指南》——2_06判断一个链表是否为回文结构

六种方法判断链表是否为回文序列

回文链表

算法总结之 判断一个链表是否是回文结构

Leetcode链表回文链表(234)