The code I have written that aims to solve the Two Sum problem:
def twoSum(self, nums: List[int], target: int) -> List[int]:
dict = {}
for i in range(len(nums)):
complement = target - nums[i]
if complement in dict:
return [dict[complement], i]
dict[complement] = i
I have just started practicing on LeetCode and I am experiencing issues with solving the Two Sum problem.
The problem statement:
Given an array of integers nums and an integer target, return indices
of the two numbers such that they add up to target.
You may assume that each input would have exactly one solution, and
you may not use the same element twice.
You can return the answer in any order.
My reasoning is to create a dictionary and iterate through the numbers, and for each number generate a complement number that I then look for in my dictionary, if it in fact is there, then I return the index that generates that complement and the current index i. Otherwise, I insert the key with the complement.
Somehow my function does not output anything, just two empty brackets. Below there is a sample input and correct output.
Input: nums = [3,2,4], target = 6
Output: [1,2]
The last line is wrong. It should read dict[nums[i]] = i, because you are storing indeces for their values. Here is the entire function with a better variable name that doesn't shadow the built-in type:
def twoSum(self, nums, target):
dct = {}
for i in range(len(nums)):
complement = target - nums[i]
if complement in dct:
return [dct[complement], i]
dct[nums[i]] = i
Or more concise using enumerate and storing indeces for their complement values:
def twoSum(self, nums, target):
dct = {}
for i, num in enumerate(nums):
if num in dct:
return [dct[num], i]
dct[target - num] = i
You may notice that you had a mixture of the two approaches. You looked for the complement in dct, and also wanted to store it for the current index. One of the two needs to be the current value.
Related
I'm working on https://leetcode.com/problems/permutations/ and I'm trying to decide which approach for generating the permutations is more clear. The question is "Given an array nums of distinct integers, return all the possible permutations. You can return the answer in any order." I've got two different solutions below.
Solution 1
def permute(self, nums: List[int]) -> List[List[int]]:
results = []
N = len(nums)
def dfs(subset, permutation: List[int]):
if len(subset) == N:
results.append(subset.copy())
return
for i, num in enumerate(permutation):
subset.append(num)
dfs(subset, permutation[:i] + permutation[i+1:])
# backtracking
subset.pop()
dfs([], nums)
return results
Solution 2
def permute(self, nums: List[int]) -> List[List[int]]:
results = []
N = len(nums)
def dfs(subset, permutation: List[int]):
if len(subset) == N:
results.append(subset.copy())
return
for i, num in enumerate(permutation):
dfs(subset + [num], permutation[:i] + permutation[i+1:])
dfs([], nums)
return results
I believe in the first solution, when you append to a list in python (i.e append to the subset parameter), lists are pass by reference so each recursive call will share the same list. This is why we have to explicitly backtrack by popping from subset. However in the second solution when a list is passed to a recursive call with the syntax subset + [num], a copy of the list is passed to each recursive call so that's why we don't explicitly have to backtrack.
Can someone confirm if my assumptions are correct? Is one approach favored over another? I think the time and space complexities are identical for both approaches (O(N!) and O(N), respectively) where N = the number of elements in nums.
Yes you are right that the first permute passes the same object (subset) in each recursive call.
And this is possible in first permute because lists are mutable, if you had a string to permute upon then you have to pass a copy because they are immutable.
And in the second permute a copy of subset is created. You can test it with the statement print(id(subset)) at the beginning of dfs in each permute. You can observe that the statement prints same id in the first permute but not in the second permute.
To me even though both have same time complexity (depends on what you do at the base condition - its O(N.N!) and not O(N!) because you are appending a copy of list to the result list ), why do you want to create a copy of subset and place an entirely new object on stack when you can have the copy of object reference (not the object itself!) on the stack which consumes less memory. So I prefer first permute.
This is two sum problem from leetcode, I tried to solve, It got accepted. I am asking if this code is efficient enough in terms of memory and space complexity.
My code :
class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
l = len(nums)
ans = []
for i in range(l):
compliment = target - nums[i];
# print(a.index(x))
if compliment in nums:
if nums.index(compliment)!=i:
# print(a.index(x))
ans.append(i)
ans.append(nums.index(compliment))
break;
return ans
Your code searches for compliment in nums, and then follows it up with an index function. Later on, you use this index again in nums.index(compliment). Essentially, you're searching through the array three times. A better way would be to search through the array and store the index if found, else -1. If the index is not -1, i.e., present in the array, you can append it to ans. This essentially skips the two lines (and that index function) and traverses the array once instead of thrice.
index_if_found = -1
for index in range(len(arr)):
if arr[index] == search_value:
index_if_found = index
break
You can now use this index index_if_found instead of using the index function.
EDIT: Thanks to Kelly for correcting me on the search algorithm.
Additionally, you have two append methods to the same array. A slightly faster approach would be to use the extend method and add them in the same operation. So instead of
ans.append(i)
ans.append(nums.index(compliment))
You'd have
ans.extend((i, nums.index(compliment)))
I am currently on LeetCode and am looking through the solutions for the Two Sum problem. Here are the instructions,
"Given an array of integers nums and an integer target, return indices of the two numbers such that they add up to target.
You may assume that each input would have exactly one solution, and you may not use the same element twice.
You can return the answer in any order."
I ran across a couple solutions and I saw this answer:
def twoSum(self, nums: [int], target: int) -> tuple:
num2idx = {}
for idx, val in enumerate(nums):
if target - val in num2idx:
return num2idx[target - val], idx
num2idx[val] = idx
The part that I am unsure of is this,
if target - val in num2idx:
return num2idx[target - val], idx
num2idx[val] = idx
How exactly will this return both indices of the numbers that add up to the target? It looks to me like what is being return is solely the, "target-val" as well as the index of the current num being iterated over.
num2idx is holding the location of each number, not the number itself. The statement
return num2idx[target - val], idx
returns the index of the current number, as well as the index of the number that makes up the difference between the current number and the target.
I'm trying to learn about PEP-8 guidelines, writing Pythonic code, and about Python's standard libraries (am a day into this journey). Suggestions to make the following piece of code (including comments) more Pythonic would be much appreciated. I know the algorithm could be improved, but this isn't a priority at the moment - but please do write if you have an elegant solution!
I've run it through the following PEP-8 checker, so hopefully the basics are not a problem: http://pep8online.com/checkresult
import collections
def two_sum(input_list, target):
# Determine if two elements in list add to target
# dict_of_counts - key: element from input_list, value: count of element
dict_of_counts = collections.Counter(input_list)
for key in dict_of_counts:
complement_key = target - key
if complement_key in dict_of_counts:
# Corner case: complement_key is the same as key,
# but the count is one (so threat of a false +ve)
if complement_key != key:
return(True)
elif dict_of_counts[complement_key] > 1:
return(True)
return(False)
P.S. My first question ever : O !
If you want to improve your PEP-8 skills, I highly recommend using a linter such as flake8. It is really good in finding any PEP-8 violations, and while you're trying to make flake8 happy you'll learn all the ins- and outs as you go.
from typing import List, Tuple
if complexity is not an issue the most pythonic way (for me) is:
def pair_sum_v1(array: List[int], s: int) -> List[Tuple]:
"""
:param array: list of integers
:param s: sum
:return: list of unique pairs [(a1,b1), (a2,b2)] where ai+bi=s
"""
pair_sums = [(num, s - num) for idx, num in enumerate(array) if s - num in array[idx:]]
return pair_sums
if you want to make it faster:
def pair_sum_v2(array: List[int], s: int) -> List[Tuple]:
"""
:param array: list of integers
:param s: sum
:return: list of unique pairs [(a1,b1), (a2,b2)] where ai+bi=s
"""
explored_integers = []
pair_sums = []
for idx, num in enumerate(array):
if num not in explored_integers:
complement = s - num
if complement in array[idx:]:
pair_sums.append((num, complement))
explored_integers.extend([num, complement])
return pair_sums
While Trying to solve few question from LeetCode I am facing a really weird issue.
Question 26: Remove Duplicates from Sorted Array
https://leetcode.com/problems/remove-duplicates-from-sorted-array/description/
Example:
Given nums = [1,1,2],
Your function should return length = 2, with the first two elements of
nums being 1 and 2 respectively.
It doesn't matter what you leave beyond the new length.
In order to code this question I used :
class Solution(object):
def removeDuplicates(self, nums):
nums = list(set(nums))
return len(nums)
what this code is doing is first converting the list into a set and
then back to list, which in turn will remove the Duplicates
But when I am trying to submit this code to the leetcode solution, modified length of nums is returned but when the program is trying to access the nums array it is not updated.
This is only Happening in Leetcode editor, in my system If I try to print the nums, the modified value is displayed, not sure what is wrong.
Now the same case is Happening to other question as well, for example:
Rotate Array
https://leetcode.com/explore/interview/card/top-interview-questions-easy/92/array/646/
Rotate an array of n elements to the right by k steps.
For example, with n = 7 and k = 3, the array [1,2,3,4,5,6,7] is rotated to [5,6,7,1,2,3,4].
My solution to this problem is as follows:
class Solution(object):
def rotate(self, nums, k):
newIndex = k % len(nums)
nums = nums[newIndex+1:len(nums)] + nums[0:newIndex+1]
print nums
But again I am amazed by the output I am getting back from the submission.
Note Here in the "Your STDOUT" we can see the list is modified accordingly.
link to the Screenshot
Please let me know if anyone else is facing this issue or anyone knows the solution to this.
Turns out the solution to this is to use: nums[:] = nums[newIndex+1:len(nums)] + nums[0:newIndex+1].
Doing nums = nums[newIndex+1:len(nums)] + nums[0:newIndex+1] simply changes the reference, while nums[:] changes the values of the list.
You can use
sudo service network-manager restart
what was happening in your code is the length you were returning is been used to travel the nums in back-end to print the unique values of the nums list. So, the requirement off the problem was the length you returned will be traveled from index 0 to the length returned. Hence with returning the length of unique values, we also have to modify the original list i.e., nums .
Solution for the 1st link
class Solution:
def removeDuplicates(self, nums):
if(len(nums) == 0):
return 0
elif len(nums) == 1 :
return 1
else:
l = 1
for i in range (1,len(nums)):
if nums[i] != nums[i-1] :
#l+=1
nums[l] = nums[i]
l+=1
return l