有没有方法/算法可以减小下面代码的时间复杂度?

huangapple go评论55阅读模式
英文:

Is there any method/algorithm to reduce time complexity of below code?

问题

Here's the translated code portion:

class Solution:
    def removeElement(self, nums: List[int], val: int) -> int:
        l = 0
        for i in range(len(nums)):
            if nums[i] == val:
                nums[i] = 1000
                l += 1
        nums.sort()
        return len(nums) - l

Regarding your question about reducing time complexity, the provided code has a time complexity of O(n log n) due to the sorting operation. You can improve the time complexity to O(n) by using a two-pointer approach. Here's an optimized version of the code:

class Solution:
    def removeElement(self, nums: List[int], val: int) -> int:
        k = 0  # Initialize a counter for elements not equal to val
        
        # Iterate through the list
        for i in range(len(nums)):
            if nums[i] != val:
                nums[k] = nums[i]  # Move non-val elements to the front
                k += 1
        
        return k

This version has a time complexity of O(n) since it iterates through the list once and moves non-val elements to the front, avoiding the need for sorting.

英文:
class Solution:
    def removeElement(self, nums: List[int], val: int) -> int:
        l=0
        for i in range(len(nums)):
            if nums[i]==val:
                nums[i]=1000
                l+=1
        nums.sort()
        return len(nums)-l

problem:
Given an integer array nums and an integer val, remove all occurrences of val in nums in-place. The order of the elements may be changed. Then return the number of elements in nums which are not equal to val.

Consider the number of elements in nums which are not equal to val be k, to get accepted, you need to do the following things:

Change the array nums such that the first k elements of nums contain the elements which are not equal to val. The remaining elements of nums are not important as well as the size of nums.
Return k.

CONSTRAINTS:
0 \<= nums.length \<= 100
0 \<= nums\[i\] \<= 50
0 \<= val \<= 100

I tried to solve this using constraints,setting val=1000 and then sorting list and returning the number k.Is there any way to reduce time complexity of above code?

答案1

得分: 2

这可以通过在应该写入不同于 val 的值的索引处进行跟踪,只在出现不同于 val 的值时递增该索引来在线性时间内解决:

def removeElement(nums, val):
    write_index = 0
    for v in nums:
        if v != val:
            nums[write_index] = v
            write_index += 1
    return write_index

因此:

nums = [1, 2, 1, 0, 4]
print(removeElement(nums, 1))
print(nums)

输出:

3
[2, 0, 4, 0, 4]

请注意,正如问题所述,输出列表末尾的 04 可以忽略。

英文:

This can be solved in linear time by keeping track of an index at which a value that is different from val should be written, and only incrementing that index when a value different from val occurs:

def removeElement(nums, val):
    write_index = 0
    for v in nums:
        if v != val:
            nums[write_index] = v
            write_index += 1
    return write_index

so that:

nums = [1, 2, 1, 0, 4]
print(removeElement(nums, 1))
print(nums)

outputs:

3
[2, 0, 4, 0, 4]

Note that as the question states, only the first 3 items of the output are important, so the 0 and 4 at the end of the output list can be ignored.

答案2

得分: 1

@blhsing提供了一个优雅的原地解决方案。稍微粗暴一点的方法是切片赋值,但更简洁、仍然是原地操作,并且符合规范(nums的大小无关紧要):

def removeElement(nums, val):
    nums[:] = filter(val.__ne__, nums)
    return len(nums)

您可以使用其他一些工具来绕过dunder方法,同时仍然保持在函数式范式中:

from functools import partial
from operator import ne

def removeElement(nums, val):
    nums[:] = filter(partial(ne, val), nums)
    return len(nums)

或者,为了避免显式使用dunder方法,可以在右侧使用任何可迭代对象,因此您可以在那里使用推导式或生成器表达式:

def removeElement(nums, val):
    nums[:] = (n for n in nums if n != val) 
    return len(nums)

了解这个模式肯定比前面的代码高手方法更普遍有用和有教育意义。

英文:

@blhsing has you covered with an elegant in-place solution. A bit more brutish would be slice-assignment, yet more concise, still linear, in-place, and according to spec (size of nums doesn't matter):

def removeElement(nums, val):
    nums[:] = filter(val.__ne__, nums)
    return len(nums)

You could use use some other utils to work around the dunder while still staying in the functional paradigm:

from functools import partial
from operator import ne

def removeElement(nums, val):
    nums[:] = filter(partial(ne, val), nums)
    return len(nums)

Alternatively, in order to avoid the explicit use of a dunder method, this works with any iterable on the right hand side, so you can use a comprehension or generator expression there:

def removeElement(nums, val):
    nums[:] = (n for n in nums if n != val) 
    return len(nums)

Knowing this pattern is certainly more universally useful and educational than the former code-golfing approach.

答案3

得分: 0

你可以沿着列表向后遍历并删除匹配的数字位置:

def removeElement(nums, val):
    for i in range(len(nums) - 1, -1, -1):
        if nums[i] == val:
            del nums[i]
    return len(nums)

输出:

A = [2, 1, 6, 5, 5, 6, 7, 7, 4, 3]

print(removeElement(A, 6))
print(A)

8
[2, 1, 5, 5, 7, 7, 4, 3]

从列表中删除项目并不是一个O(1)的操作,因此这不是一个线性时间的解决方案。为了解决这个问题,你可以将要删除的项目与末尾位置进行交换:

def removeElement(nums, val):
    k = len(nums)
    for i in range(k - 1, -1, -1):
        if nums[i] == val:
            k -= 1
            nums[i], nums[k] = nums[k], nums[i]
    return k

输出:

A = [2, 1, 6, 5, 5, 6, 7, 7, 4, 3]

print(removeElement(A, 6))
print(A)
8
[2, 1, 4, 5, 5, 3, 7, 7, 6, 6]
英文:

You can proceed backward through the list end delete positions as you find matching numbers:

def removeElement(nums,val):
    for i in range(len(nums)-1,-1,-1):
        if nums[i] == val:
            del nums[i]
    return len(nums)

output:

A = [2, 1, 6, 5, 5, 6, 7, 7, 4, 3]

print(removeElement(A,6))
print(A)

8
[2, 1, 5, 5, 7, 7, 4, 3]

Deleting items from a list isn't really an O(1) operation so this would not be a linear time solution. To work around that, you could just swap the items to remove with the ending positions:

def removeElement(nums,val):
    k = len(nums)
    for i in range(k-1,-1,-1):
        if nums[i] == val:
            k -= 1
            nums[i],nums[k] = nums[k],nums[i]
    return k

output:

A = [2, 1, 6, 5, 5, 6, 7, 7, 4, 3]

print(removeElement(A,6))
print(A)
8
[2, 1, 4, 5, 5, 3, 7, 7, 6, 6]

答案4

得分: -1

如果您想返回与val不相等的元素数量,无需转换您正在使用的列表。您所展示的代码在本地范围内使用了一个列表,该列表从未被返回。如果您需要在全局范围内修改该列表,您需要返回它。根据您的代码和描述,一个更好的方法是...

class Solution:
    def removeElement(self, nums: List[int], val: int) -> int:
        return len([num for num in nums if num != val])

此代码将返回列表中与val不同的值的数量。如果您想要返回该列表以在外部范围中使用它。

class Solution:
    def removeElement(self, nums: List[int], val: int) -> int:
        non_equal_list = [num for num in nums if num != val]
        non_equal_list.sort()
        return len(non_equal_list), non_equal_list
英文:

If you wan to return the number of elements in nums which are not equal to val, you don't need to transform the list you are using. The code you have shown is using a list in a local scope that never get's returned. If you need to modify that list in a global scope, you need to return it. Following your code and description, a better way would be...

class Solution:
    def removeElement(self, nums: List[int], val: int) -> int:
        return len([num for num in nums if num != val])

This code will return the number of values that are different from val inside the list. If you want to return the list to use it in outter scope.

class Solution:
    def removeElement(self, nums: List[int], val: int) -> int:
        non_equal_list = [num for num in nums if num != val]
        non_equal_list.sort()
        return len(non_equal_list), non_equal_list

huangapple
  • 本文由 发表于 2023年6月6日 15:08:43
  • 转载请务必保留本文链接:https://go.coder-hub.com/76412197.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定