Yes, it is O(1) to pop the last element of a Python list, and O(N) to pop an arbitrary element (since the whole rest of the list has to be shifted).

Here's a great article on how Python lists are stored and manipulated: An Introduction to Python Lists.

Answer from Dan Lenski on Stack Overflow
๐ŸŒ
Python
wiki.python.org โ€บ moin โ€บ TimeComplexity
TimeComplexity - Python Wiki
The average case for an average value of k is popping the element the middle of the list, which takes O(n/2) = O(n) operations.
Discussions

What is the time complexity of pop() for the set in Python? - Stack Overflow
I know that pop the last element of the list takes O(1). And after reading this post What is the time complexity of popping elements from list in Python? I notice that if we pop an arbitrary number... More on stackoverflow.com
๐ŸŒ stackoverflow.com
algorithm - Why is the big O of pop() different from pop(0) in python - Stack Overflow
Shouldn't they both be O(1), as popping an element from any location in a Python list involves destroying that list and creating one at a new memory location? More on stackoverflow.com
๐ŸŒ stackoverflow.com
algorithm - Python list.pop(i) time complexity? - Stack Overflow
There are 161 tests, but maybe ... where complexity barely matters. Maybe the test cases have most of the numbers to be removed at the back of the list. I think people take the "percentage faster than x" stuff from Leetcode too seriously. ... @MichaelButscher: It's not "a single machine code instruction" (Python lists are much more complicated than that). But otherwise, yes, O(n) can hide huge constant multipliers; if the pop(i) solution ... More on stackoverflow.com
๐ŸŒ stackoverflow.com
Does pop(i) have a Time Complexity of O(n) or O(k)?
O(k) when k = n-1 is really the same as O(n) where time complexity is concerned. More on reddit.com
๐ŸŒ r/learnpython
3
3
July 1, 2020
๐ŸŒ
Quora
quora.com โ€บ What-is-the-time-complexity-of-the-pop-function-in-a-Python-list
What is the time complexity of the pop() function in a Python list? - Quora
Answer: Depends upon whether you pop from the end (which is the default when you pass no argument), or pop a specific position (which you can do, by passing an index number). Pop from the end is O(1) of course, but popping a specific position ...
๐ŸŒ
Runestone Academy
runestone.academy โ€บ ns โ€บ books โ€บ published โ€บ pythonds3 โ€บ AlgorithmAnalysis โ€บ Lists.html
2.6. Lists โ€” Problem Solving with Algorithms and Data Structures 3rd edition
After thinking carefully about Table 2, you may be wondering about the two different times for pop. When pop is called on the end of the list it takes \(O(1)\), but when pop is called on the first element in the listโ€”or anywhere in the middle itโ€”is \(O(n)\) The reason for this lies in how Python chooses to implement lists.
๐ŸŒ
Medium
medium.com โ€บ @shuangzizuobh2 โ€บ how-well-do-you-code-python-9bec36bbc322
How slow is python list.pop(0) ?. An empirical study on python list.popโ€ฆ | by Hj | Medium
September 27, 2023 - How slow is python list.pop(0) ? An empirical study on python list.pop complexity TL;DR Python list.pop(k) has a time complexity of O(n). Be cautious when use a python list as a Queue structure. Use โ€ฆ
๐ŸŒ
Unstop
unstop.com โ€บ home โ€บ blog โ€บ python pop() function | list & dictionaries (+code examples)
Python pop() Function | List & Dictionaries (+Code Examples)
November 11, 2024 - Python pop() operates in O(1) time complexity when used to remove the last element (i.e., when no index is specified or the index is -1).
๐ŸŒ
Medium
thinklikeacto.medium.com โ€บ time-complexity-of-popping-elements-from-list-in-python-215ad3d9c048
Time complexity of popping elements from list in Python! | by Naresh Thakur | Medium
January 23, 2020 - By doing a.pop() with no arguments it will remove and return the last element which has O(1) time complexity. Because it just remove the last element and do not need to re-arrange the elements.
Find elsewhere
๐ŸŒ
DataCamp
datacamp.com โ€บ tutorial โ€บ python-pop
How to Use the Python pop() Method | DataCamp
July 31, 2024 - The pop() method default time complexity is O(1), which is constant and efficient. Yes, the pop() method can also be applied to sets and bytearrays in Python. For sets, set.pop() removes and returns an arbitrary element, as sets are unordered.
๐ŸŒ
GoLinuxCloud
golinuxcloud.com โ€บ home โ€บ programming โ€บ python list pop() function examples [beginners]
Python list pop() function examples [Beginners] | GoLinuxCloud
January 9, 2024 - Nevertheless, those memory allocations are infrequent, and the time complexity for the append operation is referred to as amortized O(1) time. In the following table, the timings for different operations on a list of size 10,000 are shown; you ...
๐ŸŒ
DigitalOcean
digitalocean.com โ€บ community โ€บ tutorials โ€บ pop-python
How to Use `.pop()` in Python Lists and Dictionaries | DigitalOcean
July 24, 2025 - The dict.pop(key, default) method ... of raising KeyError. Internally, this performs a hash-table lookup and deletion, maintaining average-case constant time complexity (O(1))....
๐ŸŒ
GeeksforGeeks
geeksforgeeks.org โ€บ python โ€บ python-remove-rear-element-from-list
Python - Remove rear element from list - GeeksforGeeks
April 6, 2023 - # Python 3 code to demonstrate ... list is : [1, 4, 3, 6, 7] Modified list is : [1, 4, 3, 6] Time complexity: O(1) for the pop() method and O(n) for the len() method, but as n is constant, the time complexity can be considered ...
Top answer
1 of 2
3

Your algorithm genuinely does take O(n) time and the "pop in reverse order" algorithm genuinely does take O(nยฒ) time. However, LeetCode isn't reporting that your time complexity is better than 89% of submissions; it is reporting your actual running time is better than 89% of all submissions. The actual running time depends on what inputs the algorithm is tested with; not just the sizes but also the number of duplicates.

It also depends how the running times across multiple test cases are averaged; if most of the test cases are for small inputs where the quadratic solution is faster, then the quadratic solution may come out ahead overall even though its time complexity is higher. @Heap Overflow also points out in the comments that the overhead time of LeetCode's judging system is proportionally large and quite variable compared to the time it takes for the algorithms to run, so the discrepancy could simply be due to random variation in that overhead.

To shed some light on this, I measured running times using timeit. The graph below shows my results; the shapes are exactly what you'd expect given the time complexities, and the crossover point is somewhere between 8000 < n < 9000 on my machine. This is based on sorted lists where each distinct element appears on average twice. The code I used to generate the times is given below.

Timing code:

def linear_solution(nums):
    left, right = 0, 0
    while right < len(nums)-1:
        if nums[right] != nums[right+1]:
            nums[left+1]=nums[right+1]
            left += 1
        right += 1
    return left + 1

def quadratic_solution(nums):
    prev_obj = []
    for i in range(len(nums)-1,-1,-1):
        if prev_obj == nums[i]:
            nums.pop(i)
        prev_obj = nums[i]
    return len(nums)

from random import randint
from timeit import timeit

def gen_list(n):
    max_n = n // 2
    return sorted(randint(0, max_n) for i in range(n))

# I used a step size of 1000 up to 15000, then a step size of 5000 up to 50000
step = 1000
max_n = 15000
reps = 100

print('n', 'linear time (ms)', 'quadratic time (ms)', sep='\t')
for n in range(step, max_n+1, step):
    # generate input lists
    lsts1 = [ gen_list(n) for i in range(reps) ]
    # copy the lists by value, since the algorithms will mutate them
    lsts2 = [ list(g) for g in lsts1 ]
    # use iterators to supply the input lists one-by-one to timeit
    iter1 = iter(lsts1)
    iter2 = iter(lsts2)
    t1 = timeit(lambda: linear_solution(next(iter1)), number=reps)
    t2 = timeit(lambda: quadratic_solution(next(iter2)), number=reps)
    # timeit reports the total time in seconds across all reps
    print(n, 1000*t1/reps, 1000*t2/reps, sep='\t')

The conclusion is that your algorithm is indeed faster than the quadratic solution for large enough inputs, but the inputs LeetCode is using to measure running times are not "large enough" to overcome the variation in the judging overhead, and the fact that the average includes times measured on smaller inputs where the quadratic algorithm is faster.

2 of 2
-3

Just because the solution is not O(n), you can't assume it to be O(n^2).

It doesn't quite become O(n^2) because he is using pop in reverse order which decreases the time to pop every time, using pop(i) on forward order will consume more time than that on reverse, as the pop searches from reverse and in every loop he is decreasing the number of elements on the back. Try that same solution in non-reverse order, run few times to make sure, you'll see.

Anyway, regarding why his solution is faster, You have an if condition with a lot of variables, he has only used one variable prev_obj, using the reverse order makes it possible to do with just one variable. So the number of basic mathematical operations are more in your case, so with same O(n) complexity each of your n-loops is longer than his.

Just look at your count varible, in every iteration its value is left+1 you could return left+1, just removing that would decrease n amount of count=count+1 you have to do.

I just posted this solution and it is 76% faster

class Solution:
    def removeDuplicates(self, nums: List[int]) -> int:
        a=sorted(set(nums),key=lambda item:item)
        for i,v in enumerate(a):
            nums[i]=v
        return len(a)

and this one gives faster than 90%.

class Solution:
    def removeDuplicates(self, nums: List[int]) -> int:
        a ={k:1 for k in nums} #<--- this is O(n)
        for i,v in enumerate(a.keys()): #<--- this is another O(n), but the length is small so O(m)
            nums[i]=v
        return len(a)

You can say both of them are more than O(n) if you look at the for loop, But since we are working with dublicate members when I am looping over the reduced memebers while your code is looping over all memebers. So the time required to make that unique set/dict is if lesser than time required for you to loop over those extra members and to check for if conditions, then my solution can be faster.

๐ŸŒ
Finxter
blog.finxter.com โ€บ python-set-pop
Python Set pop() โ€“ Be on the Right Side of Change
April 14, 2021 - s = {'Alice', 'Bob', 'Carl', 'Liz', ... 'Bob'] print(s) # {'Ann', 'Carl'} The runtime complexity of the set.pop() function on a set with n elements is O(1)....
๐ŸŒ
Codecademy
codecademy.com โ€บ docs โ€บ python โ€บ lists โ€บ .pop()
Python | Lists | .pop() | Codecademy
May 26, 2025 - Yes, .pop() is generally more efficient than other methods like .remove() when you know the index of the element to remove. It has O(1) time complexity when removing the last element (default) and O(n) when removing from other positions due to ...
๐ŸŒ
Quora
quora.com โ€บ What-are-the-time-complexity-considerations-of-lists-in-Python
What are the time complexity considerations of lists in Python? - Quora
Answer: In a normal list on average: * Append : O(1) * Extend : O(k) - k is the length of the extension * Index : O(1) * Slice : O(k) * Sort : O(n log n) - n is the length of the list * Len : O(1) * Pop : O(1) - pop from end * Insert : O(n) ...
๐ŸŒ
Bradfield CS
bradfieldcs.com โ€บ algos โ€บ analysis โ€บ performance-of-python-types
Performance of Python Types
When pop is called from the end, the operation is ... O(n)O(n). Why the difference? When an item is taken from the front of a Python list, all other elements in the list are shifted one position closer to the beginning.
๐ŸŒ
Quora
quora.com โ€บ What-is-the-time-complexity-of-the-push-and-pop-operation-of-an-array-based-stack
What is the time complexity of the push and pop operation of an array-based stack? - Quora
In push operation you add one element ... constant time so push takes O(1). In pop operation you remove one element from the top of the stack so you make one step , so it takes constant time so push takes O(1)....