Leetcode #35 Search Insert Position (list index out of range) - python

test=[]
for i in range(len(nums)):
if nums[i+1] > target > nums[i]:
test.append(nums[i])
test.append(target)
else:
test.append(nums[i])
return test.index(target)
I try to create new array sort the value first, then find the index of the target.
It get error in index out of range in line nums[i+1].
How can I correct the code without the big change
Question link: https://leetcode.com/problems/search-insert-position/

What you are doing wrong:
This is because you are using nums[i+1] and since i is in the range 0 to len(nums) it gives index out of range for the last value of i.
You are checking if an element in nums is greater than the previous element or not. This will always be true because nums is sorted. I also don't know why are you appending the nums[i+1] and target to the test list. There's no need to create a new list.
What the question asks you to do
It tells you that the nums is sorted and you need to return the index if target is in nums. If not then return the index where it should be inserted. NOTE: It doesn't ask you to insert the target.
So, the steps which you can follow are:
Loop through nums. You can use for i, num in enumerate(len(nums)):. This will give you the index i.e. i and the value of each element in nums i.e. num.
Take each element to check if the target is greater than or equal to nums[i].
If it is then you need to return that index because that would be the index where the target needs to be inserted. Eg: [1,3,6,8] if target is 5 then it should be inserted at 2 which is the index of nums[i] > target.
If target is greater than the last element of nums then return the last index of nums i.e. len(nums).
Combining all steps. The code we get(Do try it yourself first! Spoiler Alert!):
def searchInsert(self, nums: List[int], target: int) -> int:
for i, num in enumerate(nums):
if num >= target:
return i
return len(nums)

Related

Python code throws error list out of range, even though the logic is same

1)
class Solution:
def removeDuplicates(self, nums: List[int]) -> int:
i = 1
while i < len(nums)-1:
if nums[i]==nums[i-1] and nums[i]==nums[i+1]:
del nums[i]
else:
i+=1
return len(nums)
The code above happens to work perfectly.
2)
class Solution:
def removeDuplicates(self, nums: List[int]) -> int:
n = len(nums)-1
i = 1
while i < n:
if nums[i]==nums[i-1] and nums[i]==nums[i+1]:
del nums[i]
else:
i+=1
return len(nums)
But the 2nd code throws this error :-
IndexError: list index out of range
if nums[i]==nums[i-1] and nums[i]==nums[i+1]:
The logic behind both the codes happens to be same, in the first code we don't store the length of the list nums, instead we use it in while loop directly like while < len(nums) - 1
In the second code, we store the value of len(nums) in a variable n, and use it in a similar fashion in the while loop, while i < n - 1
I don't understand what's the difference between the two.
Your two snippets are not identical.
Notice that the list is modified inside the loop with del nums[i], so its length changes.
In the first code, you access len(nums) every time you need it, so you always get the correct value of len(nums).
In the second code, when you do n = len(nums) - 1, the value of len(nums) - 1 at that time is assigned to the variable n. This variable isn't automatically updated when the value of len(nums) changes, so even after you delete elements of the list, n still has its original value.

Divide and Conquer to check if a value in a list is equal to its index

Given a list of distinct integers (decreasing order), return True if there is atleast position p, such that the value at position p is p. For instance, List = [4, 3, 2, 0], the function returns true since 2 is at index 2.
I know we can just go for a loop and check if list[i] == i.
I was wondering if and how this can be implemented with the divide and conquer algorithm?
My base cases are:
L is empty, return False.
If L[0] is negative, return False. Since list is in decreasing order, all values will be negative, and all index are positive. SO we will not get a match. For simplicity, i am just considering positive index.
I am a bit confused how to divide the list here. Since splitting the list in 2, each list would have index [0:n/2]. So comparing the the values and index dont make sense.
Appreciate some help!
You only need to compare the starting and ending values of a list to the values in the list index to see if it's possible.
Code
def divide_conqueer(lst, indexes = None):
if indexes is None:
indexes = list(range(len(lst))) # create list index
if not lst:
return False
elif len(lst) == 1:
return lst[0] == indexes[0]
elif lst[0] < indexes[0] or lst[-1] > indexes[-1]:
# Compare values of beginning and end of the list to the
# list indexes of the beginnning and end
# There is a matching value to index only if beginning value >= starting index and
# ending value <= ending index
return False
else:
# Divide values and intervals in half and test each half
return (divide_conqueer(lst[:len(lst)//2], indexes[:len(indexes)//2]) or
divide_conqueer(lst[len(lst)//2:], indexes[len(indexes)//2:]))
Test
print(divide_conqueer([4, 3, 2, 1]))
# Output: True

Index out of range | Python

I am attempting the TwoSum Question using python and have tried the two pointer method essentially having a pointer at the beginning and end of the array, when the sum of the two indexes is greater than the value where are looking for it decrements the ending pointer one index less and if the sum is less than it increments the beginning pointer by 1. I keep getting an index out of range error and would like to know why it happens. I stepped through my code and everything seems to make sense and my test case passes but it gives me an out of range error when I get a list like this:
[-1,-2,-3,-4,-5] and the target being -8
the goal is to output index positions [2,4] using the two pointer technique
Here is my code:
class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
stack = list()
n = len(nums)
j = (len(nums)-1)
i = 0
while i < n:
tempSum = nums[i] + nums[j]
if tempSum == target:
stack.append(i)
stack.append(j)
break
if tempSum > target:
j-=1
else:
i+=1
return stack
The error happens due to the logic you have built in your while loop. Whenever tempSum is larger than target, you subtract 1 from j. When working with negative numbers, this means that your loop will continue reducing j until it reaches j=-6, at which point it will produce an out of range error.
Try taking the absolute value of tempSum and target within your if statement, then the evaluation will work in case of negative numbers as well.
if abs(tempSum) > abs(target):
j-=1
else:
i+=1

Two Sum solution on LeetCode

I am currently on LeetCode and am looking through the solutions for the Two Sum problem. Here are the instructions,
"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."
I ran across a couple solutions and I saw this answer:
def twoSum(self, nums: [int], target: int) -> tuple:
num2idx = {}
for idx, val in enumerate(nums):
if target - val in num2idx:
return num2idx[target - val], idx
num2idx[val] = idx
The part that I am unsure of is this,
if target - val in num2idx:
return num2idx[target - val], idx
num2idx[val] = idx
How exactly will this return both indices of the numbers that add up to the target? It looks to me like what is being return is solely the, "target-val" as well as the index of the current num being iterated over.
num2idx is holding the location of each number, not the number itself. The statement
return num2idx[target - val], idx
returns the index of the current number, as well as the index of the number that makes up the difference between the current number and the target.

Index out of range when traversing a single list using a nested for loop [duplicate]

This question already has answers here:
Accessing the index in 'for' loops
(26 answers)
Closed 2 years ago.
I am working through a challenge and I'm trying to use a nested for loop to solve it. The challenge asks in a given array of integers nums and an integer k, determine whether there are two distinct indices i and j in the array where nums[i] = nums[j] and the absolute difference between i and j is less than or equal to k.
This is my attempt:
def containsCloseNums(nums, k):
for i in nums:
for j in nums:
if (nums[i] == nums[j]) and abs(i-k) <= k:
return True
else:
return False
But this is the error I'm getting:
Traceback (most recent call last):
main.py3 in the pre-written template, in getUserOutputs
userOutput = _rundyxlc(testInputs[i])
main.py3 in the pre-written template, in _rundyxlc
return containsCloseNums(*_fArgs_zeutcbsrcmec)
main.py3 in the pre-written template, in containsCloseNums
if (nums[i] == nums[j]) and abs(i-j) <= k:
IndexError: list index out of range
I don't see a reason for why I'd be out of index because I'm not incrementing beyond the list's length.
I appreciate all help but since this is a challenge, it is more beneficial for me to know why my logic didn't work as opposed to just spitting out an answer.
In your code
for i in nums:
"i" is item in this list "nums".
You should change to:
for index_i, value_i in enumerate(nums):
Then "index_i" is the index of item while value_i is the value of the item in list "nums"
By the way I think it should be:
def containsCloseNums(nums, k):
for i_index, i_value in enumerate(nums):
for j_index, j_value in enumerate(nums):
if (i_value == j_value) and abs(i_index-j_index) <= k:
return True
else:
return False
For-loop traverses values in list, not indices.
L = [1, 5, 4]
for i in L:
print(i)
You will see:
1
5
4
There is enumerate function to get indices. It forms tuples of (indice, value) for each value in list:
for i, val in enumerate(L):
print(i, val)
output:
0, 1
1, 5
3, 4
Also, your solution has O(n^2) complexity which is not perfect for your task. Think if you coud use sets, dicts, or maybe make some use of sorting your list.
You should change your for loops to:
for i in range(len(nums)):
for j in range(len(nums)):
You are yielding elements instead of indices. There is an element in nums which is greater than the length of nums, that's why the error is throwed.
The problem in your code is that when you do
for i in nums
than i is an item from nums and not an index
so for comparing you can simply do
if i == j
but as you have to use indexes as well to compare with k you can do
for key, value in enumerate(nums):
where key will be the index and value will be the corresponding item.
Right now this code nums[i] and nums[j] will try accessing the ith and jth element in the list. This is what causes the error. if nums = [10, 20] and nums[10] and nums[20] do not exist.
What you want to do is to access the index of each element in the list and use that in the for loop. To access the index you can use enumerate.
I have also edited your code so that it works now.
def containsCloseNums(nums, k):
for idxi, i in enumerate(nums):
for idxj, j in enumerate(nums):
if (nums[idxi] == nums[idxj]) and abs(i-k) <= k:
return True
else:
return False

Categories