1. 程式人生 > >隨手練——S(n)=O(1),判斷一個鏈表是否為“回文”

隨手練——S(n)=O(1),判斷一個鏈表是否為“回文”

eof img hide main for stack 回文 ron nod

方法一: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(1),判斷一個鏈表是否為“回文”