给定一个未排序的整数数组,找出其中未出现的最小正整数。
Python 官网:https://www.python.org/
Free:大咖免费“圣经”教程《 python 完全自学教程》,不仅仅是基础那么简单……
地址:https://lqpybook.readthedocs.io/
自学并不是什么神秘的东西,一个人一辈子自学的时间总是比在学校学习的时间长,没有老师的时候总是比有老师的时候多。
—— 华罗庚
本文质量分:
CSDN质量分查询入口:http://www.csdn.net/qc
给你一个未排序的整数数组nums,请你找出其中没有出现的最小的正整数。请你实现时间复杂度为 O(n) 并且只使用常1数级别额外空间的解决方案。
样例 1:
输入:
nums = [1, 2, 0]
输出:
3
样例2:
输入:
nums = [3, 4, -1, 1]
输出:
2
样例 3:
输入:
nums = [7, 8, 9, 11, 12]
输出:
1
提示:
从大佬的博文中剪来的题解代码,其中while一段以我目前水准读不明白。
class Solution:def firstMissingPositive(self, nums: List[int]) -> int:n = len(nums)for i in range(n):while 1 <= nums[i] <= n and nums[nums[i] - 1] != nums[i]:input(nums) nums[nums[i] - 1], nums[i] = nums[i], nums[nums[i] - 1]for i in range(n):if nums[i] != i + 1:return i + 1return n + 1
以上这段代码的逻辑:
“好在题目没说参数空间不可以修改,不说就是默认,我们就用参数的空间。我们把在范围内的正数放在对应的位置,处理完一遍数组后,第二次遍历数组,对应位置数字不对的就是缺失的正数。”
def firstMissingPositive(self, nums: List[int]) -> int:pass
这函数形参的定义语法,我的两个Python环境都“死活”不认。😣
函数定义原语句,修改成了我Python喜欢的样子,才成功跑起来了。
def firstMissingPositive(self, nums) -> int:pass
以我目前的Python学识,读不明白那while那一段代码,加了两个print()“显形”,才晓得是起“排序”作用。😝
代码
def firstMissingPositive(self, nums) -> int:n = len(nums)for i in range(n):print(nums) # 添加的调试用语句。while 1 <= nums[i] <= n and nums[nums[i] - 1] != nums[i]:nums[nums[i] - 1], nums[i] = nums[i], nums[nums[i] - 1]print(nums) # 添加的调试用语句。
效果截屏
经过仔细拆解,终于读懂大佬算法代码。
原来大佬说的“……把在范围内的正数放在对应的位置,处理完一遍数组后……”,意思是遍历一遍数组,把<=数组长度len(nums)的正整数放在其对应的正确位置(设定数组第一个位置放1),依次处理每个正整数。nums[nums[i] - 1] != nums[i]的意义是遍历到的数组元素值减1不等于它的下标,即nums[i] - 1 != i,因此可以换为后面一句的写法。
class Solution:#def firstMissingPositive(self, nums: List[int]) -> int:def firstMissingPositive(self, nums) -> int:n = len(nums)for i in range(n):print('\n遍历位置:i =', i)#while 1 <= nums[i] <= n and nums[nums[i] - 1] != nums[i]:while 0 < nums[i] <= n and nums[i] - 1 != i:print(nums)nums[nums[i]-1], nums[i] = nums[i], nums[nums[i]-1] print(f"\n{nums}\n") for i in range(n):if nums[i] != i + 1:return i + 1return n + 1
如:
样例3给出的整数都大于其长度5,不作处理。第一个位置不是1,1即是未出现过的最小正整数。
题目要求从给定数组中找出未出现过的最小正整数,正整数即是不含“0”的自然数,那么从1开始升序查找判定就好。首先对数组升序排序(题目描述中没说明不可以用轮子,我认为调用或者自码排序代码,都是可行的),然后截取正数部分比对判定,找出未出现过最小正整数。
借用list.sort()排正序,enumerate()枚举同时遍历下标和数组元素本身。
代码
def findmin(nums):''' 找出数列中未出现的最小正数 '''nums = [i for i in nums if i > 0] # 列表解析出给定数组的自然数部分。nums.sort() # 排正序。list.sort()默认正序。for k,i in enumerate(nums):if nums[k+1] - 1 != i:return i + 1return i + 1
用Python成员判定指令in来解题,无须对nums输入数组排序。用msx(nums)取出最大整数,遍历1~最大整数的整数列表,依次判定在不在数组num中,当i in nums的值为False时,即找到缺失的最小整数。这个算法只需遍历“最小缺失值”次 (从1~n依次遍历),我觉得是“易读易懂”的轻便算法。
代码
def findmin(nums):''' 找出数列中未出现的最小正数 '''for i in range(1, max(nums)):if i not in nums: # not False即是True。return i
(源码较长,点此跳过源码)
我的HOT博:
精品文章:
来源:老齐教室
◆ Python 入门指南【Python 3.6.3】
好文力荐:
全栈领域优质创作者——寒佬(还是国内某高校学生)博文“非技术文—关于英语和如何正确的提问”,“英语”和“会提问”是学习的两大利器。
【8大编程语言的适用领域】先别着急选语言学编程,先看它们能干嘛
靠谱程序员的好习惯
CSDN实用技巧博文: