Rotate array - by using another array - python

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.

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)))

Pattern printing with arrays/tuples

So I'm trying to do this
You will be given a positive integer n > 0 and you will construct a pattern that is made up of n rows:
• Row 0 contains 1 number—the number 1
• Each row is one longer than the one before and follows the pattern that ensues
So if variable n:int = 4, the output would be
[1]
[1,2]
[2,3,5]
[5,7,10,15]
The number in the current array is added to the number immediately above it in the previous array and appended at the end of the current array. Also when starting a new array the last element of the previous array is considered as the first element of the current array.
I apologize if my question is unclear, but I hope after the example and explanation I provided, the question is clearer now.
Here is my code:
def append(n: int):
for x in range(1,n+1):
return(x,x+1)
print(append(n))
When I put n = 4, it doesnt seem to work, what's the problem here?
This will do it:
def func(n):
mylist = []
for i in range(n):
if i == 0:
mylist.append([1])
else:
mylist.append(createnewlist(mylist[i-1]))
return mylist
def createnewlist(a):
newlist = []
for i in range(len(a)+1):
if i == 0:
newlist.append(a[len(a)-1])
else:
value = a[len(a)-1]
for m in range(i):
value += a[m]
newlist.append(value)
return newlist
print(func(6))
I don't think your code will return the pattern you want to show. Here's a little code I wrote to print that pattern but there are two loops running, if you could optimize that you could do it or else use the code just as it is.
n=4
arr=[1]
brr = [1]
print(brr)
for i in range(0,n-1):
brr = arr[i:]
for k in range(0,len(arr)):
brr.append(arr[k]+brr[k])
arr = brr
print(brr)

Python list reference and just another copy

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)

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