剑指Offfer练习记录 数组类

剑指 Offer 数组类

在一个 n * m 的二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个高效的函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。

#暴力
 for row in matrix:
 	if target in row:
 		return True
 return False

从右上角开始,如果Target比右上角大则舍弃第一行,若比右上角小舍弃最后一列。

class Solution:
    def findNumberIn2DArray(self, matrix: List[List[int]], target: int) -> bool:
        if len(matrix)==0 or len(matrix[0])==0:
            return False
        rows=len(matrix)-1
        x=0
        y=len(matrix[0])-1
        while(rows>=x and y>=0):
            corner=matrix[x][y]
            if(target>corner):
                x=x+1
            elif(target<corner):
                y=y-1
            elif(target==corner):
                return True
        return False
取经路上

从左下角开始的版本,似乎用时比右上角少点

class Solution:
    def findNumberIn2DArray(self, matrix: List[List[int]], target: int) -> bool:
        if len(matrix)==0 or len(matrix[0])==0:
            return False
        rows=len(matrix)-1
        x=rows
        cols=len(matrix[0])-1
        y=0
        while(x>=0 and y<=cols):
            corner=matrix[x][y]
            if(target>corner):
                y=y+1
            elif(target<corner):
                x=x-1
            elif(target==corner):
                return True
        return False

####################################################
取经路上

class Solution:
    def findRepeatNumber(self, nums: List[int]) -> int:
        n=len(nums)
        for index in range(0,n):
           while(index !=nums[index]):
                temp=nums[index]
                temp2=nums[temp]
                if(temp2==temp):
                    return temp
                nums[index],nums[temp]=nums[temp],nums[index]

###################################################

取经路上

俺只想说简单题都这样,俺还是继续回去当保安吧。

最开始自己写尝试写了向上 向下 向左 向右四个函数,想法是从左上角开始在一个while循环中依次调用四个函数;然而边界一直处理不好,只能通过一半的测试用例。
索性还是直接看解析了。解析第一个解法 通过维护一个

directions = [[0, 1], [1, 0], [0, -1], [-1, 0]] 

数组可以实现转向


class Solution:
    def spiralOrder(self, matrix: List[List[int]]) -> List[int]:
        if not matrix or not matrix[0]:
            return []        #异常输入检验
        
        rows, columns = len(matrix), len(matrix[0])
        visited = [[False] * columns for _ in range(rows)] #生成一个同样大小的Boolean 值数组来记录是否被访问过。
        total = rows * columns#总共的元素个数
        order = [0] * total#用来放最后的记录

        directions = [[0, 1], [1, 0], [0, -1], [-1, 0]] #四个方向分别是列+1 向右,行+1 向下,列-1 向左,行-1 向上
        row, column = 0, 0 #起始的位置 左上角00
        directionIndex = 0 #用整数值记录当前方向 起始是向右
        for i in range(total):
            order[i] = matrix[row][column] #放入一个值
            visited[row][column] = True#记录
            nextRow, nextColumn = row + directions[directionIndex][0], column + directions[directionIndex][1]#下一个假定位置坐标
            if not (0 <= nextRow < rows and 0 <= nextColumn < columns and not visited[nextRow][nextColumn]): #如果假定坐标没有在边界内或已被访问
                directionIndex = (directionIndex + 1) % 4#转换方向
            row += directions[directionIndex][0] #下一个行坐标
            column += directions[directionIndex][1]#下一个列坐标
        return order

时间复杂度 O(mn)空间复杂度O(mn)

每个元素都要访问一边,并要维护一个布尔数组

第二种解法和自己想的四个函数有相同之处,区别在于比我多了一个(bottom right)

在这里插入图片描述

class Solution:
    def spiralOrder(self, matrix: List[List[int]]) -> List[int]:
        if not matrix or not matrix[0]:
            return []
        rows=len(matrix)
        cols=len(matrix[0])
        left,right,top,bottom=0,cols-1,0,rows-1
        ans=[]
        while(left<=right and bottom>=top):
            for c in range(left,right+1):
                ans.append(matrix[top][c])
            for r in range(top+1,bottom+1):
                ans.append(matrix[r][right])
            if(left<right and bottom > top):
                for c in range (right-1,left,-1):
                    ans.append(matrix[bottom][c])
                for r in range (bottom,top,-1):
                    ans.append(matrix[r][left])
            left,right,top,bottom=left+1,right-1,top+1,bottom-1

        return ans

评论区一个大佬的方法 能通过24/27个用例

还是值得一看的。

class Solution:
    def spiralOrder(self, matrix: List[List[int]]) -> List[int]:
        ans = []
        while matrix:
            ans.extend(matrix[0])#取一行
            matrix = list(zip(* matrix[1:]))[::-1]#剩下的反转矩阵并倒序
        return ans

############################################
在这里插入图片描述

两次二分

先找右侧边界,再找左侧边界。 时间复杂度O(logn)

class Solution:
    def search(self, nums: [int], target: int) -> int:
        # 搜索右边界 right
        i, j = 0, len(nums) - 1
        while i <= j:
            m = (i + j) // 2
            if nums[m] <= target: i = m + 1
            else: j = m - 1
        right = i #right值会停在target 右侧一位数,j会等于target(如果有)
        print(right)
        print(nums[right])
        # 若数组中无 target ,则提前返回
        if j >= 0 and nums[j] != target: return 0
        # 搜索左边界 left
        i = 0
        while i <= j:
            m = (i + j) // 2
            if nums[m] < target: i = m + 1
            else: j = m - 1
        left = j
        return right - left - 1

在这里插入图片描述

二分,返回右子数组的首位元素

class Solution:
    def missingNumber(self, nums: List[int]) -> int:
        i=0
        j=len(nums)-1

        while(i<=j):
            m=(i+j)//2
            if(nums[m]==m):
                i=m+1
            else:
                j=m-1
        return i

暴力

nums=[0,1,2,3,4,5,6,7,9]
now=sum(nums)
full=0
for x in range(0,len(nums)+1):
    full=full+x
print(full-now)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值