《剑指Offer》第23-33题

AcWing 35. 反转链表

定义一个函数,输入一个链表的头结点,反转该链表并输出反转后链表的头结点。

思考题:

请同时实现迭代版本和递归版本。
样例

输入:1->2->3->4->5->NULL

输出:5->4->3->2->1->NULL

递推

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    def reverseList(self, head):
        """
        :type head: ListNode
        :rtype: ListNode
        """
        p = head
        pre = None
        while p != None:
            temp = p.next
            p.next = pre
            pre = p
            p = temp
        return pre

递归
先我们先考虑 reverseList 函数能做什么,它可以翻转一个链表,并返回新链表的头节点,也就是原链表的尾节点。
所以我们可以先递归处理 reverseList(head->next),这样我们可以将以head->next为头节点的链表翻转,并得到原链表的尾节点tail,此时head->next是新链表的尾节点,我们令它的next指针指向head,并将head->next指向空即可将整个链表翻转,且新链表的头节点是tail。

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        if (!head || !head->next) return head;
        ListNode *tail = reverseList(head->next);
        head->next->next = head;
        head->next = nullptr;
        return tail;
    }
};

AcWing 36. 合并两个排序的链表

输入两个递增排序的链表,合并这两个链表并使新链表中的结点仍然是按照递增排序的。

样例

输入:1->3->5 , 2->4->5

输出:1->2->3->4->5->5

# Definition for singly-linked list.
# class ListNode(object):
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution(object):
    def merge(self, l1, l2):
        """
        :type l1: ListNode
        :type l2: ListNode
        :rtype: ListNode
        """
        head = ListNode(0)
        p = head
        while l1 != None and l2 != None:
            if l1.val < l2.val:
                p.next = l1
                l1 = l1.next
            else:
                p.next = l2
                l2 = l2.next
            p = p.next
        if l1 != None:
            p.next = l1
        else:
            p.next = l2
        '''
        while l1 != None:
            temp = ListNode(l1.val)
            p.next = temp
            p = p.next
            l1 = l1.next
        while l2 != None:
            temp = ListNode(l2.val)
            p.next = temp
            p = p.next
            l2 = l2.next
        p.next = None
        '''
        return head.next
                

AcWing 37. 树的子结构

输入两棵二叉树A,B,判断B是不是A的子结构。

我们规定空树不是任何树的子结构。

样例
在这里插入图片描述

返回 true ,因为B是A的子结构。
算法
(二叉树,递归) O(nm)

代码分为两个部分:

  1. 遍历树A中的所有非空节点R;
  2. 判断树A中以R为根节点的子树是不是包含和树B一样的结构,且我们从根节点开始匹配;
    对于第一部分,我们直接递归遍历树A即可,遇到非空节点后,就进行第二部分的判断。

对于第二部分,我们同时从根节点开始遍历两棵子树:

  1. 如果树B中的节点为空,则表示当前分支是匹配的,返回true;
  2. 如果树A中的节点为空,但树B中的节点不为空,则说明不匹配,返回false;
    如果两个节点都不为空,但数值不同,则说明不匹配,返回false;
    否则说明当前这个点是匹配的,然后递归判断左子树和右子树是否分别匹配即可;

时间复杂度
最坏情况下,我们对于树A中的每个节点都要递归判断一遍,每次判断在最坏情况下需要遍历完树B中的所有节点。
所以时间复杂度是 O(nm),其中 n 是树A中的节点数, m 是树B中的节点数。

# Definition for a binary tree node.
# class TreeNode(object):
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution(object):
    def dfs(self, pRoot1, pRoot2):
        if pRoot2 == None:
            return True
        if pRoot1 == None or pRoot1.val != pRoot2.val:
            return False
            
        return self.dfs(pRoot1.left, pRoot2.left) and self.dfs(pRoot1.right, pRoot2.right) 
            
    def hasSubtree(self, pRoot1, pRoot2):
        """
        :type pRoot1: TreeNode
        :type pRoot2: TreeNode
        :rtype: bool
        """
        if pRoot1 == None or pRoot2 == None:
            return False
        if self.dfs(pRoot1, pRoot2) == True:
            return True
        return self.hasSubtree(pRoot1.left, pRoot2) or self.hasSubtree(pRoot1.right, pRoot2)

AcWing 38. 二叉树的镜像

输入一个二叉树,将它变换为它的镜像。
在这里插入图片描述

# Definition for a binary tree node.
# class TreeNode(object):
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution(object):
    def dfs(self, root):
        
        if root.left :self.dfs(root.left)
        if root.right :self.dfs(root.right)
        root.left, root.right = root.right, root.left
            
    def mirror(self, root):
        """
        :type root: TreeNode
        :rtype: void
        """
        if root != None:
            self.dfs(root)
        

AcWing 39. 对称的二叉树

请实现一个函数,用来判断一棵二叉树是不是对称的。

如果一棵二叉树和它的镜像一样,那么它是对称的。

样例
在这里插入图片描述

# Definition for a binary tree node.
# class TreeNode(object):
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution(object):
    def dfs(self, p, q):
        if p == None or q ==None:
            return p == None and q == None
        return p.val == q.val and self.dfs(p.left, q.right) and self.dfs(p.right, q.left)
    def isSymmetric(self, root):
        """
        :type root: TreeNode
        :rtype: bool
        """
        if root == None :
            return  True
        return self.dfs(root.left, root.right)

AcWing 40. 顺时针打印矩阵

输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字。

样例
输入:
[
[1, 2, 3, 4],
[5, 6, 7, 8],
[9,10,11,12]
]

输出:[1,2,3,4,8,12,11,10,9,5,6,7]

class Solution(object):
    def printMatrix(self, matrix):
        """
        :type matrix: List[List[int]]
        :rtype: List[int]
        """
        n = len(matrix)
        if n == 0:
            return []
        m = len(matrix[0])
        st = [[0] * m for _ in range(n)]
        res = []
        
        dx = [0, 1, 0, -1]
        dy = [1, 0, -1, 0]
        
      
        x = 0
        y = -1
        i = 0
        while len(res) < n * m :
  
            x1 = x + dx[i]
            y1 = y + dy[i]
                
            if x1 < n and x1 >= 0 and y1 < m and y1 >= 0 and st[x1][y1] == 0:
                st[x1][y1] = 1
                x = x1
                y = y1
                
                res.append(matrix[x1][y1])
            else:
                i = (i + 1) % 4
            # print(x, y, i, matrix[x][y])
        return res
                    
                

AcWing 41. 包含min函数的栈

设计一个支持push,pop,top等操作并且可以在O(1)时间内检索出最小元素的堆栈。

push(x)–将元素x插入栈中
pop()–移除栈顶元素
top()–得到栈顶元素
getMin()–得到栈中最小元素

样例
MinStack minStack = new MinStack();
minStack.push(-1);
minStack.push(3);
minStack.push(-4);
minStack.getMin(); --> Returns -4.
minStack.pop();
minStack.top(); --> Returns 3.
minStack.getMin(); --> Returns -1.

直接维护一个单调栈来做

class MinStack(object):

    def __init__(self):
        """
        initialize your data structure here.
        """
        self.stk = []

    def push(self, x):
        """
        :type x: int
        :rtype: void
        """
        self.stk.append(x)

    def pop(self):
        """
        :rtype: void
        """
        self.stk.pop()

    def top(self):
        """
        :rtype: int
        """
        return self.stk[-1]

    def getMin(self):
        """
        :rtype: int
        """
        return min(self.stk)


# Your MinStack object will be instantiated and called as such:
# obj = MinStack()
# obj.push(x)
# obj.pop()
# param_3 = obj.top()
# param_4 = obj.getMin()
class MinStack {
public:
    /** initialize your data structure here. */
    stack<int> stackValue;
    stack<int> stackMin;
    MinStack() {

    }

    void push(int x) {
        stackValue.push(x);
        if (stackMin.empty() || stackMin.top() >= x)
            stackMin.push(x);
    }

    void pop() {
        if (stackMin.top() == stackValue.top()) stackMin.pop();
        stackValue.pop();
    }

    int top() {
        return stackValue.top();
    }

    int getMin() {
        return stackMin.top();
    }
};

/**
 * Your MinStack object will be instantiated and called as such:
 * MinStack obj = new MinStack();
 * obj.push(x);
 * obj.pop();
 * int param_3 = obj.top();
 * int param_4 = obj.getMin();
 */

AcWing 42. 栈的压入、弹出序列

输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否可能为该栈的弹出顺序。

假设压入栈的所有数字均不相等。

例如序列1,2,3,4,5是某栈的压入顺序,序列4,5,3,2,1是该压栈序列对应的一个弹出序列,但4,3,5,1,2就不可能是该压栈序列的弹出序列。

注意:若两个序列长度不等则视为并不是一个栈的压入、弹出序列。若两个序列都为空,则视为是一个栈的压入、弹出序列。

样例
输入:
[1,2,3,4,5]
[4,5,3,2,1]

输出:true

class Solution(object):
    def isPopOrder(self, pushV, popV):
        """
        :type pushV: list[int]
        :type popV: list[int]
        :rtype: bool
        """
        i = 0
        j = 0
        stk = []
        while i < len(pushV):
            stk.append(pushV[i])
            while j < len(popV) and len(stk) > 0 and stk[-1] == popV[j]:
                j += 1
                stk.pop()
            i += 1
        return j == len(popV) and len(stk) == 0
                

AcWing 43. 不分行从上往下打印二叉树

从上往下打印出二叉树的每个结点,同一层的结点按照从左到右的顺序打印。
在这里插入图片描述

# Definition for a binary tree node.
# class TreeNode(object):
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None
class Solution:
    def bfs(self, root):
        res = []
        q = [0 for i in range(10005)]
        hh = 0
        tt = -1
        tt += 1
        q[tt] = root
        
        while hh <= tt:
            t = q[hh]
            hh += 1
            res.append(t.val)
            if t.left != None:
                tt += 1
                q[tt] = t.left
            if t.right != None:
                tt += 1
                q[tt] = t.right
        return res    
    def printFromTopToBottom(self, root):
        """
        :type root: TreeNode
        :rtype: List[int]
        """
        if root == None:
            return []
        return self.bfs(root)
        

AcWing 44. 分行从上往下打印二叉树

从上到下按层打印二叉树,同一层的结点按从左到右的顺序打印,每一层打印到一行。
在这里插入图片描述
宽度优先遍历,一层一层来做

# Definition for a binary tree node.
# class TreeNode(object):
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None
class Solution:
    def bfs(self, root):
        res = []
        
        q = [0 for i in range(10005)]
        hh = 0
        tt = -1
        
        tt += 1
        q[tt] = root

        res.append([root.val])
        while hh <= tt:
            tail = tt
            temp = []
            while hh <= tail:
                t = q[hh]
                hh += 1
             
              
                if t.left != None:
                    tt += 1
                    q[tt] = t.left
                    temp.append(t.left.val)
                if t.right != None:
                    tt += 1
                    q[tt] = t.right
                    temp.append(t.right.val)
            res.append(temp)
        res.pop()
        return res    
    def printFromTopToBottom(self, root):
        """
        :type root: TreeNode
        :rtype: List[int]
        """
        if root == None:
            return []
        return self.bfs(root)
  1. 将根节点插入队列中;
  2. 创建一个新队列,用来按顺序保存下一层的所有子节点;
  3. 对于当前队列中的所有节点,按顺序依次将儿子加入新队列,并将当前节点的值记录在答案中;
  4. 重复步骤2-3,直到队列为空为止。
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    vector<int> get_val(vector<TreeNode*> level)
    {
        vector<int> res;
        for (auto &u : level)
            res.push_back(u->val);
        return res;
    }

    vector<vector<int>> printFromTopToBottom(TreeNode* root) {
        vector<vector<int>>res;
        if (!root) return res;
        vector<TreeNode*>level;
        level.push_back(root);
        res.push_back(get_val(level));
        while (true)
        {
            vector<TreeNode*> newLevel;
            for (auto &u : level)
            {
                if (u->left) newLevel.push_back(u->left);
                if (u->right) newLevel.push_back(u->right);
            }
            if (newLevel.size())
            {
                res.push_back(get_val(newLevel));
                level = newLevel;
            }
            else break;
        }
        return res;
    }
};

AcWing 45. 之字形打印二叉树

请实现一个函数按照之字形顺序从上向下打印二叉树。

即第一行按照从左到右的顺序打印,第二层按照从右到左的顺序打印,第三行再按照从左到右的顺序打印,其他行以此类推。在这里插入图片描述

# Definition for a binary tree node.
# class TreeNode(object):
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution(object):
    def bfs(self, root):
        res = []
        
        q = [0 for i in range(10005)]
        hh = 0
        tt = -1
        
        tt += 1
        q[tt] = root

        res.append([root.val])
        i = 1
        while hh <= tt:
            tail = tt
            temp = []
            while hh <= tail:
                t = q[hh]
                hh += 1
             
              
                if t.left != None:
                    tt += 1
                    q[tt] = t.left
                    temp.append(t.left.val)
                if t.right != None:
                    tt += 1
                    q[tt] = t.right
                    temp.append(t.right.val)
          
            if i % 2 == 1:
                res.append(temp[::-1])
            else:
                res.append(temp)
            i += 1
        res.pop()
        return res    
    def printFromTopToBottom(self, root):
        """
        :type root: TreeNode
        :rtype: List[List[int]]
        """
        if root == None:
            return []
        return self.bfs(root)
posted @ 2021-11-29 14:54  pxlsdz  阅读(23)  评论(0编辑  收藏  举报