剑指offer解题思路简述 21-30

  • 面试题21:调整数组顺序使奇数位于偶数前面

方法一:设置前后两个指针,前面的指针往后移,当前面的指针指向的数是偶数时,后面往前移,当后面的指针指向奇数时,两个指针的数据交换,直到两个指针重合

class Solution:
    def exchange(self, nums: List[int]) -> List[int]:
        i, j = 0, len(nums) - 1
        while i < j:
            while i < j and nums[i] & 1 == 1: i += 1
            while i < j and nums[j] & 1 == 0: j -= 1
            nums[i], nums[j] = nums[j], nums[i]
        return nums

方法二:从头遍历,偶数放一个list里,奇数放一个list里,然后拼接两个list,需要额外的空间

# -*- coding:utf-8 -*-
class Solution:
    def reOrderArray(self, array):
        # write code here
        odd=[]
        even=[]
        for i in array:
            if i%2==1:
                odd.append(i)
            else: 
                even.append(i)
        return(odd+even)
  • 面试题22:链表中倒数第K个节点

方法一:先遍历一遍链表,得到链表的长度l,然后指针走l-k步

class Solution:
    def FindKthToTail(self, head, k):
        # write code here
        #需要判断k是否超过长度或者是空链表
        if head==None:return
        len=1
        temp=head
        while(temp.next!=None):
            len=len+1
            temp = temp.next
        if k>len :return
        for _ in range(len-k):
            head = head.next
        return head

方法二:两个指针,第一个指针走k,然后从第K步开始,第二个指针开始一起走,当第一个指针式到尾节点时,第二个指针正好指向倒数第k个,要注意代码的鲁棒性:判断K是否为正数,k是否大于链表长度,链表是否是空

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

class Solution(object):
    def getKthFromEnd(self, head, k):
        """
        :type head: ListNode
        :type k: int
        :rtype: ListNode
        """
        result = head
        temp = head
        num = 1
        while num != k and temp:
            temp = temp.next
            num += 1
        if num != k:# 判断是否存在倒数第K个节点
            return None
        while temp.next:
            result = result.next
            temp = temp.next
        return result

class Solution:
    def middleNode(self, head):
        slow = fast = head
        while fast and fast.next:
            slow = slow.next
            fast = fast.next.next
        return slow
  • 面试23:链表中的入口节点

方法一:第一步,确定是否有环,设置两个指针,一个一次走一步,一个一次走两步,当走两步的到了链表的结尾还没遇到走的慢的,则没有环,否则有环。第二步,确定环中节点的个数,在第一步的基础上,一个指针不动,另一个指针每次移动一步,直到再次相遇,计数n。第三步,重新用两个指针,一个先走n步,另一个再走,相遇的点即为入口节点

方法二:每次把节点放入set类型中,如果有重复说明即是环的入口

class Solution:
    def EntryNodeOfLoop(self, pHead):
        # write code here
        if not pHead:
            return None
        pset = {}
         
        while True:
            pset.add(pHead)
            pHead = pHead.next
            if not pHead:
                return None
            if pHead in plist:
                return pHead
  • 面试24:反转链表

方法1:如果只有一个节点,可以直接返回。设置三个指针,一个a指向pHead.next,另一个b指向a.next,然后在while循环中,pHead,a,b依次往后移动

class Solution:
    # 返回ListNode
    def ReverseList(self, pHead):
        # write code here
        if (pHead==None or pHead.next==None):
            return pHead
        
        a = pHead
        b = pHead.next
        c = b.next
        a.next= None
        while(c!=None):
            b.next=a
            a = b
            b = c
            c = c.next
        b.next = a
        return b

方法2:递归 https://zhuanlan.zhihu.com/p/60117407?from_voters_page=true  全网最详细,思路用递归先找到尾节点作为头节点,然后依次往前挨个反转

class Solution:
    def reverseList(self, head):
        if not head:
            return None
        if not head.next:
            return head
        headNode = self.reverseList(head.next)
        head.next.next = head
        head.next = None
        return headNode
  • 面试25:合并两个排序的链表

方法一:while循环,创建两个空节点ans=res=ListNode(0),res负责反复循环里面不断指向合并链表的下一位,循环的退出条件是其中一个链表的next为空,退出后将res.next指向剩下的不为空的那个链表,return ans.next

class Solution:
    # 返回合并后列表
    def Merge(self, pHead1, pHead2):
        # write code here
        if(pHead1==None):
            return pHead2
        if(pHead2==None):
            return pHead1
        ans=res=ListNode(0)
        while pHead1 and pHead2:
            if pHead1.val<pHead2.val:
                res.next=pHead1
                pHead1=pHead1.next
            else:
                res.next=pHead2
                pHead2=pHead2.next
            res=res.next
        res.next=pHead1 or pHead2
        return ans.next
  • 面试26:树的子结构

方法:构建一个子函数专门判断每个节点是否相等,主函数里挨个遍历左右节点作为根节点传入到前面构建的函数中。

class Solution:
    def isSubStructure(self, pRoot1, pRoot2):
        # write code here
        if not pRoot1 or not pRoot2:
            return False     
        return self.recur(pRoot1,pRoot2) or self.isSubStructure(pRoot1.left, pRoot2) or self.isSubStructure(pRoot1.right, pRoot2)
     
    def recur(self, root1, root2):
        if not root2:
            return True
        if not root1:
            return False
        return root1.val==root2.val and self.recur(root1.right,root2.right) and self.recur(root1.left,root2.left)
  • 面试题27:二叉树的镜像

方法:递归,交换左右子树,然后分别将左右节点作为根节点递归调用函数

class Solution:
    # 返回镜像树的根节点
    def Mirror(self, root):
        # write code here
        if root==None: 
            return None
        root.left,root.right = root.right,root.left
        self.Mirror(root.left)
        self.Mirror(root.right)
        return root
  • 面试题28:对称的二叉树

方法:主函数里调用判断是否为镜像的子函数,子函数里递归判断sMirror(left.left,right.right) and self.isMirror(left.right,right.left)

class Solution:
    def isSymmetrical(self, pRoot):
        if not pRoot:
            return True
        else:
            return self.isMirror(pRoot.left,pRoot.right)
          
    def isMirror(self,left,right):
        if not left and not right:
            return True
        elif not left or not right:
            return False
        return (left.val == right.val) and self.isMirror(left.left,right.right) and self.isMirror(left.right,right.left)
  • 面试题29:顺时针打印矩阵

方法:先判断行数为1和列数为1的情况,单独处理,然后while循环,设置一个标志位,转了几圈。while(row>i*2 and col>j*2):这个是每一圈的左上角的条件。里面分成四个while循环,每个while的条件是i或者j和行数列数以及flag的关系。最后while循环结束,处理特殊情况:当是正方形且边长为奇数,则需要append最中心的数;若行列不相等且都是奇数,则pop掉最后一个数。

class Solution:
    # matrix类型为二维列表,需要返回列表
    def printMatrix(self, matrix):
        # write code here
        if matrix ==[]:return []
        row = len(matrix)
        col = len(matrix[0])
        flag = 1
        i = 0
        j = 0
        result = []
        if row == 1:
            while(j<col):
                result.append(matrix[i][j])
                j = j+1
            return result
        if col == 1:
            while(i<row):
                result.append(matrix[i][j])
                i = i+1
            return result

        while(row>i*2 and col>j*2):
            while(j<col-flag):
                result.append(matrix[i][j])
                j = j+1

            while(i<row-flag):
                result.append(matrix[i][j])
                i = i+1

            while(j>flag-1):
                result.append(matrix[i][j])
                j = j-1

            while(i>flag-1):
                result.append(matrix[i][j])
                i = i-1
                
            i = i+1
            j =j+1
            flag = flag +1

        if(row%2==1 and col==row):
            result.append(matrix[row/2][col/2])
        if(row%2==1 and col!=row and col%2==1):
            result.pop()
        return result
  • 面试题30:包含min函数的栈

方法:建立一个辅助栈,存在当前状态的最小值,push时比较push元素和当前最小元素的值,如当前元素较小,则push到辅助栈,pop时两个栈需要同时pop

# -*- coding:utf-8 -*-
class Solution:
    def __init__(self):
        self.stack=[]
        self.minstack=[]
    def push(self, node):
        # write code here
        self.stack.append(node)
        if not self.minstack or node<=self.minstack[-1]:
            self.minstack.append(node)
        else:
            self.minstack.append(self.minstack[-1])
    def pop(self):
        # write code here
        #if not self.stack:
        self.stack.pop()
        self.minstack.pop()
    def top(self):
        # write code here
        return self.stack[-1]
    def min(self):
        # write code here
        return self.minstack[-1]

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值