力扣刷题|数组(初级算法)

删除排序数组中的重复项

题目:给你一个 非严格递增排列 的数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。然后返回 nums 中唯一元素的个数。

考虑 nums 的唯一元素的数量为 k ,你需要做以下事情确保你的题解可以被通过:

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

示例 :

输入:nums = [0,0,1,1,1,2,2,3,3,4]
输出:5, nums = [0,1,2,3,4]

算法思路:

首先该题的输入是一个为整数的数组。删除重复出现的元素可以用双指针的思路,右指针每一次向右移动一步,然后来判断该数和左指针的值是不是一样,如果一样右指针就向右再移动然后再判断;如果不一样,那么左指针就先向右移一步,然后把右指针的值赋值给左指针。循环的条件是直到右指针的长度小于数组的长度,然后输出左指针的长度。在最后如果想要输出[0,1,2,3,4],就需要使用切片的操作 list[start:end:step]。

python代码:

class Solution:
    def removeDuplicates(self, nums):
        right = 0
        left = 0
        while(right<len(nums)):
            if(nums[right] == nums[left]):
                right +=1
            else:
                left +=1
                nums[left] = nums[right]
        return left+1, nums[:left+1]

nums = [0,0,1,1,1,2,2,3,3,4]
solution = Solution()
removeDuplicates = solution.removeDuplicates(nums)
print(removeDuplicates)

买卖股票的最佳时机 II

题目:给你一个整数数组 prices ,其中 prices[i] 表示某支股票第 i 天的价格。在每一天,你可以决定是否购买和/或出售股票。你在任何时候 最多 只能持有 一股 股票。你也可以先购买,然后在 同一天 出售。返回 你能获得的 最大 利润 。

示例 :

输入:prices = [1,2,3,4,5]

输出:4

解释:在第 1 天(股票价格 = 1)的时候买入,在第 5 天 (股票价格 = 5)的时候卖出, 这笔交易所能获得利润 = 5 - 1 = 4 。
     总利润为 4 。

算法思路:

之前没有了解过动态规划或者贪心算法,所以看到这个题就不会解。然后看了代码随想录里的详解,视频里用了贪心算法,所以这里我也用贪心算法。

贪心算法是先找到局部最优解,然后来找全局最优解。这个题中很巧妙的点是可以把所有的利润分解为每天的利润,然后最优的利润就是所有正的利润想加。所以这个题中局部最优点就是正的利润,全局最优就是所有正利润想加。

这个题的输入就是一组数组,需要输出的是最后的最大利润。很巧妙的是 result += max((nums[i] - nums[i-1]),0) 这一行,用当天的利润和0来取最大的值,这里真的很巧妙!!!

python代码:

#自己写的,注意 python里不支持 ++ 操作符
class Solution:
    def Price(self, nums):
        result = 0
        i = 1
        while(i<len(nums)):
            result += max((nums[i] - nums[i-1]),0)
            i +=1
        return result

nums = [7,1,5,10,3,6,4]
solution = Solution()
price = solution.Price(nums)
print(price)

#代码随想录里的
class Solution:
    def Price(self, nums):
        result = 0
        for i in range(1,len(nums)):
            result += max((nums[i] - nums[i-1]),0)
        return result

nums = [7,1,5,10,3,6,4]
solution = Solution()
price = solution.Price(nums)
print(price)

第二种写法更加简洁明了,使用了Python内置的range函数,省去了变量的定义和自增操作,代码更加简洁。

旋转数组

题目:给定一个整数数组 nums,将数组中的元素向右轮转 k 个位置,其中 k 是非负数。

示例 1:

输入: nums = [1,2,3,4,5,6,7], k = 3
输出: [5,6,7,1,2,3,4]
解释:
向右轮转 1 步: [7,1,2,3,4,5,6]
向右轮转 2 步: [6,7,1,2,3,4,5]
向右轮转 3 步: [5,6,7,1,2,3,4]

算法思路:

是否可以用双指针,一首一尾,但是数组只能靠覆盖来增删查,所以要一个一个的覆盖吗?这一步如何用代码来写呢?(用一个临时数组去储存)

但是更简单的是,直接用切片的方法来实现。从 len(nums) - k 这个点去切。值得注意的是,如果K大于len(nums),那么 nums[:] = nums[n - k : ] + nums[ : n-k] 将只会得到原来的数组,所以,需要加上这行 k = k % n代码,当k < n时,k % n==k;  当k > n, 就会得到正确的值,因为变换的话是n个变换为一个周期这样来变。

python代码:

class Solution:
    def rotate(self, nums, k):
        n = len(nums)
        k = k % n
        nums[:] = nums[n - k:] + nums[:n - k]
        return nums[:]

nums = [1,2,3]
k = 5
solution = Solution()
rotate = solution.rotate(nums,k)
print(rotate)  

存在重复元素

题目:给你一个整数数组 nums 。如果任一值在数组中出现 至少两次 ,返回 true ;如果数组中每个元素互不相同,返回 false 。

示例 :

输入:nums = [1,2,3,1]
输出:true

算法思路:

首先是暴力遍历法,但是运行时间超过了。然后看了其他解法,使用了set()集合。set()集合的特点是无序和不重复。根据不重复这个特点,就可以来解决这个题。它的思路是判断len(set(nums)) 和len(nums)是否相等,如果相等就说明没有重复的,不相等就说明有重复。

python代码:

#暴力法,超时了
class Solution:
    def containsDuplicate(self,nums):
        for i in range(len(nums)):
            for j in range(i+1,len(nums)):
                if nums[i] ==nums[j]:
                    return True
        return False

nums = [1,2,3,1]
solution = Solution()
containsDuplicate = solution.containsDuplicate(nums)
print(containsDuplicate)

#使用set()集合
class Solution:
    def containsDuplicate(self, nums):
        if len(set(nums)) != len(nums):
            return True
        return False
nums = [1,2,3,4]
solution = Solution()
containsDuplicate = solution.containsDuplicate(nums)
print(containsDuplicate)

注意:使用 set(nums) 时,实际上 Python 会自动将列表 nums 中的元素提取出来并创建一个包含这些元素的集合。在这个过程中,它并不是直接把列表作为一个整体添加到集合中,而是对列表中的每个元素进行处理,将不重复的元素放入新创建的集合中。但是使用 set.add()时,就不能直接 set.add(nums),需要一个一个的放。

只出现一次的数字

题目:给你一个 非空 整数数组 nums ,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。

注:你必须设计并实现线性时间复杂度的算法来解决此问题,且该算法只使用常量额外空间。

示例 :

输入:nums = [4,1,2,1,2]
输出:4

算法思路:

当我不知道不能直接 set.add(nums)时,我不知道可以使用set集合。但是了解后,就可以根据set集合的“冲突”来解决这个问题,首先要创建一个集合(去存这个只出现一次的数),然后遍历这个数组,如果数组里的元素在这个集合里,就从集合里面删除,如果不在就添加。但是这样,不用创集合,创数组是不是也可以呢?-(也可以)(但是以下的代码的时间复杂度是n*n.)

python代码:

#set集合,添加元素用的是 add
class Solution:
    def singleNumber(self,nums):
        result_set = set()
        for num in nums:
            if num in result_set:
               result_set.remove(num)
            else:
                result_set.add(num)
        return list(result_set)[0]
    
nums = [1,2,2,3,3]
solution = Solution()
singleNumber = solution.singleNumber(nums)
print(singleNumber)                

#列表添加元素是用 append()
class Solution:
    def singleNumber(self,nums):
        result = []
        for num in nums:
            if num in result:
               result.remove(num)
            else:
                result.append(num)
        return result[0]
    
nums = [1,2,2,3,3]
solution = Solution()
singleNumber = solution.singleNumber(nums)
print(singleNumber)

#抓住 只有一个数出现一次,其它都是两次这个题目。绝了啊
class Solution:
    def singleNumber(self, nums):
        return sum(set(nums)) * 2 - sum(nums)
    
nums = [1,2,2,3,3]
solution = Solution()
singleNumber = solution.singleNumber(nums)
print(singleNumber)

还有一个很妙的方法是使用位运算:

a^a=0;自己和自己异或等于0

a^0=a;任何数字和0异或还等于他自己

a^b^c=a^c^b;异或运算具有交换律

而题目中有说 只有一个数出现了一次,其他数字都出现了2次。所以不需要创集合或者数组来存储,只需要一个整数,然后一个一个的和数组里的数进行异或运算,最后就会得到那只出现一次的数,代码是:

class Solution(object):
    def singleNumber(self, nums):
        a=0
        for num in nums:
            a^=num
        return a
    
nums = [1,2,2,3,3]
solution = Solution()
singleNumber = solution.singleNumber(nums)
print(singleNumber)

两个数组的交集 II

题目:给你两个整数数组 nums1 和 nums2 ,请你以数组形式返回两数组的交集。返回结果中每个元素出现的次数,应与元素在两个数组中都出现的次数一致(如果出现次数不一致,则考虑取较小值)。可以不考虑输出结果的顺序。

示例 1:

输入:nums1 = [1,2,2,1], nums2 = [2,2]
输出:[2,2]
示例 2:

输入:nums1 = [4,9,5], nums2 = [9,4,9,8,4]
输出:[4,9]

算法思路:

先对两个数组进行排序(sorted()默认是从小到大,然后使用两个指针,分别指向两个数组开始的位置。如果两个指针指向的值相同,说明这个值是他们的交集,就把这个值加入到集合list中,然后两个指针在分别往后移一步。如果两个指针指向的值不同,那么指向的值相对小的往后移一步,相对大的先不动,然后再比较

另外一种方法是使用map来解决:

map()函数通常有两个参数(函数对象,可迭代对象)

python代码:

class Solution(object):
    def intersect(self,nums1,nums2):
        n1 = sorted(nums1)
        n2 = sorted(nums2)
        l1 = len(nums1)
        l2 = len(nums2)
        right = 0
        left = 0
        result = []
        while((right < l1) and (left < l2)):
            if(n1[right] == n2[left]):
                result.append(n1[right])
                right +=1
                left +=1
            elif(n1[right] > n2[left]):
                left +=1
            elif(n1[right] < n2[left]):
                right +=1
        return result

加一

题目:

给定一个由 整数 组成的 非空 数组所表示的非负整数,在该数的基础上加一。

最高位数字存放在数组的首位, 数组中每个元素只存储单个数字。

你可以假设除了整数 0 之外,这个整数不会以零开头。

示例 1:

输入:digits = [1,2,3]
输出:[1,2,4]
解释:输入数组表示数字 123。

算法思路:

题目应该就是想问999+1咋办?把数组转化成一个数,然后该数加一,然后再把这个数变成数组?这样也可以,但是看了答案,使用了以下代码, for i in range(len(digits)-1, -1, -1)这行代码是从后向前的遍历,其中在for循环里面的return很关键,可以仔细品品。for循环就是从后向前的把9变成0,如果都是9则不会在for循环里面的return,如果没有9则直接加1后跳出循环返回结束了。

python代码:

class Solution(object):
    def plusOne(self, digits):
        for i in range(len(digits)-1, -1, -1): #倒序
            if digits[i] == 9:
                digits[i] = 0
            else:
                digits[i] += 1
                return digits
        #全是9的情况,然后需要加1
        digits.insert(0,1)
        return digits

digits = [9,9]
solution = Solution()
plusOne = solution.plusOne(digits)
print(plusOne)

移动零

给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。请注意 ,必须在不复制数组的情况下原地对数组进行操作。

示例 1:

输入: nums = [0,1,0,3,12]

输出: [1,3,12,0,0]

算法思路:

自己的思路是,遇到不是0的就加在另外的一个数组里,然后遇到是0的就添加在最前面(倒叙添加没有成功),然后通过反转列表输出,在自己本地跑是成功的,但是没有提交通过。看了参考答案,妙啊,没有添加新的数组,在原来的数组中操作,只对不为0的进行遍历,然后使用nums[i],nums[j]=nums[j],nums[i] 这行代码进行交换,完全想不出来,妙啊!!!多看几遍吧!!!

python代码:

#用了新的列表,然后在本地跑的答案是正确的,但是没有通过
class Solution(object):
    def moveZeroes(self, nums):
        num1 =[]
        left = len(num1) 
        for i in range(len(nums)-1,-1,-1):
            if nums[i] != 0:
                num1.append(nums[i])
            else:
                num1.insert(0,0)
        return num1[::-1]
    
nums = [0,1,0,3,12,0]
solution = Solution()
moveZeroes = solution.moveZeroes(nums)
print(moveZeroes)

#例题答案
class Solution(object):
    def moveZeroes(self, nums):
        j=0
        for i in range(len(nums)):
            if nums[i] !=0 :
                nums[i],nums[j]=nums[j],nums[i]
                j+=1
        return nums
nums = [0,1,0,3,12,0]
solution = Solution()
moveZeroes = solution.moveZeroes(nums)
print(moveZeroes)

两数之和

题目:

给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target  的那 两个 整数,并返回它们的数组下标。你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。你可以按任意顺序返回答案。

示例 1:

输入:nums = [2,7,11,15], target = 9
输出:[0,1]
解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1] 。

算法思路:

双指针?也可以,但是时间复杂度很高,给的参考答案就很妙!!!使用了字典!!!多看几遍这种方法吧,大大的降低了时间复杂。

python代码

class Solution(object):
    def twoSum(self,nums,target):
        for right in range(len(nums)):
            for left in range(right+1,len(nums)):
                if nums[right] + nums[left] == target:
                    return right,left

nums = [3,2,4] 
target = 6
solution = Solution()
twoSum = solution.twoSum(nums,target)
print(twoSum)

class Solution(object):
    def twoSum(self, nums, target):
        h = {}
        for i, num in enumerate(nums):
            n = target - num
            if n not in h:
                h[num] = i
            else:
                return [h[n], i]
nums = [3,2,4] 
target = 6
solution = Solution()
twoSum = solution.twoSum(nums,target)
print(twoSum)

有效的数独

题目:请你判断一个 9 x 9 的数独是否有效。只需要 根据以下规则 ,验证已经填入的数字是否有效即可。

  • 数字 1-9 在每一行只能出现一次。
  • 数字 1-9 在每一列只能出现一次。
  • 数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。(请参考示例图)

  • 6
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值