Three sum algorithm solution - python

Original Problem Statement:
Given an array S of n integers, are there elements a, b, C in S such that a + b + c = 0? Find all unique triplets in the array which gives the sum of zero.
Note: The solution set must not contain duplicate triplets.
For example, given array S = [-1, 0, 1, 2, -1, -4],
A solution set is: [[-1, 0, 1], [-1, -1, 2]]
I solved the Two Sum problem on LeetCode some time back and I thought of using it to solve the three sum as well. My idea is that for every element find two elements in the remaining list which sum up to element * -1 to get 0. However, this code doesn't pass all the test, for example
Input: [-4,-2,-2,-2,0,1,2,2,2,3,3,4,4,6,6]
Output: [[-4,-2,6],[-4,0,4],[-4,1,3],[-4,2,2]]
Expected: [[-4,-2,6],[-4,0,4],[-4,1,3],[-4,2,2],[-2,-2,4],[-2,0,2]]
I don't really know what's wrong. Can someone be kind enough to explain the problem to me.
class Solution(object):
def threeSum(self, nums):
"""
:type nums: List[int]
:rtype: List[List[int]]
"""
def twoSum(self, nums, target):
targ = target
for index, i in enumerate(nums):
targ -= i
if targ in nums[index+1:]:
return [nums[index], nums[nums[index+1:].index(targ)+index+1]]
else:
targ = target
return None
res = []
for index, i in enumerate(nums):
target = i * -1
num = nums[:index] + nums [index+1:]
ans = twoSum(self, num, target)
if ans != None:
temp = ans + [i]
temp.sort()
res.append(temp)
print(res)
import itertools
res.sort()
res = list(res for res,_ in itertools.groupby(res))
return res
Original Question: https://leetcode.com/problems/3sum/description/
The one I'm using to solve this: https://leetcode.com/problems/two-sum/description/

using itertools.
import itertools
stuff = [-1, 0, 1, 2, -1, -4]
stuff.sort()
ls = []
for subset in itertools.combinations(stuff, 3):
if sum(list(subset))==0:
# first I have sorted the list because of grouping
# Ex: [-1, 0, 1] and [0, 1, -1] are build with the same element
# so here is avoiding this.
if list(subset) not in ls:
ls.append(list(subset))
print(ls)
input/output
input : [-1, 0, 1, 2, -1, -4]
output : [[-1, -1, 2], [-1, 0, 1]]
input : [-4,-2,-2,-2,0,1,2,2,2,3,3,4,4,6,6]
output: [[-4, -2, 6], [-4, 0, 4], [-4, 1, 3], [-4, 2, 2], [-2, -2, 4], [-2, 0, 2]]

Here's another way of solving it which has O(n^2) time complexity and passes the LeetCode test. It counts the occurrences and then sorts (number, count) tuples so [-1, 0, 1, 2, -1, -4] becomes [(-4, 1), (-1, 2), (0, 1), (1, 1), (2, 1)]. Then it iterates from beginning picking first trying to pick each number twice and third greater if possible and add this to result. Then it picks number once and tries to find two greater numbers which sum to 0.
from collections import Counter
class Solution(object):
def threeSum(self, nums):
res = []
counts = Counter(nums)
num_counts = sorted(counts.items())
# Handle the only case where we pick three same nums
if counts[0] >= 3:
res.append([0] * 3)
for i, (first, first_count) in enumerate(num_counts):
# Pick two of these and one greater
if first_count >= 2 and first < 0 and -(first * 2) in counts:
res.append([first, first, -(first * 2)])
# Pick one and two greater
for j in range(i + 1, len(num_counts)):
second, second_count = num_counts[j]
# Pick two of these as second and third num
if second_count >= 2 and -first == 2 * second:
res.append([first, second, second])
# Pick this as second num and third which is greater
third = -(first + second)
if third > second and third in counts:
res.append([first, second, third])
return res

One of the approach is using the HashSet, What I have try here:
public List<List<Integer>> threeSum(int[] nums) {
Set<List<Integer>> set = new HashSet<>();
Arrays.sort(nums);
for (int i = 0; i < nums.length - 1; i++) {
int j = i + 1;
int k = nums.length - 1;
while (j < k) {
int sum = nums[i] + nums[j] + nums[k];
if (sum == 0) {
set.add(Arrays.asList(nums[i], nums[j++], nums[k--]));
} else if (sum > 0) {
k--;
} else if (sum < 0) {
j++;
}
}
}
return new ArrayList<>(set);
}
}

I'd like to add the answer you claimed(in the comment) to post:
class Solution(object):
def threeSum(self, nums):
"""
:type nums: List[int]
:rtype: List[List[int]]
"""
def twoSum(self, nums, target):
targ = target
for index, i in enumerate(nums):
targ -= i
# if targ in nums[index+1:]:
# return [nums[index], nums[nums[index+1:].index(targ)+index+1]]
_num = nums[:index] + nums[index+1:]
if targ in _num:
return [i, targ]
else:
targ = target
return None
res = []
for index, i in enumerate(nums):
target = i * -1
num = nums[:index] + nums [index+1:]
ans = twoSum(self, num, target)
if ans != None:
temp = ans + [i]
temp.sort()
res.append(temp)
print(res)
import itertools
res.sort()
res = list(res for res,_ in itertools.groupby(res))
return res
I have only run it my brain and hope it is right.

Related

Given an integer array nums, rotate the array to the right by k steps, where k is non-negative.class

class Solution:
def rotate(self, nums: List[int], k: int) -> None:
"""
Do not return anything, modify nums in-place instead.
"""
temp=[]
l=len(nums)
for i in range(l):
temp[(i+k)%l]=nums[i]
nums=temp
It is giving an error of
list assignment out of range.
What's the problem?
In Python lists don't grow automatically, so when you do temp[(i+k)%l]=nums[i] you will get this error -- the temp list is empty, so you cannot assign to any index. To make this work you should either call temp.append, or first make sure temp has all the entries before starting the loop.
However, the comment at the top of your function clearly indicates that you should perform the rotation in place, and your code is not doing that:
The last statement is not mutating the given list. Instead it changes the local name to reference another list, but the caller will still see the original list where no rotation happened.
To mutate the original list, assign to nums[:]
So -- without changing anything else -- your code can be corrected to this:
temp=[0] * len(nums) # define all indices
l = len(nums)
for i in range(l):
temp[(i+k)%l] = nums[i]
nums[:] = temp # mutate nums
Improvements
This works, but then why not first copy nums to temp, and then get values from temp storing them in the rotated position in nums. This will need one step less:
temp = nums[:]
l = len(nums)
for i in range(l):
nums[(i+k)%l] = temp[i]
You can solve this without writing a loop explicitly and without needing a name to store the rotated result:
k %= len(nums)
nums[:] = nums[-k:] + nums[:-k]
To really do this without O(n) auxiliary memory you could use the 3 x reversal technique:
class Solution:
def rotate(self, nums: List[int], k: int) -> None:
# helper function
def reverse_slice(nums, start, end):
mid = (start + end) // 2
for i, j in zip(range(start, mid), range(end - 1, mid - 1, -1)):
nums[i], nums[j] = nums[j], nums[i]
n = len(nums)
k = (n - (k % n)) % n # Express the given rotation in the opposite direction
reverse_slice(nums, 0, k)
reverse_slice(nums, k, n)
nums.reverse()
Test case: arr = [1, 2, 3, 4, 5], k = 1
const reverseArray = (arr, start, end) => {
//swapping two numbers using array destructuring
while (start < end) {
[arr[start], arr[end]] = [arr[end], arr[start]]
start++
end--
}
}
const rotate = (arr, k) => {
// Assuming k = 0, no rotation happens.
// if arr is empty then no rotation is possible.
// if the array has one element then no need to rotate.
//step 1: reverse complete(0 to arr.length - 1) array, time complexity 0(n)
//step 2: reverse 0 to k-1
//step 3: reverse k to arr.length - 1
k = k % arr.length
reverseArray(arr, 0, arr.length - 1) //[5, 4, 3, 2, 1]
reverseArray(arr, 0, k - 1) //[5, 4, 3, 2, 1]
reverseArray(arr, k, arr.length - 1) //[5, 1, 2, 3, 4]
return arr
}

The code doesn't always give correct smallest number between the largest and the smallest number that is not in the list

I have written a code that gives me minimum , maximum and smallest number between the largest and the smallest number that is not in the list.so for few uses cases I do get the correct answer For example. for lt=[2, -4, 8, -5, 9, 7] I got correct answer res=[-5, -3, 9] but for another list pt=[1, 3, -3, -2, 8, -1] is giving me res=[-3, -1, 8] instead of giving res =[-3, 0, 8].
Below is my code:
class Solution(object):
def minmax(self,nums):
nums.sort()
minimum_number = nums[0]
maximum_number = nums[-1]
res=[]
j=1
count = 0
for i in range(1,len(nums)):
while count!=1:
if minimum_number+j == nums[i]:
pass
else:
res.append(minimum_number)
res.append(minimum_number + j)
res.append(maximum_number)
count += 1
j += 1
return res
if __name__ == "__main__":
pt = [2, -4, 8, -5, 9, 7]
lt = [1, 3, -3, -2, 8, -1]
print(Solution().minmax(pt))
print(Solution().minmax(lt))
Instead of if minimum_number+j == nums[i]:
do if minimum_number+j in nums:
Also i think no need of for loop..!
Code:
class Solution(object):
def minmax(self,nums):
nums.sort()
minimum_number = nums[0]
maximum_number = nums[-1]
res=[]
j=1
count = 0
while count!=1:
if minimum_number+j in nums:
pass
else:
res.append(minimum_number)
res.append(minimum_number + j)
res.append(maximum_number)
count += 1
j += 1
return res
if __name__ == "__main__":
pt = [2, -4, 8, -5, 9, 7]
lt = [1, 3, -3, -2, 8, -1]
print(Solution().minmax(lt))
print(Solution().minmax(pt))
Output:
[-3, 0, 8]
[-5, -3, 9]
I actually have a hard time understanding what your code does. To understand why your code is failing for the second test case, it can be helpful to add some print statements, like this:
def minmax(self, nums):
nums.sort()
minimum_number = nums[0]
maximum_number = nums[-1]
res = []
j = 1
count = 0
print(f'nums = {nums}') # added debug print statement
for i in range(1, len(nums)):
print(f'i={i}') # added debug print statement
while count != 1:
print(f'i={i}, j={j}, count={count}') # added debug print statement
if minimum_number + j == nums[i]:
pass
else:
print('result defined here!') # added debug print statement
res.append(minimum_number)
res.append(minimum_number + j)
res.append(maximum_number)
count += 1
j += 1
return res
For your second test case, the output is as follows:
nums = [-3, -2, -1, 1, 3, 8]
i=1
i=1, j=1, count=0
i=1, j=2, count=0
result defined here!
i=2
i=3
i=4
i=5
So the result (variable res) is determined when i=1 and j=2, because nums[1] != minimum_number + 2 (i.e. -2 != -3 + 2). This logic seems flawed. It is probably pure luck (or bad luck) that the code gives correct results for the first testcase.
The code is supposed to find "the smallest number between the largest and the smallest number that is not in the list". So in case the smallest number is -3, you could compare the sorted list with [-3, -2, -1, 0, 1, ...] and find the first number that differs from that list. This can be done using only one index (i), which is much easier than using two indices (i and j). Also, the count variable is unneeded: you do not actually count anything, but are simply using it as a flag. Maybe you are used to such constructs from other programming languages? Using return avoids the need of such extra variables, which makes the code much shorter and clearer IMHO.
Taking the above into account would result in something like this:
class Solution:
def minmax(self, nums):
nums.sort()
for i, num in enumerate(nums):
if nums[0] + i != num:
return [nums[0], nums[0] + i, nums[-1]]
return []
The last line is not really needed, but keeps the behavior similar to your original code. If the last line is removed, the function will return None if no valid solution is found.
Another way to look at the problem is to find the first number that is not exactly 1 higher than the previous number in the list. Following that logic, the inner loop could be written like this (which gives the same result):
for i in range(len(nums) - 1):
if nums[i + 1] - nums[i] != 1:
return [nums[0], nums[i] + 1, nums[-1]]

New to Python, i am Missing an Output. goal is to find all possible outcomes from a list that sums to Zero

Problem: From a given list, i should return all possible outcomes that give a sum of 0
for a list [-1,0,1,2,-1,-4] the output should be [[-1,-1,2],[-1,0,1]]
The problem is it's not showing all possible outcomes.
Code:
nums = [-1,0,1,2,-1,-4]
def three_sum():
lst=[]
for i in nums: #take 3 variables
for j in nums:
for k in nums:
if (nums.index(i) != nums.index(j)) and (nums.index(i) != nums.index(k)) and (nums.index(j) != nums.index(k)):
if i+j+k==0:
tmp_lst=[i,j,k]
tmp_lst.sort()
lst.append(tmp_lst)
for m in lst:
while lst.count(m)>1:
lst.remove(m)
lst.sort()
return lst
The expected output should be [[-1,-1,2],[-1,0,1]] but i get [[-1, 0, 1]]
Not an answer to your question, but here's an alternative solution using itertools. The nice thing about it is that you can use it to get any combination size
import itertools
def n_sum(nums, n=3):
results = set()
for c in itertools.combinations(nums, n):
if sum(c) == 0:
results.add(tuple(sorted(c)))
return results
print(n_sum([-1,0,1,2,-1,-4], 3))
Output
{(-1, -1, 2), (-1, 0, 1)}
Or if you prefer a shorter version:
def n_sum(nums, n):
return {tuple(sorted(c)) for c in itertools.combinations(nums, n) if sum(c) == 0}
The problem is when you check (nums.index(i) != nums.index(j)) and (nums.index(i) != nums.index(k)) and (nums.index(j) != nums.index(k)), if you have two equal numbers in the list (like two -1) then nums.index will return the index of the first one and you will discard that combination.
To solve this I changed your i, j and k to be the indexes and force them to not be equal directly in the range function.
nums = [-1, 0, 1, 2, -1, -4]
def three_sum(nums):
lst = []
for i in range(len(nums)):
for j in range(i + 1, len(nums)):
for k in range(j + 1, len(nums)):
n1, n2, n3 = nums[i], nums[j], nums[k]
if n1 + n2 + n3 == 0:
tmp_lst = [n1, n2, n3]
tmp_lst.sort()
lst.append(tmp_lst)
# remove possible duplicates
for m in lst:
while lst.count(m) > 1:
lst.remove(m)
lst.sort()
return lst
print(three_sum(nums))

3SUM (finding all unique triplets in a list that equal 0)

I am working on the 3SUM problem (taken from leetcode), which takes a list as input and finds all unique triplets in the lists such that a+b+c=0. I am not really sure what my code is doing wrong, but it currently returns an empty list for this list [-1, 0, 1, 2, -1, -4], so it is not recognizing any triplets that sum to 0. I would appreciate any suggestions or improved code.
Here's my code:
result = []
nums.sort()
l = 0
r=len(nums)-1
for i in range(len(nums)-2):
while (l < r):
sum = nums[i] + nums[l] + nums[r]
if (sum < 0):
l = l + 1
if (sum > 0):
r = r - 1
if (sum == 0):
result.append([nums[i],nums[l],nums[r]])
print(result)
A couple things to note.
Don't use sum as a variable name because that's a built-in function.
Your indexing is a little problematic since you initialize l = 0 and have i begin at 0 as well.
Don't rest on your laurels: increment the value of l when you find a successful combination. It's really easy to forget this step!
An edited version of your code below.
nums = [-1, 0, 1, 2, -1, -4]
result = []
nums.sort()
r=len(nums)-1
for i in range(len(nums)-2):
l = i + 1 # we don't want l and i to be the same value.
# for each value of i, l starts one greater
# and increments from there.
while (l < r):
sum_ = nums[i] + nums[l] + nums[r]
if (sum_ < 0):
l = l + 1
if (sum_ > 0):
r = r - 1
if not sum_: # 0 is False in a boolean context
result.append([nums[i],nums[l],nums[r]])
l = l + 1 # increment l when we find a combination that works
>>> result
[[-1, -1, 2], [-1, 0, 1], [-1, 0, 1]]
If you wish, you can omit the repeats from the list.
unique_lst = []
[unique_lst.append(sublst) for sublst in result if not unique_lst.count(sublst)]
>>> unique_lst
[[-1, -1, 2], [-1, 0, 1]]
Another approach uses itertools.combinations. This doesn't require a sorted list.
from itertools import combinations
result = []
for lst in itertools.combinations(nums, 3):
if sum(lst) == 0:
result.append(lst)
A nested for loop version. Not a big fan of this approach, but it's basically the brute-force version of the itertools.combinations solution. Since it's the same as approach as above, no sort is needed.
result = []
for i in range(0, len(nums)-2):
for j in range(i + 1, len(nums)-1):
for k in range(j + 1, len(nums)):
if not sum([nums[i], nums[j], nums[k]]): # 0 is False
result.append([nums[i], nums[j], nums[k]])
Uncomment print statement from my solution:
class Solution:
def threeSum(self, nums):
"""
:type nums: List[int]
:rtype: List[List[int]]
"""
# print('Input: {}'.format(nums))
nums.sort() # inplace sorting, using only indexes
N, result = len(nums), []
# print('Sorted Input: {}'.format(nums))
for i in range(N):
if i > 0 and nums[i] == nums[i-1]:
# print("Duplicate found(when 'i' iterate ) at index: {}, current: {}, prev: {}, so JUMP this iteration------".format(i,nums[i], nums[i-1]))
continue
target = nums[i]*-1
s,e = i+1, N-1
# print('~'*50)
# print("Target: {} at index: {} & s: {} e: {} {}".format(target,i, s, e, '----'*2))
while s<e: # for each target squeeze in s & e
if nums[s]+nums[e] == target:
result.append([nums[i], nums[s], nums[e]])
# print(' {} + {} == {}, with s: {} < e: {}, Triplet: {}, MOVING --> R'.format(nums[s], nums[e], target,s, e,result))
s = s+1
while s<e and nums[s] == nums[s-1]: # duplicate
# print("Duplicate found(when 's' iterates) at s: {} < e: {}, WILL KEEP MOVING ---> R (s: {}) == (s-1: {})".format(s, e, nums[s], nums[s - 1]))
s = s+1
elif nums[s] + nums[e] < target:
# print(' {} + {} < {}, with s: {} e: {}, MOVING ---> R'.format(nums[s], nums[e], target,s, e))
s = s+1
else:
# print(' {} + {} > {}, with s: {} e: {}, MOVING <--- L'.format(nums[s], nums[e], target,s, e))
e = e-1
return result
It will help you to understand the algorithm better. Also, this algorithm is 3 times faster than the above available options. It takes ~892.18 ms compared to the above alternative with runs in ~4216.98 ms time. The overhead is because of the additional removal of duplicates logic.
I did a similar approach as 3novak, but I added in the case where the number list is less than three integers returning an empty list.
class Solution:
def threeSum(self, nums):
"""
:type nums: List[int]
:rtype: List[List[int]]
"""
# if less than three numbers, don't bother searching
if len(nums) < 3:
return []
# sort nums and use current sum to see if should have larger number or smaller number
nums = sorted(nums)
triplets = []
for i in range(len(nums)-2): # i point to first number to sum in list
j = i + 1 # j points to middle number to sum in list
k = len(nums) - 1 # k points to last number to sum in list
while j < k:
currSum = nums[i] + nums[j] + nums[k]
if currSum == 0:
tmpList = sorted([nums[i], nums[j], nums[k]])
if tmpList not in triplets:
triplets.append(tmpList)
j += 1 # go to next number to avoid infinite loop
# sum too large, so move k to smaller number
elif currSum > 0:
k -= 1
# sum too small so move j to larger number
elif currSum < 0:
j += 1
return triplets
I'm doing the same problem at leetcode, but still have a runtime error. This may be able to be done by using a binary search tree-like algorithm to find the third result, as well.
Using two pointer approach:
First sort the list.
Iterate from left to right. Say current position is i, set left side position as i+1, and set the right end as the end of the list N-1.
If the sum is greater than 0, decrease the right end by 1.
else if, the sum is less than 0, increase the left end by 1,
else, check the uniqueness of the new entry and if it is unique add it to answer list. Continue search for more entry with leftEnd++, rightEnd--.
Java Code:
public ArrayList<ArrayList<Integer>> threeSum(ArrayList<Integer> A) {
ArrayList<ArrayList<Integer>> ans = new ArrayList<ArrayList<Integer>>();
Collections.sort(A); // takes O(nlogn)
if (A.size() < 3) return ans;
ArrayList<Integer> triplet = new ArrayList<>();
for(int i = 0; i < A.size()-3; i++){ // takes O(n^2)
if (i > 0 && A.get(i) == A.get(i-1)) continue; // to maintain unique entries
int r = A.size()-1;
int l = i+1;
while (l < r){
int s = sumOfThree(A, i, l, r);
if (s == 0){
if (ans.size() == 0 || !bTripletExists(A, i, l, r, triplet)){
triplet = getNewTriplet(A, i, l, r); // to be matched against next triplet
ans.add(triplet);
}
l++;
r--;
}else if (s > 0){
r--;
}else {
l++;
}
}
}
return ans;
}
public int sumOfThree(ArrayList<Integer> A, int i, int j, int k){
return A.get(i)+A.get(j)+A.get(k);
}
public ArrayList<Integer> getNewTriplet(ArrayList<Integer> A, int i, int j, int k){
ArrayList<Integer> newTriplet = new ArrayList<>();
newTriplet.add(A.get(i));
newTriplet.add(A.get(j));
newTriplet.add(A.get(k));
return newTriplet;
}
public boolean bTripletExists(ArrayList<Integer> A, int i, int j, int k, ArrayList<Integer> triplet){
if (A.get(i).equals(triplet.get(0)) &&
A.get(j).equals(triplet.get(1)) &&
A.get(k).equals(triplet.get(2)))
return true;
return false;
}
Most of the answers given above are great but fails some edge cases on leetcode.
I added a few more checks to pass all the test cases
class Solution:
def threeSum(self, nums: List[int]) -> List[List[int]]:
# if the list has less than 3 elements
if len(nums)<3:
return []
# if nums is just zeroes return just one zeroes pair
elif sum([i**2 for i in nums]) == 0:
return [[0,0,0]]
nums.sort()
result = []
for i in range(len(nums)):
#duplicate skip it
if i > 0 and nums[i]== nums[i-1]:
continue
# left pointer starts next to current i item
l = i+1
r = len(nums)-1
while l< r:
summ = nums[l] + nums[r]
# if we find 2 numbers that sums up to -item
if summ == -nums[i]:
result.append([nums[i],nums[l],nums[r]])
l +=1
# duplicate skip it
while l<r and nums[l] == nums[l-1]:
l +=1
# if the sum is smaller than 0 we move left pointer forward
elif summ + nums[i] < 0:
l +=1
# if the sum is bigger than 0 move the right pointer backward
else:
r -=1
return result

How do I improve remove duplicate algorithm?

My interview question was that I need to return the length of an array that removed duplicates but we can leave at most 2 duplicates.
For example, [1, 1, 1, 2, 2, 3] the new array would be [1, 1, 2, 2, 3]. So the new length would be 5. I came up with an algorithm with O(2n) I believe. How can I improve that to be the fastest.
def removeDuplicates(nums):
if nums is None:
return 0
if len(nums) == 0:
return 0
if len(nums) == 1:
return 1
new_array = {}
for num in nums:
new_array[num] = new_array.get(num, 0) + 1
new_length = 0
for key in new_array:
if new_array[key] > 2:
new_length = new_length + 2
else:
new_length = new_length + new_array[key]
return new_length
new_length = removeDuplicates([1, 1, 1, 2, 2, 3])
assert new_length == 5
My first question would be is my algorithm even correct?
Your logic is correct however he is a simpler method to reach the goal you had mentioned in your question.
Here is my logic.
myl = [1, 1, 1, 2, 2, 3, 1, 1, 1, 2, 2, 3, 1, 1, 1, 2, 2, 3]
newl = []
for i in myl:
if newl.count(i) != 2:
newl.append(i)
print newl
[1, 1, 2, 2, 3, 3]
Hope this helps.
If your original array size is n.
Count distinct numbers in your array.
If you have d distinct numbers, then your answer will be
d (when n == d)
d+1 (when n == d+1)
d+2 (when n >= d+2)
If all the numbers in your array are less than n-1, you can even solve this without using any extra space. If that's the case check this and you can count distinct numbers very easily without using extra space.
I'd forget about generating the new array and just focus on counting:
from collections import Counter
def count_non_2dups(nums):
new_len = 0
for num, count in Counter(nums).items():
new_len += min(2, count)
return new_len
int removeDuplicates(vector<int>& nums) {
if (nums.size() == 0) return nums.size();
int state = 1;
int idx = 1;
for (int i = 1; i < nums.size(); ++i) {
if (nums[i] != nums[i-1]) {
state = 1;
nums[idx++] = nums[i];
}
else if (state == 1) {
state++;
nums[idx++] = nums[i];
}
else {
state++;
}
}
return idx;
}
idea:maintain a variable(state) recording the current repeat times(more precisely, state records the repeat times of the element which adjacent to the left of current element). This algorithm is O(n) with one scanning of the array.
def removeDuplicates(nums):
if nums is None:
return 0
if len(nums) == 0:
return 0
if len(nums) == 1:
return 1
new_array_a = set()
new_array_b = set()
while nums:
i = nums.pop()
if i not in new_array_a:
new_array_a.add(i)
elif i not in new_array_b:
new_array_b.add(i)
return len(new_array_a) + len(new_array_b)

Categories