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/
Related
I am trying to use recursion to solve the OddOccurrencesInArray Problem in Codility, in which
we are given an array with N elements, N is always odd
all of the elements of the array except for one has a total even number of occurrences
we need to write code that returns the one unpaired value
For example, if the array given is [9, 3, 9, 3, 7, 9, 9], the code must return 7, because that is the only element in the array which is unpaired.
My solution pseudocode/thought process was:
sort the array
if the first two elements are equal to each other, remove them and run the solution algorithm again recursively on the array minus the first two elements (after sorting) i.e. if the unpaired element is not found, we keep reducing the size of the array
if the first two elements are NOT equal to each other, the first element of the array must be the unpaired item
My implementation was:
def solution(A):
# write your code in Python 3.6
if len(A) > 1:
A = sorted(A)
if A[0] != A[1]:
return A[0]
else:
solution(A[2:])
else:
return A[0]
I keep getting the error message
Invalid result type, int expected, <class 'NoneType'> found.
RUNTIME ERROR (tested program terminated with exit code 1)
Can anyone help me figure out what this means and how I can correct it? Algorithmically, I think my solution is sound, and I don't understand why it isn't returning the integer values as I specified.
Another Python solution 100%
There is another solution where we can use XOR logic.
First Let's remember together what does XOR mean:
So we can recognize that if we have for Input A and Input B the same bit then, XOR Output will be zero.
Also, if we take the bit XOR of any number with zero will definitely give the same number because the bits of the number will result in the same bits which means the same number.
Now, to solve the problem with the XOR logic, we start by defining a number that will hold the result of the XOR output each time, so first, we start with zero and I said earlier that 0 with any number gives the same number.
but if we get a different number next time, the XOR result will be some unknown number.
In the end, for sure the number that did not pair will be returned.
Since a solution like this will be possible with only one loop we need to loop through all elements and if we do break at some point, the result of the XOR would be some number we do not need so we need to make sure that we loop through the whole array once and then because of the fact that bit XOR of the same number would return zero. so that we remain at the end with the number that is unpaired with anything.
Detected time complexity:
O(N) or O(N*log(N))
def solution(A):
num = 0
for i in range(len(A)):
num = num ^ A[i]
return num
I would suggest a different approach altogether. A recursive approach is not incorrect, however repeated calls to sorted is highly inefficient, especially if the input is significantly large.
def solve(t):
s = set()
for v in t:
s.add(v) if v not in s else s.remove(v)
return list(s)
input = [9, 3, 9, 3, 7, 9, 9]
solve(input)
We can visualize s over the course of the evaluation -
{} # <- initial s
{9} # <- 9 is added
{9,3} # <- 3 is added
{3} # <- 9 is removed
{} # <- 3 is removed
{7} # <- 7 is added
{7,9} # <- 9 is added
{7} # <- 9 is removed
The finally list(s) is returned converting {7} to [7]. To output the answer we can write a simple if/elif/else -
unpaired = solve(input)
if (len(unpaired) < 1):
print("there are no unpaired elements")
elif (len(unpaired) > 1):
print("there is more than one unpaired element")
else:
print("answer:", unpaired[0])
Another option is to have solve return the first unpaired element or None -
def solve(t):
s = set()
for v in t:
s.add(v) if v not in s else s.remove(v)
for v in s:
return v # <- immediately return first element
answer = solve(input)
if answer is None:
print("no solution")
else:
print("the solution is", answer)
You don't return anything from your recursive call, which means you are returning None.
def solution(A):
cloned = []
A.sort()
if len(A) > 1:
for itr in A:
if itr in cloned:
itrindex = cloned.index(itr)
cloned.pop(itrindex)
else:
cloned.append(itr)
else:
return A[0]
return cloned[0]
It has something simple like this using php array functions, it had 100% score at codility, thought it might help if python has some array functions like this.
function solution($a){
$result = array_count_values($a);
$result = array_filter($result , function($a){
return ($a % 2) && 1;
});
return key($result);
}
I tried multiple ways but the performance just doesn't get better!
def solution(A):
for i in set(A):
if A.count(i) == 1:
return i
This just gives me a 25% perf score. However, I tried other way also.
from collections import Counter
def solution(A):
c = Counter(A)
final = [k for k, v in c.items() if v == 1]
return final[0]
This could be a solution but the performance score is just 50%. Not sure what makes it 100%. Please post if you get 100% perf for this challenge in Codility.
Edit1:
def solution(A):
A.sort()
A.append(-1) #Just to make list even and run till last but not match with existing integers
for i in range(0,len(A),2):
if A[i]!=A[i+1]:
return A[I]
This got me a 100% perf score. Ref:CodeTrading (YouTube)
I have written a code and run it, and it works fine. But I wanted to understand what is happening in the following:
nums = [4, 5, 1, 8]
target = 12
def TwoSum(nums, target):
comps = dict()
for i in range(len(nums)):
comp = target - nums[i]
if nums[i] in comps:
return [comps[nums[i]], i]
else:
comps[comp] = i
print(TwoSum(nums, target))
I understand that this is using a dict, and the idea is to add elements from nums to it, then doing target - nums[i] and then checking if this is in the dict, and if it is, then returning the indices of the two numbers that sum to the target.
But how is comps = dict() used? Is it necessary? Because in the code it doesn't seem to be storing anything! Except for the last line it is used- but I don't understand what it does- can someone please explain?
First, your code was using self as first argument of TwoSum. It should be eliminated given that this is a static function, not a class method. (Fixed).
The line comp = dict() is an initialization of comp to an empty dict. It could be written in a more pythonic way: comp = {}.
comp appears to store the complement (the difference between target and nums[i]) as comps[diff] = i. Thereafter, when you examine a number nums[j], if the complement is already in comps, that j and the corresponding previous i is the pair of indices you are looking for.
In our case, it stores number as a key thats required to find a target, and index of opposit number in nums as value.
So, for example, when we have target at 12 and nums [4,5,1,8] , at the iteration on the number 4, 8->0 will be added to comps, when iteration will get to the number 8, we will check if we have number 8 in comps, and then return value of that number in comps, which is 0, and index of current iterating number, which is 3.
This code snippet is one of posts in a LeetCode problem by fukuzawa_yumi
def splitArray(self, nums):
d,n={nums[0]:[0]},len(nums)
for i in range(1,n):
nums[i]+=nums[i-1]
if nums[i] not in d: d[nums[i]]=[i]
else: d[nums[i]].append(i)
for i in range(1,n-5):
for k in d.get(nums[-1]-nums[i-1],[]):
if i+3<k<n-1 and any(nums[i-1]+nums[j+1]==nums[k-1] for j in d.get(nums[i]+nums[i-1],[]) if i<j<k-2): return True
return False
The nums[0]:[0], d: d[nums[i]]=[i] are unfamiliar to me and I can't find explanation online.
Please, reference me in the right direction and give a few examples for posterity.
d,n={nums[0]:[0]},len(nums)
Is a somewhat ugly way of writing1:
d = {nums[0]: [0]}
n = len(nums)
It creates a dictionary d with a single item. The key is the first element in nums and the value is a one element list containing 0.
Later on, when you get to:
d[nums[i]] = [i]
This is a "replace-or-set" operation on the dictionary. The code is setting a dictionary item with key = nums[i] to a list with a single element whose value is i.
1In my subjective opinion :)
d,n={nums[0]:[0]},len(nums)
What this line is doing is:
bind d to a dictionary formed a single element with the key nums[0] (first element in list nums) and value [0] (a list containing 0)
bind n to the length of the list nums
It is possible to combine the two assignments on one line like this in Python. Python will perform the assignment of the variables based on the order. It's the same as doing tuple expansion.
So I wrote this algorithm where given a set of integers it will remove all integers except 0 and 7 and then it will check if the remaining integers are in a certain order and then will return a boolean. Code below:
def spy_game(nums):
for i in nums:
if i != 0:
if i == 7:
continue
else:
nums.remove(i)
else:
continue
stringlist = [str(o) for o in nums]
mystring = ''.join(stringlist)
return '007' in mystring
spy_game([1,0,2,4,0,7,5])
Now the problem is that if I run
(for example) spy_game([1,0,2,4,0,7,5]) it will not return True regardless of the fact that the sequence of interest is present. After I decided to return the list per se after the filtration process, I found that all numbers except the ones in the middle got filtered out. So in this example, if I return nums it will return [0, 4, 0, 7] although the 4 should've been removed. I am aware that there are more optimal alternatives to this algorithm but I just want to understand why it doesn't work. Thank you.
Instead of modifying the list, use another list to keep track of the wanted numbers.
You should not modify the list while iterating on it.
Here's a cleaned up version
def spy_game(nums):
ans = []
for i in nums:
if i == 0 or i == 7:
ans.append(i)
stringlist = [str(o) for o in ans]
mystring = ''.join(stringlist)
return '007' in mystring
zenwraight's comment says what the problem is: in Python, you can't modify a list while iterating over it.
As for why, the Python documentation discusses this in a note on the for statement's section:
An internal counter is used to keep track of which item is used next, and this is incremented on each iteration. … This means that if the [loop body] deletes the current … item from the sequence, the next item will be skipped (since it gets the index of the current item which has already been treated).
The documentation also describes what happens when you insert an element during a loop, and suggests one possible solution (using a slice to copy the list: for i in nums[:]: ...). In your use case, that solution is likely to work fine, but it is considerably less efficient than options that don't copy the entire list.
A better solution might be to use another list comprehension:
nums = [i for i in nums if i == 0 or i == 7]
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