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

单链表逆序详解

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;
    }
View Code
使用快慢指针和原地翻转的代码如下:
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;
    }
View Code
原文地址:https://www.cnblogs.com/wxgblogs/p/5766172.html