LeetCode—Python版数组简单题(二)

文章目录

    • 1. 求众数(169)
    • 2. 旋转数组(189)
    • 3. 存在重复元素(217)
    • 4. 存在重复元素II(219)
    • 5. 缺失数字(268)
    • 6. 移动零(268)
    • 7. 第三大的数(414)
    • 8. 找到所有数组中消失的数字(448)
    • 9. 最大连续1的个数(485)
    • 10. 数组中的K-diff数对(532)
    • 11. 数组拆分(561)
    • 12. 重塑矩阵(566)
    • 12. 最短无序连续子数组(581)

1. 求众数(169)

给定一个大小为 n 的数组,找到其中的众数。众数是指在数组中出现次数大于 ⌊ n/2 ⌋ 的元素。

你可以假设数组是非空的,并且给定的数组总是存在众数。

示例 1:

输入: [3,2,3]
输出: 3
示例 2:

输入: [2,2,1,1,1,2,2]
输出: 2

解法1
注意最多的元素出现的次数大于数组长度的一半,所以使用如下的代码,在最极端的情况下,最后的count都会大于0,cand就是所要找的元素

class Solution(object):
    def majorityElement(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        cand = nums[0]
        count = 1
        for i in nums[1:]:
            if count == 0:
                cand, count = i, 1
            else:
                if i == cand:
                    count = count + 1
                else:
                    count = count - 1
        return cand

解法2:用sort方法

class Solution:
    def majorityElement(self, nums: List[int]) -> int:
        return sorted(nums)[len(nums)//2]

2. 旋转数组(189)

给定一个数组,将数组中的元素向右移动 k 个位置,其中 k 是非负数。

示例 1:

输入: [1,2,3,4,5,6,7] 和 k = 3
输出: [5,6,7,1,2,3,4]
解释:
向右旋转 1 步: [7,1,2,3,4,5,6]
向右旋转 2 步: [6,7,1,2,3,4,5]
向右旋转 3 步: [5,6,7,1,2,3,4]
示例 2:

输入: [-1,-100,3,99] 和 k = 2
输出: [3,99,-1,-100]
解释:
向右旋转 1 步: [99,-1,-100,3]
向右旋转 2 步: [3,99,-1,-100]

解法

class Solution:
    def rotate(self, nums: List[int], k: int) -> None:
        """
        Do not return anything, modify nums in-place instead.
        """
        n = len(nums)
        nums[:] = nums[n - k:] + nums[:n - k]

3. 存在重复元素(217)

给定一个整数数组,判断是否存在重复元素。

如果任何值在数组中出现至少两次,函数返回 true。如果数组中每个元素都不相同,则返回 false。

示例 1:

输入: [1,2,3,1]
输出: true
示例 2:

输入: [1,2,3,4]
输出: false
示例 3:

输入: [1,1,1,3,3,4,3,2,4,2]
输出: true

解法:利用set不能保存重复元素的特性,判断前后两个数组长度是否相同即可。

class Solution:
    def containsDuplicate(self, nums: List[int]) -> bool:
        list_len = len(nums)
        set_len = len(set(nums))
        if list_len == set_len:
            return False
        else:
            return True

4. 存在重复元素II(219)

给定一个整数数组和一个整数 k,判断数组中是否存在两个不同的索引 i 和 j,使得 nums [i] = nums [j],并且 i 和 j 的差的绝对值最大为 k。

示例 1:

输入: nums = [1,2,3,1], k = 3
输出: true
示例 2:

输入: nums = [1,0,1,1], k = 1
输出: true
示例 3:

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

解法:用dict保存数组元素出现的位置,两种情况下更新

class Solution:
    def containsNearbyDuplicate(self, nums: List[int], k: int) -> bool:
        dic = dict()
        for index,value in enumerate(nums):
            if value in dic and index - dic[value] <= k:
                return True
            dic[value] = index
        return False

5. 缺失数字(268)

给定一个包含 0, 1, 2, …, n 中 n 个数的序列,找出 0 … n 中没有出现在序列中的那个数。

示例 1:

输入: [3,0,1]
输出: 2
示例 2:

输入: [9,6,4,2,3,5,7,0,1]
输出: 8
解法

class Solution:
    def missingNumber(self, nums: List[int]) -> int:
        n = len(nums)
        return n * (n+1) //2 - sum(nums)

6. 移动零(268)

给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。

示例:

输入: [0,1,0,3,12]
输出: [1,3,12,0,0]
说明:

必须在原数组上操作,不能拷贝额外的数组。
尽量减少操作次数。

解法
遍历数组,用一个变量记录当前不为0的个数,同时也是新不为零元素插入的位置:

class Solution:
    def moveZeroes(self, nums: List[int]) -> None:
        """
        Do not return anything, modify nums in-place instead.
        """
        index = 0
        for num in nums:
            if num != 0:
                nums[index] = num
                index += 1
        for i in range(index, len(nums)):
            nums[i] = 0

7. 第三大的数(414)

给定一个非空数组,返回此数组中第三大的数。如果不存在,则返回数组中最大的数。要求算法时间复杂度必须是O(n)。

示例 1:

输入: [3, 2, 1]

输出: 1

解释: 第三大的数是 1.
示例 2:

输入: [1, 2]

输出: 2

解释: 第三大的数不存在, 所以返回最大的数 2 .
示例 3:

输入: [2, 2, 3, 1]

输出: 1

解释: 注意,要求返回第三大的数,是指第三大且唯一出现的数。
存在两个值为2的数,它们都排第二。

解法
这里用三个值记录前三大的数字,要注意是三个不同的数字,重复的数字不记录排序,所以要注意判断条件:

class Solution:
    def thirdMax(self, nums: List[int]) -> int:
        max1 = max2 = max3 = float('-inf')
        for num in nums:
            if num > max1:
                max2, max3 = max1, max2
                max1 = num
            elif num < max1 and num > max2:
                max2, max3 = num, max2
            elif num < max2 and num > max3:
                max3 = num
        return max1 if max3 == float('-inf') else max3

8. 找到所有数组中消失的数字(448)

给定一个范围在 1 ≤ a[i] ≤ n ( n = 数组大小 ) 的 整型数组,数组中的元素一些出现了两次,另一些只出现一次。

找到所有在 [1, n] 范围之间没有出现在数组中的数字。

您能在不使用额外空间且时间复杂度为O(n)的情况下完成这个任务吗? 你可以假定返回的数组不算在额外空间内。

示例:

输入:
[4,3,2,7,8,2,3,1]

输出:
[5,6]
解法
这个题就比较神奇了,注意到数组元素个数跟元素范围是一样的,所以我们可以把出现过的元素对应下标位置的数字变成负数,最后把所有正数对应的下标拿出来,就是缺失的数字。

class Solution:
    def findDisappearedNumbers(self, nums: List[int]) -> List[int]:
        for i in range(len(nums)):
            index = abs(nums[i])-1
            nums[index] = -abs(nums[index])
        return [i+1 for i in range(len(nums)) if nums[i] > 0]

9. 最大连续1的个数(485)

给定一个二进制数组, 计算其中最大连续1的个数。

示例 1:

输入: [1,1,0,1,1,1]
输出: 3
解释: 开头的两位和最后的三位都是连续1,所以最大连续1的个数是 3.
注意:

输入的数组只包含 0 和1。
输入数组的长度是正整数,且不超过 10,000。

解法

class Solution:
    def findMaxConsecutiveOnes(self, nums: List[int]) -> int:
        cnt = 0
        res = 0
        for i in range(len(nums)):
            if nums[i] == 1:
                cnt += 1
                res = max(res, cnt)
            else:
                cnt = 0
        return res

10. 数组中的K-diff数对(532)

给定一个整数数组和一个整数 k, 你需要在数组里找到不同的 k-diff 数对。这里将 k-diff 数对定义为一个整数对 (i, j), 其中 i 和 j 都是数组中的数字,且两数之差的绝对值是 k.

示例 1:

输入: [3, 1, 4, 1, 5], k = 2
输出: 2
解释: 数组中有两个 2-diff 数对, (1, 3) 和 (3, 5)。
尽管数组中有两个1,但我们只应返回不同的数对的数量。
示例 2:

输入:[1, 2, 3, 4, 5], k = 1
输出: 4
解释: 数组中有四个 1-diff 数对, (1, 2), (2, 3), (3, 4) 和 (4, 5)。
示例 3:

输入: [1, 3, 1, 5, 4], k = 0
输出: 1
解释: 数组中只有一个 0-diff 数对,(1, 1)。
注意:

数对 (i, j) 和数对 (j, i) 被算作同一数对。
数组的长度不超过10,000。
所有输入的整数的范围在 [-1e7, 1e7]。

解法1
使用collections集合模块

class Solution:
    def findPairs(self, nums: List[int], k: int) -> int:
        if k>0:
            return len(set(nums) & set(n+k for n in nums))
        elif k==0:
            return sum(v>1 for v in collections.Counter(nums).values())
        else:
            return 0

解法2
不使用collections集合模块

class Solution:
    def findPairs(self, nums: List[int], k: int) -> int:
        count,n=0,len(nums)
        s=set(nums)
        if k<0 or len(nums)<2:
            return 0
        if k==0:
            for ele in s:
                if nums.count(ele)>1:
                    count+=1
            return count
                    
        for ele in s:
            #保证数据的不重复,同时不选自己
            if ele+k in s:
                count+=1
        return count

参考:https://blog.csdn.net/qq_41929011/article/details/88532227

11. 数组拆分(561)

给定长度为 2n 的数组, 你的任务是将这些数分成 n 对, 例如 (a1, b1), (a2, b2), …, (an, bn) ,使得从1 到 n 的 min(ai, bi) 总和最大。

示例 1:

输入: [1,4,3,2]

输出: 4
解释: n 等于 2, 最大总和为 4 = min(1, 2) + min(3, 4).
提示:

n 是正整数,范围在 [1, 10000].
数组中的元素范围在 [-10000, 10000].

解法
就是返回排序后第1,3,5,。。2n-1小的数

class Solution:
    def arrayPairSum(self, nums: List[int]) -> int:
        return sum(sorted(nums)[::2])

12. 重塑矩阵(566)

在MATLAB中,有一个非常有用的函数 reshape,它可以将一个矩阵重塑为另一个大小不同的新矩阵,但保留其原始数据。

给出一个由二维数组表示的矩阵,以及两个正整数r和c,分别表示想要的重构的矩阵的行数和列数。

重构后的矩阵需要将原始矩阵的所有元素以相同的行遍历顺序填充。

如果具有给定参数的reshape操作是可行且合理的,则输出新的重塑矩阵;否则,输出原始矩阵。

示例 1:

输入:
nums =
[[1,2],
[3,4]]
r = 1, c = 4
输出:
[[1,2,3,4]]
解释:
行遍历nums的结果是 [1,2,3,4]。新的矩阵是 1 * 4 矩阵, 用之前的元素值一行一行填充新矩阵。
示例 2:

输入:
nums =
[[1,2],
[3,4]]
r = 2, c = 4
输出:
[[1,2],
[3,4]]
解释:
没有办法将 2 * 2 矩阵转化为 2 * 4 矩阵。 所以输出原矩阵。
注意:

给定矩阵的宽和高范围在 [1, 100]。
给定的 r 和 c 都是正数。

解法
将数组转换为1行,然后根据要转换的行列数进行转换

class Solution:
    def matrixReshape(self, nums: List[List[int]], r: int, c: int) -> List[List[int]]:
        if len(nums) * len(nums[0]) != r * c:
            return nums
        else:
            onerow = [nums[i][j] for i in range(len(nums)) for j in range(len(nums[0]))]
            return [onerow[t * c : (t+1) * c] for t in range(r)]

12. 最短无序连续子数组(581)

给定一个整数数组,你需要寻找一个连续的子数组,如果对这个子数组进行升序排序,那么整个数组都会变为升序排序。

你找到的子数组应是最短的,请输出它的长度。

示例 1:

输入: [2, 6, 4, 8, 10, 9, 15]
输出: 5
解释: 你只需要对 [6, 4, 8, 10, 9] 进行升序排序,那么整个表都会变为升序排序。
说明 :

输入的数组长度范围在 [1, 10,000]。
输入的数组可能包含重复元素 ,所以升序的意思是<=。

解法
all_same[::-1]返回的不是从正向数的索引,返回的是以最后一个元素为0索引,倒数第二个元素为1索引的反向数列的索引值,如例子中所示,从前数有一个不需排序,从后数,有一个不需排序。

class Solution:
    def findUnsortedSubarray(self, nums: List[int]) -> int:
        all_same = [a == b for (a, b) in zip(nums, sorted(nums))]
        return 0 if all(all_same) else len(nums) - all_same.index(False) - all_same[::-1].index(False)

你可能感兴趣的:(剑指offerLeetcode)