剑指offer之二维数组的查找,替换空格,从尾到头打印链表,重建二叉树,栈实现队列

1、二维数组的查找:

问题描述:在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。

代码实现:

# -*- coding:utf-8 -*-
class Solution:
    # array 二维列表
    '''
    #从第一行第最后一列开始比较(右上角)
    def Find(self, target, array):
        # write code here
        if len(array)==0 or len(array[0])==0:
            return False
        i=0
        j=len(array[0])-1
        while i<len(array) and j>=0:
            if array[i][j]==target:
                return True
            elif array[i][j]<target:
                i=i+1
            else:
                j=j-1
        return False
    '''
     
    #第二种:从第最后一行第0列的位置开始比较(与第一种只是颠倒了i和j)
    def Find(self, target, array):
        if len(array)==0 or len(array[0])==0:
            return False
        i=len(array)-1
        j=0
        while i>=0 and j<len(array[0]):
            if array[i][j]==target:
                return True
            elif array[i][j]<target:
                j+=1
            else:
                i-=1
        return False

第一次做剑指offer,一只知道二分查找的思想,就极少使用,参考着别人的回答和分析,做了此题。

此二维数组比较特殊,每行中右边的数比左边的数大,每列中下边的数比上边的数大。

将行号,列号比作平常所见的一维数据中的low,high,初始设置第0行第最后一列,mid的位置就是第0行第最后一列,将此位置的数与目标值比较;

比目标值大说明目标值在此位置的左上侧,列号减减;

比目标值小说明目标值在此位置的右下侧,行号加加;

如此查找。

第二种类似的方法也可以这样:

将行号,列号比作平常所见的一维数据中的high,low,初始设置第最后1行第一列,mid的位置就是第最后一行第一列,将此位置的数与目标值比较;

比目标值大说明目标值在此位置的左上侧,行号减减;

比目标值小说明目标值在此位置的右下侧,列号加加;

2、替换空格:

问题描述:请实现一个函数,将一个字符串中的每个空格替换成“%20”。例如,当字符串为We Are Happy.则经过替换之后的字符串为We%20Are%20Happy。

代码实现:

# -*- coding:utf-8 -*-
#import re
class Solution:
    # s 源字符串
    def replaceSpace(self, s):
        # write code here
        #1
        #return re.sub(' ','%20',s)
        #2
        #return s.replace(' ','%20')
        #3字符串是不可变对象,所以可以先变成list(暂时有问题)
        s1=list(s)
        length=len(s1)
        for i in range(length-1,-1,-1):
            if s1[i]==' ':
                s=s+'  '
                s1.append(' ')
                s1.append(' ')
                length+=2
                j=length-1
                while (j-2)>i:
                    s1[j]=s[j-2]
                    j-=1
                s1[i]='%'
                s1[i+1]='2'
                s1[i+2]='0'
                s=''.join(s1)
        return s
         
        #4将旧字符串换到了新字符串
        '''
        str=''
        for i in s:
            if i==' ':
                str=str+'%20'
            else:
                str=str+i
        return str
        '''

具体的解题思路是将字符串转换成list列表的形式,主要是因为s作为字符串是不可变对象。

转换后的s是s1,从后往前比较,遇到空格就进行如下操作:  1s1列表增加2个位置,长度加2,;

    2将遇到到空格后面的字母往后挪2个位置,并在空格位置及之后的两个位置填入%20

    3如此反复,直到遍历完成整个list;

    4比较次数时列表的长度,移动次数是sum(每个空格后面的元素个数)

    5最后把list形式的s1转化成string的s

3、从尾到头打印链表:

问题描述:输入一个链表,按链表值从尾到头的顺序返回一个ArrayList。

代码实现:

# -*- coding:utf-8 -*-
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None
 
class Solution:
    # 返回从尾部到头部的列表值序列,例如[1,2,3]
    def printListFromTailToHead(self, listNode):
        # write code here
        head=listNode
        array=[]
        while head is not None:
            array.append(head.val)
            head=head.next
        array.reverse()
        return array

主要是遍历整个链表,从头到尾,并把节点的值(val)赋给Arraylist,最后使用reverse()函数把整个list逆序一下。

4、重建二叉树

问题描述:输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。

代码实现:

# -*- coding:utf-8 -*-
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None
class Solution:
    # 返回构造的TreeNode根节点
    def reConstructBinaryTree(self, pre, tin):
        # write code here
        if pre==[]:
            return None
        val=pre[0]
        index=tin.index(val)
        ltin=tin[0:index]
        rtin=tin[index+1:]
        lpre=pre[1:1+len(ltin)]
        rpre=pre[1+len(ltin):]
        root=TreeNode(val)
        root.left=self.reConstructBinaryTree(lpre,ltin)
        root.right=self.reConstructBinaryTree(rpre,rtin)
        return root

主要是通过二叉树的前序和中序序列,构造二叉树。

首先根据二叉树的前序遍历中的第一个值知道二叉树的根节点(root),同时该节点将中序序列分成了左右子树;

然后再根据前序序列的第二个值知道左子树的根节点,同时将中序序列中的左子树又分为左右子树,以此类推直到将左边子树划分为完,再以同样的方式划分右子树,直到划分完;

最后输出节点值。

5、用2个栈实现队列

问题描述:用两个栈来实现一个队列,完成队列的Push和Pop操作。 队列中的元素为int类型。

代码实现:

# -*- coding:utf-8 -*-
class Solution:
    def __init__(self):
        self.stack1=[]
        self.stack2=[]
    def push(self, node):
        # write code here
        self.stack1.append(node)
    def pop(self):
        # return xx
        if len(self.stack2):
            return self.stack2.pop()
        while self.stack1:
            self.stack2.append(self.stack1.pop())
        return self.stack2.pop()

队列的特点是先进先出,栈的特点是先进后出。

使用两个栈(先进后出)实现队列的先进先出的主要想法是:

    push和pop分别通过不同的栈实现,Push的时候放进一个栈stack1中,pop时从另一个栈中出stack2,而stack1和stack2的关系是stack2的内容是从stack1中来的,stack1中栈底是最先进入的值,栈顶是最后进来的值,这样stack2中栈底的值就是最后进来的值,栈顶的值是最先进入的,从stack2中出栈便能得到最先进入的值。

通过两个栈的合作便能实现队列的功能,先进先出。

 

以上参考牛客网的剑指offer题目以及其他题友的分析。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值