日常系列LeetCode《2·一维数组篇》

Posted 常某某的好奇心

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了日常系列LeetCode《2·一维数组篇》相关的知识,希望对你有一定的参考价值。

数据规模->时间复杂度

<=10^4 😮(n^2)
<=10^7:o(nlogn)
<=10^8:o(n)
10^8<=:o(1)

lc 941 :https://leetcode.cn/problems/valid-mountain-array/
提示:
1 <= arr.length <= 10^4
0 <= arr[i] <= 10^4

class Solution:
    def validMountainArray(self, arr: List[int]) -> bool:
        i=0
        #升
        while i<len(arr)-1 and arr[i]<arr[i+1]:i+=1
        #注:边界-非单调
        if i==0 or i==len(arr)-1:return False
        #降
        while i<len(arr)-1 and arr[i]>arr[i+1]:i+=1
        #
        return i==len(arr)-1

lc 189 :https://leetcode.cn/problems/rotate-array/
提示:
1 <= nums.length <= 10^5
-231 <= nums[i] <= 231 - 1
0 <= k <= 10^5
进阶:
尽可能想出更多的解决方案,至少有 三种 不同的方法可以解决这个问题。
你可以使用空间复杂度为 O(1) 的 原地 算法解决这个问题吗?

#方案一:使用额外数组(i+ k) % n
class Solution:
    def rotate(self, nums: List[int], k: int) -> None:
        """
        Do not return anything, modify nums in-place instead.
        """
        #o(n)
        n=len(nums)
        k=k%n#优化-减少移动
        newarr=[0]*n
        #o(n)
        for i in range(n):newarr[(i+k)%n]=nums[i]
        nums[:]=newarr
        #
        return nums
        
#方案二:环状替换
class Solution:
    def rotate(self, nums: List[int], k: int) -> None:
        """
        Do not return anything, modify nums in-place instead.
        """
        #o(1)
        n=len(nums)
        start=count=0#已处理元素
        k=k%n
        #o(n):环状交换
        while count<n:
            #每个环的初始
            curr=start
            prev=nums[start]
            #交换
            while True:
                nums[(curr+k)%n],prev=prev, nums[(curr+k)%n]
                curr=(curr+k)%n          
                count+=1
                #边界
                if curr == start:break
            start+=1  
        return nums
#方案三:数组旋转
class Solution:
    #对撞反转
    def reverse(self, nums: List[int],start:int, end: int) -> None:
        while start<end:
            nums[start],nums[end]=nums[end],nums[start]
            start+=1
            end-=1
  
    def rotate(self, nums: List[int], k: int) -> None:
        """
        Do not return anything, modify nums in-place instead.
        """
        #
        n=len(nums)
        k=k%n
        #
        self.reverse(nums,0,n-1)
        self.reverse(nums,0,k-1)
        self.reverse(nums,k,n-1)
        return nums

lc 665 :https://leetcode.cn/problems/non-decreasing-array/
提示:
n == nums.length
1 <= n <= 10^4
-10^5 <= nums[i] <= 10^5

class Solution:
    def checkPossibility(self, nums: List[int]) -> bool:
        #o(1)
        count=0
        #(n)
        for i in range(1,len(nums)):
            if nums[i]<nums[i-1]:
                #临界
                count+=1 #注:位置  
                if count>1:return False
                #
                if i>=2 and nums[i]<nums[i-2]:
                    nums[i]=nums[i-1]
                else:nums[i-1]=nums[i]            
        #
        return True

lc 228:提示:
0 <= nums.length <= 20
-2^31 <= nums[i] <= 2^31 - 1
nums 中的所有值都 互不相同
nums 按升序排列

class Solution:
    def summaryRanges(self, nums: List[int]) -> List[str]:
        #o(1)
        res=[]
        #o(n)
        i=0
        while i<len(nums):#区别于for
            low=i
            i+=1
            while i<len(nums) and nums[i]-nums[i-1]==1:i+=1
            high=i-1
            #
            tmp=str(nums[low])
            if low<high:
                tmp+="->"
                tmp+=str(nums[high])
            #
            res.append(tmp)
        #
        return res

lc 163 :https://leetcode.cn/problems/missing-ranges/

class Solution:
    def findMissingRanges(self, nums: List[int], lower: int, upper: int) -> List[str]:
        #o(1)
        res=[]
        #o(n)
        pre=lower-1
        nums.append(upper+1)
        for num in nums:
            if num-pre==2:res.append(str(pre+1))
            if num-pre>2:res.append(str(pre+1)+'->'+str(num-1))
            pre=num
        #
        return res

lc 31【top100】:https://leetcode.cn/problems/next-permutation/
提示:
1 <= nums.length <= 100
0 <= nums[i] <= 100
必须 原地 修改,只允许使用额外常数空间

#找到尽量靠右的【较小数】;找到尽量靠右且比【较小数】大的【较大数】
class Solution:
    def nextPermutation(self, nums: List[int]) -> None:
        """
        Do not return anything, modify nums in-place instead.
        """
        #o(n)
        #【较小数】
        i=len(nums)-2#注:起始点
        while i>=0 and nums[i]>=nums[i+1]:i-=1
        #【较大数】
        if i>=0:
            j=len(nums)-1
            while nums[j]<=nums[i]:j-=1 #注:<=,>=
            #o(1)
            #交换
            nums[i],nums[j]=nums[j],nums[i]
        #o(n)反序
        left,right=i+1,len(nums)-1
        while left<right:
            nums[left],nums[right]=nums[right],nums[left]
            left+=1
            right-=1
        #
        return nums

lc 135:https://leetcode.cn/problems/candy/
提示:
n == ratings.length
1 <= n <= 2 * 10^4
0 <= ratings[i] <= 2 * 10^4

#方案一:暴力解法(超时)
class Solution:
    def candy(self, ratings: List[int]) -> int:
        #o(n)
        n=len(ratings)
        candies=[1]*n
        #o(n^2)
        haschange=True
        while haschange:
            haschange=False
            #
            for i in range(n):
                if i<n-1 and ratings[i]>ratings[i+1] and candies[i]<=candies[i+1]:
                    candies[i]=candies[i+1]+1
                    haschange=True
                if i>0 and ratings[i]>ratings[i-1] and candies[i]<=candies[i-1]:
                    candies[i]=candies[i-1]+1
                    haschange=True
        #
        return sum(candies)
#方案二:'两个数组'(优化-其中一个数组可用变量代替)加上两次遍历
class Solution:
    def candy(self, ratings: List[int]) -> int:
        #o(n)
        n=len(ratings)
        left2right=[1]*n
        right2left=1 #变量形式
        sm=0
        #o(n)
        for i in range(n):
            if i>0 and ratings[i]>ratings[i-1]:
                 left2right[i]= left2right[i-1]+1
        for i in range(n-1,-1,-1):       
            if i<n-1 and ratings[i]>ratings[i+1]:
                right2left +=1
            else:right2left =1
            sm +=max(left2right[i],right2left)   
        #
        return sm

lc 605 :https://leetcode.cn/problems/can-place-flowers/
提示:
1 <= flowerbed.length <= 2 * 104
flowerbed[i] 为 0 或 1
flowerbed 中不存在相邻的两朵花
0 <= n <= flowerbed.length

#1-0-0-0-1-0-0-0-1
class Solution:
    def canPlaceFlowers(self, flowerbed: List[int], n: int) -> bool:
        #
        w=len(flowerbed)
        #
        i=0
        while i<w and n>0:
            if flowerbed[i]==1:
                i+=2
            elif i==w-1 or flowerbed[i+1]==0: #1-0-0,1-0-0-0
                n-=1
                i+=2
            else:i+=3#0-1-0-0
        #
        return n==0

lc 860 :https://leetcode.cn/problems/lemonade-change/
提示:
1 <= bills.length <= 105
bills[i] 不是 5 就是 10 或是 20

class Solution:
    def lemonadeChange(self, bills: List[int]) -> bool:
        #
        five=ten=0
        #
        for bill in bills:
            if bill==5:
                five+=1
            elif bill==10:
                if five==0:return False #注
                five-=1
                ten+=1
            else:
                if five>0 and ten>0:
                    #注
                    five-=1
                    ten-=1
                elif five>=3:
                    #注
                    five-=3
                else: return False
        #
        return True

以上是关于日常系列LeetCode《2·一维数组篇》的主要内容,如果未能解决你的问题,请参考以下文章

日常系列LeetCode《1·数组常用技巧篇》

日常系列LeetCode《9·哈希查找篇》

日常系列LeetCode《8·二分查找篇》

日常系列LeetCode《5·数学篇》

日常系列LeetCode《13·综合应用1篇》

使用环状替换 Leetcode189