剑指 Offer II day 9

剑指 Offer II 027. 回文链表
在这里插入图片描述
一、反转链表
Java

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    public boolean isPalindrome(ListNode head) {
        StringBuilder stringBuilder=new StringBuilder();
        StringBuilder reverse=new StringBuilder();
        while(head!=null){
            stringBuilder.append(head.val);
            reverse.append(head.val);
            head=head.next;
        }
        reverse.reverse();
        return stringBuilder.toString().equals(reverse.toString());
    }
}

二、快慢指针
找到前半部分链表的尾节点。
反转后半部分链表。
判断是否回文。
恢复链表。
返回结果。
此方法时间复杂度:O(N);空间复杂度:O(1)

Java

class Solution {
    public boolean isPalindrome(ListNode head) {
        if (head == null) {
            return true;
        }
        ListNode firstHalfEnd = endOfFirstHalf(head);
        ListNode secondHalfStart = reverseList(firstHalfEnd.next);
        ListNode p1 = head;
        ListNode p2 = secondHalfStart;
        boolean result = true;
        while (result && p2 != null) {
            if (p1.val != p2.val) {
                result = false;
            }
            p1 = p1.next;
            p2 = p2.next;
        }        
        firstHalfEnd.next = reverseList(secondHalfStart);
        return result;
    }
    private ListNode reverseList(ListNode head) {
        ListNode prev = null;
        ListNode curr = head;
        while (curr != null) {
            ListNode nextTemp = curr.next;
            curr.next = prev;
            prev = curr;
            curr = nextTemp;
        }
        return prev;
    }

    private ListNode endOfFirstHalf(ListNode head) {
        ListNode p = head;
        ListNode q = head;
        while (p.next != null && p.next.next != null) {
            p = p.next.next;
            q = q.next;
        }
        return q;
    }
}

C++

class Solution {
public:
    bool isPalindrome(ListNode* head) {
        if (head == nullptr) {
            return true;
        }
        ListNode* firstHalfEnd = endOfFirstHalf(head);
        ListNode* secondHalfStart = reverseList(firstHalfEnd->next);
        ListNode* p1 = head;
        ListNode* p2 = secondHalfStart;
        bool result = true;
        while (result && p2 != nullptr) {
            if (p1->val != p2->val) {
                result = false;
            }
            p1 = p1->next;
            p2 = p2->next;
        }        
        firstHalfEnd->next = reverseList(secondHalfStart);
        return result;
    }
    ListNode* reverseList(ListNode* head) {
        ListNode* prev = nullptr;
        ListNode* curr = head;
        while (curr != nullptr) {
            ListNode* nextTemp = curr->next;
            curr->next = prev;
            prev = curr;
            curr = nextTemp;
        }
        return prev;
    }
    ListNode* endOfFirstHalf(ListNode* head) {
        ListNode* p = head;
        ListNode* q = head;
        while (p->next != nullptr && p->next->next != nullptr) {
            p = p->next->next;
            q = q->next;
        }
        return q;
    }
};

Python

class Solution:
    def isPalindrome(self, head: ListNode) -> bool:
        if head is None:
            return True
        first_half_end = self.end_of_first_half(head)
        second_half_start = self.reverse_list(first_half_end.next)
        result = True
        first_position = head
        second_position = second_half_start
        while result and second_position is not None:
            if first_position.val != second_position.val:
                result = False
            first_position = first_position.next
            second_position = second_position.next
        first_half_end.next = self.reverse_list(second_half_start)
        return result    
    def end_of_first_half(self, head):
        p = head
        q = head
        while p.next is not None and p.next.next is not None:
            p = p.next.next
            q = q.next
        return q
    def reverse_list(self, head):
        previous = None
        current = head
        while current is not None:
            next_node = current.next
            current.next = previous
            previous = current
            current = next_node
        return previous

剑指 Offer II 028. 展平多级双向链表
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
DFS代码

/*
// Definition for a Node.
class Node {
    public int val;
    public Node prev;
    public Node next;
    public Node child;
};
*/

class Solution {
    public Node flatten(Node head) {
        dfs(head);
        return head;
    }
    public Node dfs(Node node) {
        Node cur = node;
        Node last = null;
        while (cur != null) {
            Node next = cur.next;
            if (cur.child != null) {
                Node childLast = dfs(cur.child);
                next = cur.next;
                cur.next = cur.child;
                cur.child.prev = cur;
                if (next != null) {
                    childLast.next = next;
                    next.prev = childLast;
                }
                cur.child = null;
                last = childLast;
            } else {
                last = cur;
            }
            cur = next;
        }
        return last;
    }
}

时间复杂度:O(n),其中n 是链表中的节点个数。
空间复杂度:O(n)

剑指 Offer II 029. 排序的循环链表
在这里插入图片描述
在这里插入图片描述
首先,循环单链表往往将操作指针p指向尾部(即本题中的最后一个最大值);接着,如果值大于等于最大值或者小于等于最小值,那么往p的后面插入就可以了反之就去查找插入位置,最后插入就可以了。
代码

/*
// Definition for a Node.
class Node {
    public int val;
    public Node next;

    public Node() {}

    public Node(int _val) {
        val = _val;
    }

    public Node(int _val, Node _next) {
        val = _val;
        next = _next;
    }
};
*/

class Solution {
    public Node insert(Node head, int insertVal) {
        if(head == null) {
            Node res = new Node(insertVal);
            res.next = res;
            return res;
        }
        if(head.next == head) {
            head.next = new Node(insertVal, head);
            return head;
        }        
        Node p = head;
        do{
            if(p.next.val >= p.val) {
                if(insertVal >= p.val && insertVal <= p.next.val) {
                    p.next = new Node(insertVal, p.next);
                    return head;
                }
            }
            else {
                if(insertVal >= p.val || insertVal <= p.next.val) {
                    p.next = new Node(insertVal, p.next);
                    return head;
                }
            }
            p = p.next;
        } 
        while(p != head);
        head.next = new Node(insertVal, head.next);
        return head;
    }
}

时间复杂度:O(N)
空间复杂度:O(1)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值