Python array slice not working as expected - python

I'm trying to write a program for a given array and a value, to remove all instances of that value in place and return the new length.
Example:
Given input array nums = [3,2,2,3], val = 3
It should return length = 2, with the first two elements of nums being 2.
Here is my code:
Code 1:
def removeElement(self, nums, val):
"""
:type nums: List[int]
:type val: int
:rtype: int
"""
i = 0
j = len(nums) - 1
while i <= j:
while i <= j and nums[j] != val:
j -= 1
while i <= j and nums[i] == val:
i += 1
if i <= j:
nums[i], nums[j] = nums[j], nums[i]
return len(nums[i:])
This returns the array slice in reverse order.
Input:
[3,2,2,3]
3
Output: [3,3]
Expected: [2,2]
However, if I make slight modifications at the end of the code 1, it gives me the correct output:
nums[:] = nums[i:]
return len(nums[i:])
Code 2:
def removeElement(self, nums, val):
"""
:type nums: List[int]
:type val: int
:rtype: int
"""
i = 0
j = len(nums) - 1
while i <= j:
while i <= j and nums[j] != val:
j -= 1
while i <= j and nums[i] == val:
i += 1
if i <= j:
nums[i], nums[j] = nums[j], nums[i]
nums[:] = nums[i:]
return len(nums)
I cant figure out why my code 1 doesnt work. Could someone help me understand why slice doesnt work as expected?

This would do what you intend ("... remove all instances of that value in place and return the new length"):
def remove_element(nums, val):
nums[:] = [x for x in nums if x != val]
return len(nums)
Test:
nums = [3, 2, 2, 3]
val = 3
print(remove_element(nums, val))
print(nums)
Output:
2
[2, 2]

Your first example works.
When you slice a new list is created. So in your first code sample you are creating a new list at the end containing the correct result, but never returning it.
In your second code example you are assigning the newly created list to the original list and are hence able to access the final result.

Related

Codewars Python Two sum not working for some test cases

This Python code is not working for some test cases on code wars two sum. Here is the link to the problem:
https://www.codewars.com/kata/52c31f8e6605bcc646000082/train/python
def two_sum(nums, target):
nums.sort()
l = 0
r = len(nums)-1
while l < r:
sum = nums[l] + nums[r]
if sum == target:
return [l, r]
if sum > target:
r -= 1
if sum < target:
l += 1
return []
Any help is much appreciated! :)
The solution you are looking for will be:
def two_sum(nums, target):
indices = {}
for index, num in enumerate(nums):
remainder = target - num
if remainder in indices:
return indices[remainder], index
indices[num] = index
return 0, 0
Right off the bat, I can also tell you that sorting nums before doing anything else is bad because the original indices can get mixed up.
def two_sum(numbers, target):
for n1 in enumerate(numbers):
for n2 in enumerate(numbers):
if n1[0] != n2[0]:
if (n1[1] + n2[1]) == target:
return [n1[0], n2[0]]

Why is there a KeyError

The following is a LeetCode question:
Given an integer array nums which is sorted in ascending order and all
of its elements are unique and given also an integer k, return the kth
missing number starting from the leftmost number of the array.
I wrote a solution (not the best one), and am getting a KeyError. This is being run on the Leetcode platform. Here is my solution:
class Solution:
def missingElement(self, nums: List[int], k: int) -> int:
missing_dict = {}
c = 0
min_nums = nums[0]
max_nums = nums[len(nums)-1]
for num in range(min_nums, max_nums):
num += 1
if num not in nums:
c += 1
missing_dict[c] = num
return missing_dict[k]
Some examples:
Input: nums = [4,7,9,10], k = 1
Output: 5
Explanation: The first missing number is 5.
Input: nums = [4,7,9,10], k = 3
Output: 8
Explanation: The missing numbers are [5,6,8,...], hence the third missing number is 8.
I get the following error: KeyError: 3. I don't understand why I am getting this error? The last executed input was nums = [1,2,4] and k=3 and the expected value was 6.
Added. Since we know the array is sorted in ascending order, I am looping through the array, adding 1 to each element and checking to see if it is in the array. If it is not, then I set the first missing element to that value (missing_dict[1] = value). If the next element aka value+1 is in the array then k is still 1. Otherwise we increment k by 1 and missing_dict[2] = value+1 etc..
Added I just realized the kth missing number doesn't have to be in [min_nums, max_nums]. That wasn't clear before.
Added
1 <= nums.length <= 5 * 10^4
1 <= nums[i] <= 10^7
nums is sorted in ascending order, and all the elements are unique.
1 <= k <= 10^8
Partial Solution
Here is a partial solution using binary search:
class Solution:
def missingElement(self, nums: List[int], k: int) -> int:
def count_missing(x: int) -> int:
return x-min(nums)-1
def binary_search_recursive(nums, k, start, end):
if start > end:
return -1
mid = (start + end) // 2
if(count_missing(nums[mid]) > 0):
if count_missing(nums[mid]) >= k:
return nums[start]+k
else:
return nums[mid]+(k-count_missing(nums[mid]))
if count_missing(nums[mid]) >= k:
return binary_search_recursive(nums, k, start, mid-1)
else:
return binary_search_recursive(nums, k, mid+1, end)
return binary_search_recursive(nums, k, 0, len(nums)-1)
It fails for nums = [2,3,5,7] and k =1 where the output is
6 when it should be 4.
Cause of the key error:
You are getting the key error because the max limit is set to the maximum element of nums. For the given test case nums = [1, 2, 4], k = 3, the missing element is 6 but the dictionary does not contain any key of 3.
From OP comment,
I just realized the kth missing number doesn't have to be in
[min_nums, max_nums]. That wasn't clear in the question.
Solution:
We can use a dictionary to store the given nums list. Then start checking which numbers are not present in the dictionary from the first number on the list.
from typing import List
class Solution:
def missingElement(self, nums: List[int], k: int) -> int:
data = {}
for i in nums:
data[i] = 1
i = nums[0]
while k != 0:
if i not in data:
k -= 1
i += 1
return i - 1
if __name__ == "__main__":
solution = Solution()
nums = [4, 7, 9, 10]
k = 1
print(solution.missingElement(nums, k))
nums = [4, 7, 9, 10]
k = 3
print(solution.missingElement(nums, k))
nums = [1, 2, 4]
k = 3
print(solution.missingElement(nums, k))
Output:
5
8
6

Returning all possible subsets given a list returns wrong answer

I am currently practicing an interview question and doing the one in which I have to return all possible subsets given a list.
For example,
Input: [1,2,2]
Output:
[
[2],
[1],
[1,2,2],
[2,2],
[1,2],
[]
]
is the answer.
class Solution(object):
def subsetsWithDup(self, nums):
"""
:type nums: List[int]
:rtype: List[List[int]]
"""
res = []
subset = []
self.backtrack(sorted(nums), res, subset, 0)
return res
def backtrack(self, nums, res, subset, start):
res.append(list(subset))
for i in range(start, len(nums)):
if i > start and nums[i] == nums[i - 1]:
continue
subset.append(nums[i])
self.backtrack(nums, res, subset, start + 1)
subset.pop()
My solution is as above, using backtracking. I checked the condition if i > start and nums[i] == nums[i - 1] to handle duplicates. However, my output is [[],[1],[1,2],[1,2,2],[2],[2,2],[2,2,2]], giving an extra [2, 2, 2] which is not supposed to be generated.
I drew a diagram following my code, but still don't get why this is getting generated. Isn't it supposed to terminate before that?
Thanks
isValidSubset function do substruction between nums to subset so for
[1,2,2] - [2,2,2] remain 2 and want be a valid subset
def subsetsWithDup(nums):
res = []
subset = []
backtrack(sorted(nums), res, subset, 0)
return res
def isValidSubset(s, n):
nums = s.copy()
subset = n.copy()
return len([i for i in nums if not i in subset or subset.remove(i)]) == 0
def backtrack(nums, res, subset, start):
if (isValidSubset(subset, nums)):
res.append(list(subset))
for i in range(start, len(nums)):
if i > start and nums[i] == nums[i - 1]:
continue
subset.append(nums[i])
backtrack(nums, res, subset, start + 1)
subset.pop()
a = [1, 2, 2]
b = [2, 2, 2]
print(subsetsWithDup(a))

Can someone say what went wrong in this code?

I am working on a problem which takes a nums, row, column as parameters and returns a resultant matrix of size row x column.
def matrixReshape(self, nums, r, c):
"""
:type nums: List[List[int]]
:type r: int
:type c: int
:rtype: List[List[int]]
"""
count = 0
i = j = 0
m = [[0]*c]*r
for row in nums:
for val in row:
if j < c and i < r:
print(val,m[i][j], i, j)
m[i][j] = val
print(val,m[i][j], i, j)
count += 1
j += 1
if j == c:
i += 1
j = 0
if count == (r*c):
return m
else:
return nums
When I tested for input like ([[1,2],[3,4]], 4, 1) it generates output [[4],[4],[4],[4]] instead of [[1],[2],[3],[4]]
m = [[0]*c]*r
This creates a list of r references to the same inner list. So, whenever you modify m[0], you're also modifying m[1], and so on, because they're the same list.
You probably wanted something like this:
m = [[0 for _ in range(c)] for _ in range(r)]
[0]*4 gives you four copies of the same object, not four independent lists.
Try
m = [[0 for i in range(c)] for j in range(r)]

Finding value in a matrix using python

I am getting the error 'int object is not iterable' on this method in my class. Someone assist me find the bug as I can't see what I am doing wrong
def find(self, val): #finds value in matrix
if 0 <= val <= 8:
for i,j in range(3):
#for j in range(3):
if self.matrix[i][j] == val:
return i, j
return None
def find(self, val): # finds value in matrix
if 0 <= val <= 8:
for i in range(3):
for j in range(3):
if self[i][j] == val:
return i, j
return None
Example:
self = [[2,1,2],[1,6,4],[0,0,2]]
val = 4
i, j = find(self, val)
print(i)
print(j)
Print:
1
2
If define self as matrix of numpy:
def find(self, val): # finds value in matrix
if 0 <= val <= 8:
for i in range(3):
for j in range(3):
if self.item((i, j)) == val:
return i, j
return None
here is the part of your code that is causing the error
for i,j in range(3)
the python's built-in range function generates a sequence of number that are then assigned to one variable, but you're using two variables instead
. This is how your code should be :
def find(self, val): #finds value in matrix
if 0 <= val <= 8:
for i in range(3):
for j in range(3):
if self.matrix[i][j] == val:
return i, j
return None

Categories

Resources