Leetcode Python Issue - python

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

Related

Leetcode claiming incorrect answer when it's inarguably correct

I'm trying to complete the 189. Rotate Array problem on Leetcode.
This is the code I've written:
class Solution(object):
def rotate(self, nums, k):
end = len(nums) - 1
carry = []
new = [n for n in nums]
for i in range(end-k+1, end+1):
carry.append(nums[i])
for i in range(1, k+1):
new.pop()
for n in new:
carry.append(n)
print(carry)
return carry
(The obsolete variables were to try and erase any possibility of something wacky happening with Leetcode's testing system.)
I can run this code anywhere (I've tried VS Code and an online interpreter) and the result is always correct (for the first case, [5, 6, 7, 1, 2, 3, 4]).
However, when I try in Leetcode:
The stdout shows the correct answer literally the line before the return, and yet the array somehow magically changes through no tampering.
This is driving me up the wall... please help!!
(Problem description:
Given an array, rotate the array to the right by k steps, where k is non-negative.
Example 1:
Input: nums = [1,2,3,4,5,6,7], k = 3
Output: [5,6,7,1,2,3,4]
Explanation:
rotate 1 steps to the right: [7,1,2,3,4,5,6]
rotate 2 steps to the right: [6,7,1,2,3,4,5]
rotate 3 steps to the right: [5,6,7,1,2,3,4]
Example 2:
Input: nums = [-1,-100,3,99], k = 2
Output: [3,99,-1,-100]
Explanation:
rotate 1 steps to the right: [99,-1,-100,3]
rotate 2 steps to the right: [3,99,-1,-100]
Constraints:
1 <= nums.length <= 105
-231 <= nums[i] <= 231 - 1
0 <= k <= 105
Follow up:
Try to come up with as many solutions as you can. There are at least three different ways to solve this problem.
Could you do it in-place with O(1) extra space?
)
The Python template for this problem says:
class Solution:
def rotate(self, nums: List[int], k: int) -> None:
"""
Do not return anything, modify nums in-place instead.
"""
As the docstring mentioned, you'll need to modify nums in-place. There is no need to print or return anything.
A simple fix to your existing code would be to use an assignment nums[:] = carry at the end.
To answer #mreyeball's question about why nums = carry doesn't work:
Lists are passed by reference. This means that if you pass a list to a method, the list inside the method will refer to the same memory location as the list outside of the method.
This means that changes inside the method will affect the list outside the method as well.
However, this only goes for changes to the elements of a list. When you do nums = carry, you are literally saying "The variable nums will now refer to the same list as carry". Therefore, there is no longer a link between nums and the array that was originally passed to the method.
foo = [1,2,3,4,5]
doStuff(foo)
...
def doStuff(arr):
arr[0] = 2 # this will affect 'foo' as well
bar = ['a','b','c'] # new array
arr = bar # link broken!
arr[0] = 'd' # this won't affect 'foo', but it will affect 'bar'.

Is this code efficient? #LeetCode #two_sum

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 cannot understand why this code is wrong

class Solution:
def firstRepeated(self,A, n):
#arr : given array
#n : size of the array
D={}
for i in range(n):
if A[i] not in D:
D[A[i]]=[i]
else:
D[A[i]].append(i)
c=0
for i in D:
if(len(D[i])>1):
c+=1
return (D[i][0]+1)
if(c==0): return -1
A=[1 ,5 ,3, 4, 3, 5, 6]
n=len(A)
M=Solution()
print(M.firstRepeated(A,n))
this is a problem from geeks for geeks.
" Given an array arr[] of size n, find the first repeating element. The element should occurs more than once and the index of its first occurrence should be the smallest"
the index positions(returned) are assumed to start from 1. If there is no
such element that has frequency more than 1 , we gotta return -1
This code is actually working correctly in VS code, but whenever I use
it in GFG IDE, it's failing(shows 3 as output instead of 2)
Kindly help, as I have no idea what's wrong here.
Your code is returning the index of the repeating element based on the order that keys are stored in the dictionary. After having collected all values in a dictionary keyed by number, your code iterates that dictionary like this:
for i in D:
The order in which this loop will visit the dictionary keys (indexes), depends on the Python version. See Are dictionaries ordered in Python 3.6+?.
At the time of writing Geeks for Geeks uses version 3.5.2, and so the order the keys are visited is undefined, which means that sometimes your function will not return the expected answer on their web site, while on your own environment it will always be correct (if you have a more recent version).
Correction
You can change your code so it does not rely on the order of the dictionary. Instead, during insertion, check which is the dictionary key with the least value. Here is your code corrected just with that change in mind:
class Solution:
def firstRepeated(self,A, n):
D = {}
c = len(A)
for i in range(n):
if A[i] not in D:
D[A[i]] = i # No need to maintain a list
elif D[A[i]] < c: # When the dupe's first index is earlier...
c = D[A[i]]
if c == len(A):
return -1
return c + 1
This will do the trick.
I checked in https://www.onlinegdb.com/online_python_compiler and works correctly.
it works also in https://ide.geeksforgeeks.org/

Rotate array - by using another array

I am trying to solve problem 189 on leetcode
The question is:
Given an array, rotate the array to the right by k steps, where k is non-negative.
According to the solution, I have tried out to implement the idea given in approach 2: by using an "extra" array. Still, I am unable to get the desired result. What's the issue with this code?
I tried brute force approach as well but it's not accepted there, so trying this!! Any help would be appreciated!
i = 0
l = len(nums)
arr = [0]*l
while i < len(nums):
split = l-k
if i >=0 and i < split:
arr[i+k] = nums[i]
if i >= k+1 and i < l:
arr[i-k-1] = nums[i]
i+=1
nums = [0]*l
for a in range(0,l):
nums[a] = arr[a]
print(arr)
print(nums)
After getting some help, I tried with the slicing approach(as suggested in the comments) and this is the code I could come up with:
l = len(nums)
a = nums[:l-k] # appending part
nums = nums[l-k:] # real array
for i in a:
nums.append(i)
print(nums)
Still, this is not running on that website. I am getting the correct output array but not exactly what's the requirement.
Check the below out. I came up with the correction needed.
from typing import List
def rotate(nums: List[int], k: int) -> None:
l = len(nums)
a = nums[:l-k] # appending part
# nums = nums[l-k:] # real array # -> How you have written
nums[:] = nums[l-k:] # real array # -> How it should be
for i in a:
nums.append(i)
# print(nums) # Not needed
nums = [1,2,3,4,5]
rotate(nums, 3)
print(nums)
Problem with you code is that, the task expects you to modify the list that is being passed into the function. However when you assign it like nums = nums[l-k:], that will be visible only to within the function. That's why when you print it you saw the expected result. But that assignment will not modify the list referred to by that variable. Instead, you should do the assignment like nums[:] = nums[l-k:], in order to modify the list, which is in the global scope.

Find the Duplicate Number

Given an array nums containing n + 1 integers where each integer is between 1 and n (inclusive), prove that at least one duplicate number must exist. Assume that there is only one duplicate number, find the duplicate one.
My solution:
def findDuplicate(nums):
slow = fast = finder = 0
while fast is not None:
slow = nums[slow]
fast = nums[nums[fast]]
if fast is slow:
return slow
return False
nums = [1,2,2,3,4]
print findDuplicate(nums)
My above solution works and gives me o/p 2 but it doesn't work for every input for example it doesn't work for [11,15,17,17,14] or [3,1,2,6,2,3] and gives me error IndexError: list index out of range. I am not able to find patterns and am not able to track down the exact problem. Also tried to change my while condition:
while fast is not None and nums[nums[fast]] is not None:
your help will be greatly appreciated! Thank you.
Since the numbers are between 1 and n and you have been told there is only one duplicate, you can use difference between the sum of the numbers in the array and the sum of numbers from 1 to n to get the duplicate.
def findDuplicate(l):
n = len(l) - 1 # Get n as length of list - 1
return sum(l) - (n * (n + 1) / 2) # n*(n+1)/2 is the sum of integers from 1 to n
So the duplicate is the sum of the list - n*(n+1)/2
Of course, this doesn't generalize to finding duplicates for any list. For that case, you need to use #Jalepeno112 's answer.
The fact that the first one works is a fluke. Let's look at what it does on the first pass.
nums = [1,2,2,3,4]
# slow starts as index 0. So now, you've reassigned slow to be nums[0] which is 1.
# so slow equals 1
slow = nums[slow]
# now you are saying that fast equals nums[nums[0]].
# nums[0] is 1. nums[1] is 2
# so fast = 2
fast = nums[nums[fast]]
On the next pass, slow will be nums[1] which is 2. fast will be nums[nums[2]] which is nums[2] which is 2. At this point slow and fast are equal.
In your second example, you are getting an IndexError because of fast = nums[nums[fast]] If the value at nums[fast] is not a valid index, then this code will fail. Specifically in the second example, nums[0] is 11. nums doesn't have an element at index 11, so you get an error.
What you really want to be doing is performing a nested for loop on the array:
# range(0,len(nums)-1) will give a list of numbers from [0, to the length of nums-1)
# range(1, len(nums)) does the same,
# except it will start at 1 more than i is currently at (the next element in the array).
# So it's range is recomputed on each outer loop to be [i+1, length of nums)
for i in range(0,len(nums)-1):
for j in range(i+1,len(nums)):
# if we find a matching element, return it
if nums[i] == nums[j]:
return nums[i]
# if we don't find anything return False
return False
There are likely other more Pythonic ways to achieve this, but that wasn't your original question.
first you must ensure all numbers in list satisfy your constrains.
to find duplicated numbers in a list Use Counter in collections it will return each number and number of occurrence example :
>>> from collections import Counter
>>> l=Counter([11,15,17,17,14])
>>> l
Counter({17: 2, 11: 1, 14: 1, 15: 1})
to get the most common one use :
>>> l.most_common(n=1)
[(17, 2)]
where n is the number most common numbers you want to get
def duplicates(num_list):
if type(num_list) is not list:
print('No list provided')
return
if len(num_list) is 0 or len(num_list) is 1:
print('No duplicates')
return
for index,numA in enumerate(num_list):
num_len = len(num_list)
for indexB in range(index+1, num_len):
if numA == num_list[indexB]:
print('Duplicate Number:'+str(numA))
return
duplicates([11,15,17,17,14])
duplicates([3,1,2,6,2,3])
duplicates([])
duplicates([5])
l=[]
n= int(input("the number of digit is :"))
l=[0 for k in range(n)]
for j in range(0,n):
l[j]=int(input("the component is"))
print(l)
b=0; c=0
for i in range(n):
if l[i]== l[n-1-i]:
b=1;c=i
if b==1:
print("duplicate found! it is",l[c])
elif b==0:
print("no duplicate")
The answer is unfinished. It tries to convert the array to a linked list. So far it found where the slow pointer and fast pointer met, but this is the halfway solution. To get the solution, we need to initialize another pointer from the beginning of the linked list and walk towards each other. When they meet, that point is the where cycle is detected, in our question it is where the single point is:
class Solution:
def findDuplicate(self, nums: List[int]) -> int:
slow,fast=0,0
while True:
slow=nums[slow]
fast=nums[nums[fast]]
if slow==fast:
break
slow2=0
while True:
slow2=nums[slow2]
slow=nums[slow]
if slow==slow2:
return slow2

Categories