Python 练习 数组: LeetCode 26 删除有序数组中的重复项

Python是一种简易的脚本语言,在我平时的各类作业任务中Python脚本程序经常能给予很大的帮助。比如,生成大量测试数据、编写一个支持小规模指令集的编译工具、画图等等工作都可以由Python高效完成。大部分时候只需要程序功能正确即可大幅提升工作效率。不过前段时间,我在完成一些作业和小项目时,发现使用Python编写的程序中算法性能不好有时还是会严重影响完成作业项目的效率,其中有一个项目由于程序运行过慢导致实验分析的效率被严重拖累,因此我想抽时间学习Python算法的高性能实现。我想试试LeetCode练习,从相对简单的题目入手,采用Python实现算法要求


Python 练习 数组: LeetCode 26 删除有序数组中的重复项

给你一个非严格递增排列的数组nums ,请你原地删除重复出现的元素,使每个元素只出现一次 ,返回删除后数组的新长度。元素的相对顺序应该保持一致 。然后返回nums中唯一元素的个数。
考虑nums的唯一元素的数量为k ,你需要做以下事情确保你的题解可以被通过:

  • 更改数组nums,使nums的前k个元素包含唯一元素,并按照它们最初在nums中出现的顺序排列。nums的其余元素与nums的大小不重要。
  • 返回k

判题标准:
系统会用下面的代码来测试你的题解:

int[] nums = [...]; // 输入数组
int[] expectedNums = [...]; // 长度正确的期望答案

int k = removeDuplicates(nums); // 调用

assert k == expectedNums.length;
for (int i = 0; i < k; i++) {
	assert nums[i] == expectedNums[i];
}

如果所有断言都通过,那么您的题解将被通过


题解一

暴力求解
我首先想到的是暴力求解,先跑出结果再优化性能。思路是遍历数组(Python列表),如果有重复元素就移到数组后面,用一个指针控制数组的遍历进度

class Solution(object):
    def removeDuplicates(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        if len(nums) < 2:
            return len(nums)
        valid_length = len(nums)
        pointer = 0
        while (pointer < valid_length-1):
            if nums[pointer] == nums[pointer+1]:
                if pointer < valid_length - 2:
                    nums[:] = nums[:pointer+1] + nums[pointer+2:] + nums[pointer+1:pointer+1]
                    valid_length -= 1
            else:
                pointer += 1
        return valid_length

这里需要注意,如果想在Python函数内修改函数的列表形参,而且返回值不包含该列表,则在重新给列表赋值时要使用列表切片nums[:]的方式,直接对nums赋值无法完成列表内容的修改

nums[:] = nums[:pointer+1] + nums[pointer+2:] + nums[pointer+1:pointer+1]

我试了几个例子在本地能运行通过,但是在LeetCode上测到第三个例子就超时了。需要优化时间复杂度


题解二:

暴力求解 优化
题解二的思路和题解一类似。考虑到题目要求说数组长度与多余元素值不重要,因此可以直接删除重复值

class Solution(object):
    def removeDuplicates(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        if len(nums) < 2:
            return len(nums)
        valid_length = len(nums)
        pointer = 0
        while (pointer < valid_length-1):
            if nums[pointer] == nums[pointer+1]:
                del nums[pointer+1]
                valid_length -= 1
            else:
                pointer += 1
        return valid_length

题解二可以跑通LeetCode的测试案例,空间复杂度较低,但是时间复杂度需要进一步优化
在这里插入图片描述


题解三:

set()去重
最后,我想到Python的内置set()方法可以将列表元素去重。得到的集合是乱序的,不过由于题目给定数组已按升序排序,因此可以直接采用sorted()方法恢复列表元素顺序

class Solution(object):
    def removeDuplicates(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        nums[:] = sorted( list(set(nums)) )
        valid_length = len(nums)
        return valid_length

如果题目给定了其他排序方式,可以用sorted()方法的key参数还原列表元素顺序

newSet = set(listRandom)
noRepeat = list(newSet)
noRepeat.sort(key=listRandom.index)

尽管题解三的空间复杂度较题解二高了一些,但是算法的时间复杂度实现了巨大优化
在这里插入图片描述


小结:

内置方法的优化程度非常高,在写Python脚本时应多采用Python的内置方法(set()sorted()等等)和高度优化的运算库(numpy等),这样程序的时间复杂度将得到巨大提升

  • 22
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值