文章目录
小周让我做的一道题,俺kuakua两下,不到俩小时就做完了,虽然也不快,但也狠狠平复了轮换数组那道题的伤o(╥﹏╥)o
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/e7d0855362ebaa8359b2a72c102469ab.png)
我的做法
- 思路:从第一个位置开始,判断这个位置的值是否是后面数字中的最大值,若不是,就要交换这个位置的值和最大值所在的位置,注意,这个最大值所在的位置是最后一次出现最大值的位置,结束循环,返回;若是,则到下一位再重复操作,直到出现第一种情况或者已经到最后一位,到最后一位就说明这个数组不用换了
class Solution:
def maximumSwap(self, num: int) -> int:
nums = list(str(num))
n = len(nums)
for i in range(n):
nums[i] = int(nums[i])
current =1
for i in range(n):
best = i
current = best+1
while current < n:
if nums[current] >= nums[best]:
best = current
current += 1
if nums[best]!=nums[i]:
nums[i],nums[best] = nums[best],nums[i]
count = 0
for j in range(n):
count += nums[j] * 10**(n-1-j)
return count
return num
- 具体操作:
- 将数字每一位拆开变成数组
- 指定两个指针 best和current,分别表示剩下的数字中最大的数字所处的索引和当前正进行到的位置
- 第一个循环是对数组每个位置都要判断是否交换
- while循环是找到当前位置的元素以后的元素中最大元素的最大索引
- 只要这个索引不是当前判断的位置,都要换
更新时间复杂度更低的方法
- 以上方法虽然也能做出来,但是机智的朋友们已经发现了,这个算法的时间复杂度是 O ( n 2 ) O(n^2) O(n2)
- 小周告诉我,这道题还有 O ( n ) O(n) O(n)的解决办法!
- 思路:逆序遍历一次,完成两个任务,1、找到最大的数;2、找到最大的数左边比它小的数,且位置要最靠左
- 以上思路大致说清楚了,但是有一些奇怪的情况,让我震惊,比如99901,如果只按上面的思路是没办法获得99910的正确答案的,原因就在于少了一个备胎计划
- 按以上思路,最大的数肯定是9,但是由于没有考虑到最大的数左边可能没有比它小的数(即没有考虑最大的数左边全是重复最大数的情况),最后的答案只能是99901
- 而备胎计划则是,及时记录下在某个最大值下可以交换的位置索引,即使出现了这一特殊情况,也有备选
- 我太牛了,“备胎计划”这个名字可取得真好哈哈哈
class Solution:
def maximumSwap(self, num: int) -> int:
nums = list(str(num))
n = len(nums)
for i in range(n):
nums[i] = int(nums[i])
best = n-1
k = False
for i in range(n-1,0,-1):
if nums[i]>nums[best]:
best = i
if nums[best]>nums[i-1]:
k= True
p,q= i-1,best
if k:
nums[q],nums[p] = nums[p],nums[q]
count = ''
for j in range(n):
count += str(nums[j])
return int(count)
else:
return num