[python]LeetCode_167. Two Sum II - Input Array Is Sorted

[python]LeetCode_167. Two Sum II - Input Array Is Sorted



牽涉概念及時間紀錄

20220408 17:08-17:20 for 第一次
使用雙指針方式能降低時間複雜度
當需要雙迴圈時可以往此方向考慮


一、題目內容

簡而言之:

就是給定一個list 裡面有很多數字,以及一個目標數字。
請找出其中哪兩數字相加之後會與目標數字吻合。
必有唯一解,且同一位置不重複使用(ex 不會有[2,2]這種答案)

以下題目原文:

Given a 1-indexed array of integers numbers that is already sorted in non-decreasing order,
 find two numbers such that they add up to a specific target number. 
 Let these two numbers be numbers[index1] and numbers[index2] 
 where 1 <= index1 < index2 <= numbers.length.

Return the indices of the two numbers, index1 and index2, 
added by one as an integer array [index1, index2] of length 2.

The tests are generated such that there is exactly one solution. 
You may not use the same element twice.

Your solution must use only constant extra space.

Example 1:

Input: numbers = [2,7,11,15], target = 9
Output: [1,2]
Explanation: The sum of 2 and 7 is 9. Therefore, index1 = 1, index2 = 2. We return [1, 2].

Example 2:

Input: numbers = [2,3,4], target = 6
Output: [1,3]
Explanation: The sum of 2 and 4 is 6. Therefore index1 = 1, index2 = 3. We return [1, 3].

Example 3:

Input: numbers = [-1,0], target = -1
Output: [1,2]
Explanation: The sum of -1 and 0 is -1. Therefore index1 = 1, index2 = 2. We return [1, 2].

Constraints:

2 <= numbers.length <= 3 * 104
-1000 <= numbers[i] <= 1000
numbers is sorted in non-decreasing order.
-1000 <= target <= 1000
The tests are generated such that there is exactly one solution.

二、想法思路

1.直觀想法:

一開始不假思索就是遍歷查找一遍就應該有答案了?
fish yes (於是,抱歉我突然想耍白痴一下XD)
就直接使用迴圈從頭開始找,並注意一些可能造成無效計算的情況。
諸如相同的重複字元(ex 0,0,0,1,2,3 這樣的)
時間複雜度為O(N^2)
空間複雜度為O(1).

def twoSum(self, numbers: List[int], target: int) -> List[int]:
        numbers_l = len(numbers)
        for num in range(numbers_l):
            if num > 0:
            	# ignore same number that has already calculate.
                if numbers[num] == numbers[num-1]:
                    continue
            for num_in in range(num+1, numbers_l):
                if target == numbers[num] + numbers[num_in]:
                    return [num+1, num_in+1]
                elif target < numbers[num] + numbers[num_in]:
                    break

2.想想發現不太對,優化一下:

這邊由於題目已經明確說明是non-decreasing order了,
用指標的想法去做,可以將時間降低不少.
一開始將指標指在最小與最大,逐步往中間靠攏即可找到符合的答案。
時間複雜度為O(N)
空間複雜度為O(1).

def twoSum(self, numbers: List[int], target: int) -> List[int]:
        numbers_l = len(numbers)
        # little is the less pointer, and the big is the large pointer
        little = 0
        big = numbers_l-1
        while numbers[little] + numbers[big] != target:
            if numbers[little] + numbers[big] > target:
                big -= 1
                while numbers[big] == numbers[big-1] and numbers[little] + numbers[big] > target:
                    big -= 1
            else:
                little += 1
                while numbers[little] == numbers[little+1] and numbers[little] + numbers[big] < target:
                    little +=1
        return [little+1, big+1]

总结

這題第一種應該大部分人都會直覺想到這樣做,畢竟暴力解始終是種解。
但不知道是否我哪裡沒有寫好,兩種作法在leetcode上的時間幾乎一樣。
如果有知道哪裡有問題的大神,麻煩告訴我一下。
感謝花時間看到這裡的大家。

如果有錯,請不吝告知,也可以一起討論,一起加油XD

  • 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、付费专栏及课程。

余额充值