链表逆序+判断链表是否回文

单链表逆序详解

1.具有链表头的单链表

  假设需要逆序的单链表为:

  则逆序以后的链表为:

  过程:
(1)取p1指向header->next (p1=stu->next);p2保留p1->next(p2=p1->next);将p1->next置为NULL,因为单链表逆序以后,当前的p1节点为尾节点 p1->next=NULL;

(2)取p3保留p2->next (p3=p2->next);将p2插入p1之前(p2->next = p1);p1指向p2指向的节点(p1=p2);p2指向p3指向的节点(p2=p3);


  循环一次修改以后的单链表如下:

(3)重复步骤(2)

  循环一次修改以后的单链表如下:

(4)将header->next指向p1,完成整个单链表的逆序

typedef struct student{
    int number;
    char name[20];
    int score;
    struct student *next;
}student;
student *reverse(student *stu){
    student *p1,*p2,*p3;
    if(stu == NULL ||stu->next == NULL)
        return stu;
    p1=stu->next;                           //p1指向链表头节点的下一个节点
    p2=p1->next;
    p1->next=NULL;
    while(p2){
        p3=p2->next;
        p2->next = p1;
        p1=p2;
        p2=p3;
    }
    stu->next=p1;
    return stu;
}

2.链表回文

  判断一个单向链表是否是回文链表,要求O(n)的时间复杂度和O(1)的空间复杂度。算法有以下几种:

  1. 遍历整个链表,将链表每个节点的值记录在数组中,再判断数组是不是一个回文数组,时间复杂度为O(n),但空间复杂度也为O(n),不满足空间复杂度要求。
  2. 利用栈先进后出的性质,将链表前半段压入栈中,再逐个弹出与链表后半段比较。时间复杂度O(n),但仍然需要n/2的栈空间,空间复杂度为O(n)。
  3. 反转链表法,将链表后半段原地翻转,再将前半段、后半段依次比较,判断是否相等,时间复杂度O(n),空间复杂度为O(1)满足题目要求。

使用快慢指针加栈实现判断的代码如下:

    public boolean chkPalindrome(ListNode A) {
        Stack<Integer> stack = new Stack<Integer>();
        if (A == null || A.next == null)
            return true;
        ListNode quick = A;
        ListNode slow = A;
        boolean flag = false;
        while (quick != null) {
            stack.add(slow.val);
            slow = slow.next;
            quick = quick.next;
            if (quick != null) {
                quick = quick.next;
            } else {
                flag = true;
            }
        }
        if (flag == true)
            stack.pop();
        while (!stack.isEmpty() && slow != null) {
            int va = stack.pop();
            if (va == slow.val)
                slow = slow.next;
            else
                return false;
        }
        if (slow == null && stack.isEmpty())
            return true;
        else
            return false;
    }

使用快慢指针和原地翻转的代码如下:

public boolean chkPalindrome(ListNode A) {
        if (A == null)
            return false;
        if (A.next == null)
            return true;
        ListNode quick = A;
        ListNode slow = A;
        while (quick != null && quick.next != null) {
            quick = quick.next.next;
            slow = slow.next;
        }
        ListNode p = slow.next;
        ListNode p1 = p.next;
        while (p != null) {
            p.next = slow;
            slow = p;
            p = p1;
            if (p1 != null) {
                p1 = p1.next;
            }
        }
        while (A != slow) {
            if (A.val != slow.val) {
                return false;
            }
            if(A.next==slow){
                return true;
            }
            A = A.next;
            slow = slow.next;
        }
        return true;
    }

时间: 2024-10-16 09:31:43

链表逆序+判断链表是否回文的相关文章

编程算法 - 链表逆序 代码(C)

链表逆序 代码(C) 本文地址: http://blog.csdn.net/caroline_wendy 链表逆序, 作为链表操作的基础必须要熟练手写. 主要包含3个部分, 一个指针记录后面节点, 一个指针记录前面节点, 把当前节点指到前面节点, 移动到后面节点, 前后指针依次移动. 非递归链表逆序算法的核心代码只有10行. 代码: /* * main.cpp * * Created on: 2014.9.12 * Author: Spike */ /*eclipse cdt, gcc 4.8.

华为机试题-- 单链表逆序

[问题] 单链表逆序 [代码] #include <stdio.h> #include <stdlib.h> #include <string.h> typedef struct ListNode { int value; struct ListNode *next; }ListNode; typedef struct ListNode *List; List reverseList(List head) //列表逆序 { ListNode *rear, *curr,

逆序单链表

? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86

逆序建立链表

题目描述 输入整数个数N,再输入N个整数,按照这些整数输入的相反顺序建立单链表,并依次遍历输出单链表的数据. 输入 第一行输入整数N;: 第二行依次输入N个整数,逆序建立单链表. 输出 依次输出单链表所存放的数据. 示例输入 10 11 3 5 27 9 12 43 16 84 22 示例输出 22 84 16 43 12 9 27 5 3 11 #include <iostream> #include <malloc.h> using namespace std; struct

[2013] 链表逆序

题目二:逆序链表输出. 题目描述:   将输入的一个单向链表,逆序后输出链表中的值.链表定义如下: typedef struct tagListNode  {        int value;        struct tagListNode *next;  }ListNode;   要求实现函数:   void converse(ListNode **head); [输入]head:    链表头节点,空间已经开辟好 [输出]head:    逆序后的链表头节点 [返回]无 [注意]只需要

剑指Offer03 逆序输出链表

多写了个逆序链表 1 /************************************************************************* 2 > File Name: 03_Pirnt_LinkList.c 3 > Author: Juntaran 4 > Mail: [email protected] 5 > Created Time: 2016年08月24日 星期三 02时04分25秒 6 ***************************

单链表逆序或者逆序输出

分为两种情况,一种是只逆序输出,实际上不逆序:另一种是把链表逆序. ********************逆序输出*********************** 1 #include<iostream> 2 #include<stack> 3 #include<assert.h> 4 using namespace std; 5 6 7 typedef struct node{ 8 int data; 9 node * next; 10 }node; 11 12 //

链表逆序 和 寻找链表中间节点

已知链表的头节点为head,写一个函数把链表逆序. void reserve(list_node* head){ if(head == NULL) return 0; list_node* p = head; list_node* q = p->next; list_node* r = NULL; while(q){ r = q->next; q->next = p; p = q; q = r; } head->next == NULL; head = p; } 找出单链表的中间节

[链表常用技巧]链表逆序+链表中点

链表逆序 给定一个链表,一般的逆序的方法要设置三个指针,这种操作很繁琐,下面总结一种简单的方法: 为链表设置一个头结点,然后head后面的节点依次的插入到head结点之前.最后完成链表的逆序. 代码实现: ListNode* reverseList(ListNode* head) { if(head == NULL) return NULL; ListNode dummy(-1); dummy.next = head; ListNode *pre = dummy.next; while(pre-