Python list reference and just another copy - python

I wish to bring that last k elements of 'nums' array to the first. Like, Input:
nums = [1,2,3,4,5,6,7], k = 3
Output:
[5,6,7,1,2,3,4]
I have the following code:
class Solution(object):
def rotate(self, nums, k):
"""
:type nums: List[int]
:type k: int
:rtype: None Do not return anything, modify nums in-place instead.
"""
n = len(nums)
k = k % n
nums[:] = nums[n-k:] + nums[:n-k]
This works perfectly fine i.e. brings the last k elements to the beginning and nums shows [5,6,7,1,2,3,4]. But once I type the following nums = nums[n-k:] + nums[:n-k], it shows the resultant nums array as being the same original [1,2,3,4,5,6,7].
My question is, why is the change in output taking place? On googling and upon reding certain other threads in this forum pertaining to 'List Referencing and copying', I could realize that nums = is something about list referencing but nums[:] is like a mere copy of the list. But having said thiat, why is this change in output taking place? What's happening inside both the commands?
Seems like nums and nums[:] aren't yet clear to me. Please help.

Explanation
nums = nums[n-k:] + nums[:n-k]
The assignment nums = nums[n-k:] + nums[:n-k] would be equivalent to create a new list in memory (with the elements reversed), and changing the pointer nums to point to that new list. But since the variable nums that you change is local to the function, this change does not affect to the external one passed as parameter. Check follow diagram for better understanding:
nums[:] = nums[n-k:] + nums[:n-k]
The assignment nums[:] = nums[n-k:] + nums[:n-k] would be equivalent to write a new reversed list at the same address pointed by nums, because the slice allows to replace part of a list with new contents.
In this case you are not changing the variable nums, but the data pointed by it.
Example Code:
def rotate(nums, k):
"""
:type nums: List[int]
:type k: int
:rtype: None Do not return anything, modify nums in-place instead.
"""
n = len(nums)
k = k % n
# in function
# nums[:] = nums[n-k:] + nums[:n-k]
nums = nums[n-k:] + nums[:n-k]
# in scope
nums = [1,2,3,4,5,6,7]
k = 3
rotate(nums, k)
print(nums)

Related

No output from algorithm for Two Sum problem in Leetcode

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.

why do python lists doesn't store data properly during recursion

I am very much confused with my following code,
The code is about printing all the possible subsets(power set) for a given set of numbers.
It works well when I use a set() for storing but it fails while using lists in the process of recursion. It returns a list of empty lists
def helper(self,ind,l,nums,ans,n):
ans.append(l)
for i in range(ind,n):
if ind!=i and nums[i]==nums[i-1]:
continue
l.append(nums[i])
self.helper(i+1,l,nums,ans,n)
l.remove(nums[i])
def subsetsWithDup(self, nums: List[int]) -> List[List[int]]:
nums.sort()
n = len(nums)
ans = []
self.helper(0,[],nums,ans,n)
return ans
But using set it works completely fine
def helper(self,ind,l,nums,ans,n):
ans.add(tuple(l))
for i in range(ind,n):
if ind!=i and nums[i]==nums[i-1]:
continue
l.append(nums[i])
self.helper(i+1,l,nums,ans,n)
l.remove(nums[i])
def subsetsWithDup(self, nums: List[int]) -> List[List[int]]:
nums.sort()
n = len(nums)
ans = set()
self.helper(0,[],nums,ans,n)
return ans
I want to know the why is it returning empty list why doesn't it store the appended lists properly
You are storing the l object in your ans list. You then go on to manipulate the l list, and by the time the function is finished, l is empty. So, ans will end up with a set of empty list objects.
In the set case, it works NOT because it's a set, but because you have made a copy of l and converted it to a tuple. If you did the same in the list case, it also would work.

Why is this solution not ideal for "Rotate Array" leetcode question? [duplicate]

This question already has answers here:
Efficient way to rotate a list in python
(27 answers)
Closed 1 year ago.
the question on leetcode says "Given an array, rotate the array to the right by k steps, where k is non-negative."
for example
"Input: nums = [1,2,3,4,5,6,7], k = 3
Output: [5,6,7,1,2,3,4]"
My solution in python was:
def rotate(self, nums, k):
"""
:type nums: List[int]
:type k: int
:rtype: None Do not return anything, modify nums in-place instead.
"""
i = 0
while (i < k):
nums.insert(0, nums.pop())
i+=1
This does not seem to match any of the given solutions. I am curious what the time/space complexity of this would be? Is that why this is not a given solution? OR is it best to not use array functions in tech interviews?
Thanks
Heres on example of cut list in python, not sure if this is the solution you are looking for. Where you take the list at index k to the length of the list. So in this case its 3 to 6 and you take beginning of list 0 to 2 and you take the first part of the list and you add it to the end of the list by amount of k.
nums[k:length] = [4,5,6,7]
nums[0:k] = [1,2,3]`
def rotate(nums, k):
length = len(nums)
nums[:] = nums[k:length] + nums[0:k]
print(nums)
number = [1,2,3,4,5,6,7]
rotate(number,3)
Here is a link to some other explantions.
https://www.geeksforgeeks.org/python-program-for-program-for-array-rotation-2/
insert will internally copy all the consequent n-1 elements by 1 for each iteration. Hence, your code is of time complexity O(nk) as Paul said. Thus, even though it answers the question, it is too inefficient for a large array. Instead, you could use array slicing, which is of time complexity O(N).
def rotate_to_right(nums, k):
"""
:type nums: List[int]
:type k: int
:rtype: None Do not return anything, modify nums in-place instead.
"""
d = len(nums) - k
nums[:]=nums[d:]+nums[:d]
if __name__ == '__main__':
nums = [1,2,3,4,5,6,7]
k = 3
rotate_to_right(nums, k)
print(nums)
Result:
[5, 6, 7, 1, 2, 3, 4]

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.

Leetcode Python Issue

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

Categories