数组刷题-力扣

一维数组刷题

1.题目名称:加一

66.加一

# https://leetcode.cn/problems/plus-one/solution/
class Solution:

    def plusOne(self, digits):
        tail = len(digits) - 1
        carry = 0               # 进位

        while tail >= 0:
            if digits[tail] < 9:
                digits[tail] += 1
                return digits
            else:
                digits[tail] = 0
                carry = 1
            tail -= 1
        if carry == 1:
            digits.insert(0, 1)
        return digits

    def plusOne2(self, digits):
        '''
            1.从后往前遍历 digits, 进位 carry 默认为0
            2.如果 该元素值 <9 , 加1 返回
            3.否则(=9),该元素值赋值为 0, carry = 1
            4.依次遍历,最后如果 carry == 1 , 则开头增加一位 1.
        '''
        carry = 0  # 进位 1
        n = len(digits)
        for i in range(n-1, -1, -1):
            if digits[i] < 9:
                digits[i] += 1
                return digits
            else:
                digits[i], carry = 0, 1
        if carry == 1:
            return [1] + digits


my_list = [1, 9, 9]
solution = Solution()
res = solution.plusOne(my_list)
print(res)

res = solution.plusOne2([9, 9, 9])
print(res)

2.轮转数组

189.轮转数组

# https://leetcode.cn/problems/rotate-array/

class Solution:
    def rotate(self, nums: list, k: int):
        """
            Do not return anything, modify nums in-place instead.
            给你一个数组,将数组中的元素向右轮转 k 个位置,其中 k 是非负数。
            eg:
                输入:nums = [-1,-100,3,99], k = 2
                输出:[3,99,-1,-100]
                解释:
                向右轮转 1 步: [99,-1,-100,3]
                向右轮转 2 步: [3,99,-1,-100]
            思路:
                直接调用 list 中的 方法,执行时间有点长,时间复杂度:O(n), 空间复杂度:O(n)
        """
        for i in range(k):
            nums.insert(0, nums.pop())
        pass

    def rotate2(self, nums: list, k: int):
        '''
            思路:使用新数组, 以空间换时间
                1.假如 i 表示 数组的下标, k 表示移动的长度,n是数组的长度,则 移动之后i对应的新的下标为 (i+k)%n
        '''
        n = len(nums)
        new_list = []
        for i, num in enumerate(nums):
            new_index = (i+k) % n
            new_list.insert(new_index, num)

        for i in range(n):
            nums[i] = new_list[i]
        pass

    def rotate3(self, nums: list, k: int):
        ''' 环形替换(重点掌握):
            思路:不定义新数组,在原数组的基础上实现
                1.开始 i = 0, 定义 temp = nums[0], new_index = (i + k) mod n
                2.重复步骤1,遍历 1圈回到 nums[0], 之后 i = 1,继续重复 步骤1
                3.循环 gcd(n, k) 次(证明较麻烦,先记住,或者使用count记录每次遍历的元素个数,count == n时 结束)
            时间复杂度:
            空间复杂度:O(1)
        '''
        def gcd(m, n):
            '''求最大公约数'''
            if m < n:
                m, n = n, m
            while(n != 0):
                r = m%n
                m = n
                n = r
            return m
            pass
        n = len(nums)  # 数组长度
        k = k % n
        cnt = gcd(n, k)
        for i in range(cnt):
            current = i         # 需要新定义一个变量
            temp = nums[current]
            while True:
                new_index = (current + k) % n
                temp, nums[new_index] = nums[new_index], temp
                current = new_index
                if current == i:      # 相当于是do...while循环,先执行一次,再判断
                    break
        return nums

    def rotate4(self, nums, k):
        """环形替换:循环次数使用 cnt 记录 元素个数,cnt == n 时结束循环"""
        n = len(nums)
        current = start = 0
        cnt = 0                 # 记录交换的元素总个数
        while cnt < n:          # 使用 cnt 判断 元素是否交换完
            temp = nums[current]
            while True:
                new_index = (current + k) % n
                temp, nums[new_index] = nums[new_index], temp
                current = new_index
                cnt += 1
                if current == start:
                    current += 1
                    start += 1
                    break
        return nums

    def rotate5(self, nums, k):
        '''数组反转:
            eg:
            nums = [1, 2, 3, 4, 5, 6, 7]; k = 3
            1.全部反转 [7, 6, 5, 4, 3, 2, 1]
            2.reverse(nums, 0, k-1) : [5, 6, 7, 4, 3, 2, 1]
            3.reverse(nums, k, len(nums)): [5, 6, 7, 1, 2, 3, 4]
        '''
        def reverse(nums:list, start:int, end:int):
            while start < end:
                nums[start], nums[end] = nums[end], nums[start]
                start, end = start+1, end-1
            pass
        n = len(nums)
        k %= n
        reverse(nums, 0, n-1)       # 全部反转
        reverse(nums, 0, k-1)
        reverse(nums, k, n-1)
        pass



s = Solution()
nums = [1,2,3,4,5,6,7]
s.rotate5(nums, 3)
print(nums)

# my_list = []
# my_list.insert(0, 10)
# print(my_list)

3.寻找数组的中心下标

寻找数组的中心下标

# https://leetcode.cn/problems/find-pivot-index/
class Solution:
    """
        1.从头开始遍历 nums[]
        2.index=0, 左边为0; index=len(nums)-1 右边为0
        3.判断 index左边的所有元素之和 是否等于 右边的所有元素之和
        4.第一次满足条件的则返回 下标,遍历完没有找到,则返回 -1
        eg:
            输入:nums = [1, 7, 3, 6, 5, 6]
            输出:3
            解释:
            中心下标是 3 。
            左侧数之和 sum = nums[0] + nums[1] + nums[2] = 1 + 7 + 3 = 11 ,
            右侧数之和 sum = nums[4] + nums[5] = 5 + 6 = 11 ,二者相等
        这种2层循环,时间复杂度是 O(n^2) 效率太低
    """
    def pivotIndex(self, nums: list):
        n = len(nums)
        lsum , rsum = 0, 0
        for i in range(0, n):
            for j in range(0, i):
                lsum += nums[j]
            for j in range(i+1, n):
                rsum += nums[j]
            if lsum == rsum:
                return i
            lsum, rsum = 0, 0
        return -1
    '''
        改进:
            1.记数组的总和为 total
            2.求index 元素 左边的和 lsum
            3.则 index 右边的元素和 : total - lsum - nums[index] 
            4.若 total - lsum - nums[index]  = lsum 即返回下标index . 即 total = 2*lsum + nums[index]
    '''
    def pivotIndex2(self, nums:list):
        n = len(nums)
        total = sum(nums)
        lsum = 0
        for i in range(0, n):
            lsum += nums[i-1] if i > 0 else 0
            if total == 2*lsum + nums[i]:
                return i
        return -1
# 时间复杂度 : O(n) , 空间复杂度 O(1)


nums = [1, 7, 3, 6, 5, 6]
s = Solution()
res = s.pivotIndex2(nums)
print(res)

4.最大连续1的个数

最大连续1的个数

# https://leetcode.cn/problems/max-consecutive-ones/

class Solution:
    '''
        给定一个二进制数组 nums , 计算其中最大连续 1 的个数。
        eg:
        输入:nums = [1,1,0,1,1,1]
        输出:3
        解释:开头的两位和最后的三位都是连续 1 ,所以最大连续 1 的个数是 3.
        思路:

    '''
    def findMaxConsecutiveOnes(self, nums: list):
        maxCnt = cnt = 0
        
        for i in nums:
            if i == 1:
                cnt += 1
            else:
                maxCnt = max(maxCnt, cnt)
                cnt = 0
        maxCnt = max(maxCnt, cnt)   # 最后出现连续的 1 且长度最大时
        return maxCnt


nums = [0, 0, 0, 0]
s = Solution()
res = s.findMaxConsecutiveOnes(nums)
print(res)

附录

原文链接

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值