leetcode刷题_day1_code1(两数之和)+code1191(K 次串联后最大子数组之和)(QQ音乐面试题)

code:1
给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。

你可以假设每种输入只会对应一个答案。但是,你不能重复利用这个数组中同样的元素。

示例:

给定 nums = [2, 7, 11, 15], target = 9

因为 nums[0] + nums[1] = 2 + 7 = 9
所以返回 [0, 1]

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/two-sum
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

思考:
1 每个只能使用一次,排除暴力破解。
2 应该设置左右浮标,(有序的情况下),left+right <target 的话,left+1,反之right-1.
3 无序list输入时,需要保留序号的变化。
方法:

sorted_id = sorted(range(len(nums)), key=lambda k: nums[k])
    
nums = sorted(nums)

对nums执行sorted
对range(len(nums))= (0,len(nums)-1) 进行排序,规则按照对应的nums[k]做升序。
需要注意: lamba这里类似一个def, 即按照这个方法做升序
序列为 [0,1,2,3,4,5,6,7]的话, 比较nums[0]到nums[7]的大小做一个排序,得到新的序列[3,2,4,0,1,7,6,5], 这里nums[3] <= … <= nums[5].

然后同时形成新的数组,排好序的数组nums。

开始取两端做浮标移动:

    left = 0
    right = len(nums)-1
    while (left < right):

        if (nums[left] + nums[right] < target):
            left += 1

        elif (nums[left] + nums[right] > target):
            right -= 1

        elif (nums[left] + nums[right] == target):
            return [sorted_id[left], sorted_id[right]]

遍历完以后,如果有结果就返回原index数组。

tips:

  1. lambda 方法!按照定义的方法排序
  2. 对于这种只能选取一次的情况,设置左右浮标移动求解(类似有迭代的快排以及归并排序)
  3. 参照讨论改进:不需要再对数组进行一次排序,可以直接对数组的引用排序后的id,left+1 = sorted_id [start+1]。 可以降低时间复杂度!!!

new:
参照后续的讨论

使用字典,hashmap做一个对应查找,有自带的参数进行比对:

class Solution:
    def twoSum(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: List[int]
        """
        hashmap = {}
        for index, num in enumerate(nums):
            another_num = target - num
            if another_num in hashmap:
                return [hashmap[another_num], index]
            hashmap[num] = index
        return None

理论:
1 遍历一遍数组,取index和num
2 每次将index与num对应起来,因为目的找相同的num,所以将num设置为hashmap的键,对应值为数组index(反过来是否也可行? 我认为应该可行, hashmap.key() hashmap.value()理论上均可实现)
2 判断hashmap里面是否存在another_number值等于target - num, 如果存在,返回已经在hashmap里面的index和自己的index即可。

######################################################################################################################
code:1191(qq音乐后台机器学习开发实习面试题)
给你一个整数数组 arr 和一个整数 k。

首先,我们要对该数组进行修改,即把原数组 arr 重复 k 次。

举个例子,如果 arr = [1, 2] 且 k = 3,那么修改后的数组就是 [1, 2, 1, 2, 1, 2]。

然后,请你返回修改后的数组中的最大的子数组之和。

注意,子数组长度可以是 0,在这种情况下它的总和也是 0。

由于 结果可能会很大,所以需要 模(mod) 10^9 + 7 后再返回。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/k-concatenation-maximum-sum
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
##################################################

class Solution:
    def kConcatenationMaxSum( self,arr, k: int):
        mod = 10**9 + 7
        sum1 = 0
        for i in range(len(arr) - 1):
            for j in range(i + 1, len(arr)):
                sum_temp = sum(arr[i:j])
                if sum_temp > sum1:
                    sum1 = sum_temp

        if max(arr) <= 0:
            return 0
        else:
            if k==1:

                return sum1 % mod

            elif k >= 2:
                sum_arr = sum(arr)
                max_left = 0
                for i in range(len(arr)):
                    sum_temp = sum(arr[i:])
                    if sum_temp > max_left:
                        max_left = sum_temp

                max_right = 0
                for i in range(len(arr)):
                    sum_temp = sum(arr[:(len(arr) - i)])
                    if sum_temp > max_right:
                        max_right = sum_temp
                if sum_arr>0:
                    sum2 = max_left + max_right + (k - 2) * sum_arr
                else:
                    sum2 = max_left + max_right
                return max(sum1, sum2) % mod

超时!后续继续排查。
########################################

练习半个多月以后
重新回看此题:
最大值:(边界条件)
1 单个数组本身的最大值(所有情况都有可能出现)
2 k-2个数组和再加头尾(单个数组所有元素和>0)
3 头尾(单个数组元素和<=0)
4 最大值小于0返回0
首先创建三个函数,分别得到max_mid, max_l, max_r
(对于max_mid,需要减少时间复杂度,从左往右遍历,sum加当前值>0时才维持sum。其他情况将sum重置为0)保证增益。然后其中的最大值用max_len保存下来

然后做判断以及mod。

代码:

class Solution:
    def kConcatenationMaxSum(self, arr, k: int) -> int:
        model = 10**9 +7
        max_mid = self.find_max_mid(arr)
        max_l = self.find_max_left(arr)
        max_r = self.find_max_right(arr)
        sum_arr = sum(arr)
        print(max_mid,max_l,max_r,sum_arr)

        if max_mid ==0:
            return 0
        else:
            if k ==1:
                return max_mid%model
            else:
                if sum_arr <=0:
                    return max(max_mid,max_l + max_r) % model
                else:
                    return max(max_mid,max_l+max_r+(k-2)*sum_arr) %model





    def find_max_mid(self,s):


        sum_m = 0
        max_sum = 0
        for i in range(len(s)):
            if s[i]>=0 or sum_m + s[i]>0:
                sum_m +=s[i]
                max_sum = max(max_sum,sum_m)
            else:
                sum_m = 0
        return max_sum

    def find_max_left(self,s):
        max_sum = 0
        sum_l = 0
        for i in range(len(s)):
            sum_l += s[i]
            max_sum = max(sum_l,max_sum)
        return max_sum

    def find_max_right(self,s):
        max_sum = 0
        sum_l = 0
        for i in range(len(s)):
            sum_l += s[len(s)-i-1]
            max_sum = max(sum_l, max_sum)
        return max_sum


su = Solution()
arr = [-16,-14,18,14,-17,-6,9,13,10,-5,-15,-3,15,11,-1,-10,-10,-9]
res = su.kConcatenationMaxSum(arr,12)
print(res)

tips:
O(n)的寻找最大数组内连续元素和。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
给定一个整数数组 nums 和一个目标值 target,要求在数组中找出两个数的和等于目标值,并返回这两个数的索引。 思路1:暴力法 最简单的思路是使用两层循环遍历数组的所有组合,判断两个数的和是否等于目标值。如果等于目标值,则返回这两个数的索引。 此方法的时间复杂度为O(n^2),空间复杂度为O(1)。 思路2:哈希表 为了优化时间复杂度,可以使用哈希表来存储数组中的元素和对应的索引。遍历数组,对于每个元素nums[i],我们可以通过计算target - nums[i]的值,查找哈希表中是否存在这个差值。 如果存在,则说明找到了两个数的和等于目标值,返回它们的索引。如果不存在,将当前元素nums[i]和它的索引存入哈希表中。 此方法的时间复杂度为O(n),空间复杂度为O(n)。 思路3:双指针 如果数组已经排序,可以使用双指针的方法来求解。假设数组从小到大排序,定义左指针left指向数组的第一个元素,右指针right指向数组的最后一个元素。 如果当前两个指针指向的数的和等于目标值,则返回它们的索引。如果和小于目标值,则将左指针右移一位,使得和增大;如果和大于目标值,则将右指针左移一位,使得和减小。 继续移动指针,直到找到两个数的和等于目标值或者左指针超过了右指针。 此方法的时间复杂度为O(nlogn),空间复杂度为O(1)。 以上三种方法都可以解决问,选择合适的方法取决于具体的应用场景和要求。如果数组规模较小并且不需要考虑额外的空间使用,则暴力法是最简单的方法。如果数组较大或者需要优化时间复杂度,则哈希表或双指针方法更合适。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值