leetcode 数组题选

17.10. 主要元素

数组中占比超过一半的元素称之为主要元素。给定一个整数数组,找到它的主要元素。若没有,返回-1。

示例 1:                                            示例二:                               示例 3:
输入:[1,2,5,9,5,9,5,5,5]                           输入:[3,2]                            输入:[2,2,1,1,1,2,2]
输出:5                                             输出:-1                               输出:2

思路:主要元素个数大于数组长度的一半,一个主要元素与一个非主要元素相互抵消,最后剩下的就是主要元素

代码:

class Solution:
    def majorityElement(self, nums: List[int]) -> int:
        if not nums:
            return
        e,cnt = nums[0],1
        #一个主要元素抵消一个非主要元素,最后剩下的一定是主要元素(存在主要元素)
        for o in nums[1:]:
            if cnt==0:
                e,cnt = o,1
                continue
            if o!=e:
                cnt -=1
            else:
                cnt +=1
        
        #再遍历判断是否为主要元素
        cnt =0
        for num in nums:
            if num == e:
                cnt += 1
        if cnt > (len(nums) // 2):
            return e 
        else:
            return -1

832. 翻转图像

给定一个二进制矩阵 A,我们想先水平翻转图像,然后反转图像并返回结果。

水平翻转图片就是将图片的每一行都进行翻转,即逆序。例如,水平翻转 [1, 1, 0] 的结果是 [0, 1, 1]。

反转图片的意思是图片中的 0 全部被 1 替换, 1 全部被 0 替换。例如,反转 [0, 1, 1] 的结果是 [1, 0, 0]。
示例 1:

输入: [[1,1,0],[1,0,1],[0,0,0]]
输出: [[1,0,0],[0,1,0],[1,1,1]]
解释: 首先翻转每一行: [[0,1,1],[1,0,1],[0,0,0]];
     然后反转图片: [[1,0,0],[0,1,0],[1,1,1]]

示例2:

输入: [[1,1,0,0],[1,0,0,1],[0,1,1,1],[1,0,1,0]]
输出: [[1,1,0,0],[0,1,1,0],[0,0,0,1],[1,0,1,0]]
解释: 首先翻转每一行: [[0,0,1,1],[1,0,0,1],[1,1,1,0],[0,1,0,1]];
     然后反转图片: [[1,1,0,0],[0,1,1,0],[0,0,0,1],[1,0,1,0]]

思路:交换对应位置,并且取反(与1取异或,0 ^ 1 = 1,1 ^ 1=0)

代码:

class Solution:
    def flipAndInvertImage(self, A: List[List[int]]) -> List[List[int]]:
        m = len(A);n=len(A[0])
        mid = (n+1)//2
        for i in range(m):
            for j in range(mid):
                A[i][j],A[i][n-j-1] = A[i][n-j-1] ^ 1,A[i][j] ^ 1
        return A

1233. 删除子文件夹

你是一位系统管理员,手里有一份文件夹列表 folder,你的任务是要删除该列表中的所有 子文件夹,并以 任意顺序 返回剩下的文件夹。

我们这样定义「子文件夹」:

  • 如果文件夹 folder[i] 位于另一个文件夹 folder[j] 下,那么 folder[i] 就是 folder[j] 的子文件夹。

文件夹的「路径」是由一个或多个按以下格式串联形成的字符串:

  • / 后跟一个或者多个小写英文字母。
    例如,/leetcode 和 /leetcode/problems 都是有效的路径,而空字符串和 / 不是。

示例1:

输入:folder = ["/a","/a/b","/c/d","/c/d/e","/c/f"]
输出:["/a","/c/d","/c/f"]
解释:"/a/b/" 是 "/a" 的子文件夹,而 "/c/d/e" 是 "/c/d" 的子文件夹。

示例2:

输入:folder = ["/a","/a/b/c","/a/b/d"]
输出:["/a"]
解释:文件夹 "/a/b/c" 和 "/a/b/d/" 都会被删除,因为它们都是 "/a" 的子文件夹。

示例3:

输入:folder = ["/a/b/c","/a/b/d","/a/b/ca"]
输出:["/a/b/c","/a/b/ca","/a/b/d"]

提示:

  • 1 <= folder.length <= 4 * 10^4
  • 2 <= folder[i].length <= 100
  • folder[i] 只包含小写字母和 /
  • folder[i] 总是以字符 / 起始
  • 每个文件夹名都是唯一的
    提示:用hash表存储所有的文件夹,遍历每一个文件夹的字符串前缀,如果前缀在hash表中,说明是子文件夹
class Solution:
    def removeSubfolders(self, folder: List[str]) -> List[str]:
        m= {}
        for folde in folder:
            m[folde]=1
        
        res = []
        for folde in folder:
            tmp,j = "/",1
            flag = True
            fil_len = len(folde)
            while j < fil_len:    #取前缀,不能是整个字符串
                if folde[j]=="/" and  j!=1: #遍历到"/"字符时开始验证
                    if  m.get(tmp,0)!=0:   #前缀在hash表中,说明是子文件夹
                        flag = False
                        break
                tmp +=folde[j]
                j +=1
            if flag:                #将不是子文件夹的文件夹加入到最终结果中
                res.append(folde)
        return res

969. 煎饼排序

给定数组 A,我们可以对其进行煎饼翻转:我们选择一些正整数 k <= A.length,然后反转 A 的前 k 个元素的顺序。我们要执行零次或多次煎饼翻转(按顺序一次接一次地进行)以完成对数组 A 的排序。

返回能使 A 排序的煎饼翻转操作所对应的 k 值序列。任何将数组排序且翻转次数在 10 * A.length 范围内的有效答案都将被判断为正确。
示例1:

输入:[3,2,4,1]
输出:[4,2,4,3]
解释:
我们执行 4 次煎饼翻转,k 值分别为 4,2,4,和 3。
初始状态 A = [3, 2, 4, 1]
第一次翻转后 (k=4): A = [1, 4, 2, 3]
第二次翻转后 (k=2): A = [4, 1, 2, 3]
第三次翻转后 (k=4): A = [3, 2, 1, 4]
第四次翻转后 (k=3): A = [1, 2, 3, 4],此时已完成排序。 

示例2:

输入:[1,2,3]
输出:[]
解释:
输入已经排序,因此不需要翻转任何内容。
请注意,其他可能的答案,如[3,3],也将被接受。

提示:

  • 1 <= A.length <= 100
  • A[i] 是 [1, 2, …, A.length] 的排列

思路1:将n个元素最大的元素先翻转到末尾,再翻转到末尾,再翻转前n-1个的元素的最大值到n-1个位置,一直到数组最前面

class Solution:
   def pancakeSort(self, arr: List[int]) -> List[int]:
       res = []
       n = len(arr)
       while n>1:
           idx  = arr.index(n)   #[0,n)最大元素位置([0,n)最大元素一定为n)
           if idx + 1 == n:      #最大元素在末尾,不用翻转
               n -= 1
               continue
           arr = arr[:idx+1][::-1] + arr[idx+1:]    # 最大元素翻转到开头
           res.append(idx+1)     #记录翻转长度

           res.append(n)
           arr = arr[:n][::-1]+arr[n:]       #最大元素翻转到结尾
           n -= 1
       return res

更快的思路2(两次翻转合并为一次)
在这里插入图片描述
代码

class Solution:
   def pancakeSort(self, arr: List[int]) -> List[int]:
       res = []
       n = len(arr)
       while n>1:
           idx  = arr.index(n)
           if idx + 1 == n:
               n -= 1
               continue

           res.append(idx+1)
           res.append(n)

           arr = arr[idx+1:n][::-1]+arr[:idx+1] + arr[n:]       #一次翻转即可
           n -= 1
       return res

64. 最小路径和

给定一个包含非负整数的 m x n 网格,请找出一条从左上角到右下角的路径,使得路径上的数字总和为最小。

说明:每次只能向下或者向右移动一步。
示例:

输入:
[
  [1,3,1],
  [1,5,1],
  [4,2,1]
]
输出: 7
解释: 因为路径 1→3→1→1→1 的总和最小。

思路:到点(i,j)的最短路径为= (到点(i-1,j)与到点(i,j-1)的路径的最小值) + 点(i,j)的值(动态规划的思路)
代码(直接修改原始矩阵,若不能,可以重新开辟一个一维数组):

class Solution:
    def minPathSum(self, grid: List[List[int]]) -> int:
        if not grid:
            return 0
        m = len(grid);n=len(grid[0])
        for i in range(m):
            for j in range(n):
                if j>0 and i>0:
                    grid[i][j] += min(grid[i-1][j],grid[i][j-1])   #上,左最短路径的最小值
                if i == 0 and j > 0:       
                    grid[i][j] += grid[i][j-1]   #第一行,直接取左边的点最短路径值
                if i > 0 and j==0:
                    grid[i][j] += grid[i-1][j]   #第二列,直接取上边的点最短路径值
        return grid[m-1][n-1]

78. 子集

给定一组不含重复元素的整数数组 nums,返回该数组所有可能的子集(幂集)。

说明:解集不能包含重复的子集。
示例:

输入: nums = [1,2,3]
输出:
[
  [3],
  [1],
  [2],
  [1,2,3],
  [1,3],
  [2,3],
  [1,2],
  []
]

思路1:数组中的每一个元素都有两种情况,存在与不存在,采用递归的思路

class Solution:
    def subsets(self, nums: List[int]) -> List[List[int]]:
        re = [[]]

        for num in nums:
            re += [e + [num]  for e in re]
        return re

思路二:用二进制0,1来代表有无,从全0遍历到全1

class Solution:
    def subsets(self, nums: List[int]) -> List[List[int]]:
         n = len(nums)
        re =[]
        for i in range(2**n,2**(n+1)):
             binnum = bin(i)[3:]        #例:bin(5) : ‘0b101’ (type='str')
             re.append([nums[j] for j in range(n) if binnum[j]=='1'])
        return re

42. 接雨水

给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。

示例
在这里插入图片描述
上面是由数组 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的高度图,在这种情况下,可以接 6 个单位的雨水(蓝色部分表示雨水)

输入: [0,1,0,2,1,0,1,3,2,1,2,1]
输出: 6

思路:每个点能接到的雨点的数目之和为最终能够接到的雨水,每个点能接到的雨水为(左边的最高柱子,右边的最高柱子)之中的最小值减去此点的柱子高度

代码:

class Solution:
    def trap(self, height: List[int]) -> int:
        left_max,right_max = 0 , 0 
        i,j= 0,len(height)-1
        ans = 0
        while(i<j):
            left_max = max(left_max,height[i])
            right_max = max(right_max,height[j])
            
            if(left_max<right_max):
                ans += left_max-height[i]
                i += 1
            else:
                ans += right_max-height[j]
                j -= 1
        return ans
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值