Find the first missing positive integer in PythonCalling an external command in PythonWhat are metaclasses in Python?What is the difference between @staticmethod and @classmethod?Finding the index of an item given a list containing it in PythonDifference between append vs. extend list methods in PythonHow can I safely create a nested directory in Python?Does Python have a ternary conditional operator?How to get the current time in PythonConverting integer to string in Python?Does Python have a string 'contains' substring method?
Offset in split text content
"Marked down as someone wanting to sell shares." What does that mean?
Why do Radio Buttons not fill the entire outer circle?
How would a solely written language work mechanically
Why does the frost depth increase when the surface temperature warms up?
Output visual diagram of picture
Relations between homogeneous polynomials
Should I be concerned about student access to a test bank?
Hashing password to increase entropy
C++ lambda syntax
Do native speakers use "ultima" and "proxima" frequently in spoken English?
Put the phone down / Put down the phone
How to get directions in deep space?
1 John in Luther’s Bibel
How to split IPA spelling into syllables
How can a new country break out from a developed country without war?
Can you describe someone as luxurious? As in someone who likes luxurious things?
Trouble reading roman numeral notation with flats
How do you say "Trust your struggle." in French?
Has the laser at Magurele, Romania reached the tenth of the Sun power?
Derivative of an interpolated function
Taking the numerator and the denominator
Why would five hundred and five same as one?
"Oh no!" in Latin
Find the first missing positive integer in Python
Calling an external command in PythonWhat are metaclasses in Python?What is the difference between @staticmethod and @classmethod?Finding the index of an item given a list containing it in PythonDifference between append vs. extend list methods in PythonHow can I safely create a nested directory in Python?Does Python have a ternary conditional operator?How to get the current time in PythonConverting integer to string in Python?Does Python have a string 'contains' substring method?
I have the following task:
Given an unsorted integer array, find the first missing positive integer. Your algorithm should run in O(n) time and use constant space.
After thinking and getting a hint, I decided to change the input list A. The following is the code:
def firstMissingPositive(A):
m=max(A)
ln=len(A)
i=0
while i<ln:
if A[i]>=1 and A[i]<=ln:
if A[A[i]-1]!=m+1:
A[A[i]-1], A[i] = m+1, A[A[i]-1]
else:
i+=1
else:
i+=1
for i in range(ln):
if A[i]!=m+1:
return i+1
When I run it, it takes a long time. What shall I do to make it a bit faster?
EDIT: here is the list A.
A=[ 417, 929, 845, 462, 675, 175, 73, 867, 14, 201, 777, 407, 80, 882, 785, 563, 209, 261, 776, 362, 730, 74, 649, 465, 353, 801, 503, 154, 998, 286, 520, 692, 68, 805, 835, 210, 819, 341, 564, 215, 984, 643, 381, 793, 726, 213, 866, 706, 97, 538, 308, 797, 883, 59, 328, 743, 694, 607, 729, 821, 32, 672, 130, 13, 76, 724, 384, 444, 884, 192, 917, 75, 551, 96, 418, 840, 235, 433, 290, 954, 549, 950, 21, 711, 781, 132, 296, 44, 439, 164, 401, 505, 923, 136, 317, 548, 787, 224, 23, 185, 6, 350, 822, 457, 489, 133, 31, 830, 386, 671, 999, 255, 222, 944, 952, 637, 523, 494, 916, 95, 734, 908, 90, 541, 470, 941, 876, 264, 880, 761, 535, 738, 128, 772, 39, 553, 656, 603, 868, 292, 117, 966, 259, 619, 836, 818, 493, 592, 380, 500, 599, 839, 268, 67, 591, 126, 773, 635, 800, 842, 536, 668, 896, 260, 664, 506, 280, 435, 618, 398, 533, 647, 373, 713, 745, 478, 129, 844, 640, 886, 972, 62, 636, 79, 600, 263, 52, 719, 665, 376, 351, 623, 276, 66, 316, 813, 663, 831, 160, 237, 567, 928, 543, 508, 638, 487, 234, 997, 307, 480, 620, 890, 216, 147, 271, 989, 872, 994, 488, 291, 331, 8, 769, 481, 924, 166, 89, 824, -4, 590, 416, 17, 814, 728, 18, 673, 662, 410, 727, 667, 631, 660, 625, 683, 33, 436, 930, 91, 141, 948, 138, 113, 253, 56, 432, 744, 302, 211, 262, 968, 945, 396, 240, 594, 684, 958, 343, 879, 155, 395, 288, 550, 482, 557, 826, 598, 795, 914, 892, 690, 964, 981, 150, 179, 515, 205, 265, 823, 799, 190, 236, 24, 498, 229, 420, 753, 936, 191, 366, 935, 434, 311, 920, 167, 817, 220, 219, 741, -2, 674, 330, 909, 162, 443, 412, 974, 294, 864, 971, 760, 225, 681, 689, 608, 931, 427, 687, 466, 894, 303, 390, 242, 339, 252, 20, 218, 499, 232, 184, 490, 4, 957, 597, 477, 354, 677, 691, 25, 580, 897, 542, 186, 359, 346, 409, 655, 979, 853, 411, 344, 358, 559, 765, 383, 484, 181, 82, 514, 582, 593, 77, 228, 921, 348, 453, 274, 449, 106, 657, 783, 782, 811, 333, 305, 784, 581, 746, 858, 249, 479, 652, 270, 429, 614, 903, 102, 378, 575, 119, 196, 12, 990, 356, 277, 169, 70, 518, 282, 676, 137, 622, 616, 357, 913, 161, 3, 589, 327 ]
python
|
show 4 more comments
I have the following task:
Given an unsorted integer array, find the first missing positive integer. Your algorithm should run in O(n) time and use constant space.
After thinking and getting a hint, I decided to change the input list A. The following is the code:
def firstMissingPositive(A):
m=max(A)
ln=len(A)
i=0
while i<ln:
if A[i]>=1 and A[i]<=ln:
if A[A[i]-1]!=m+1:
A[A[i]-1], A[i] = m+1, A[A[i]-1]
else:
i+=1
else:
i+=1
for i in range(ln):
if A[i]!=m+1:
return i+1
When I run it, it takes a long time. What shall I do to make it a bit faster?
EDIT: here is the list A.
A=[ 417, 929, 845, 462, 675, 175, 73, 867, 14, 201, 777, 407, 80, 882, 785, 563, 209, 261, 776, 362, 730, 74, 649, 465, 353, 801, 503, 154, 998, 286, 520, 692, 68, 805, 835, 210, 819, 341, 564, 215, 984, 643, 381, 793, 726, 213, 866, 706, 97, 538, 308, 797, 883, 59, 328, 743, 694, 607, 729, 821, 32, 672, 130, 13, 76, 724, 384, 444, 884, 192, 917, 75, 551, 96, 418, 840, 235, 433, 290, 954, 549, 950, 21, 711, 781, 132, 296, 44, 439, 164, 401, 505, 923, 136, 317, 548, 787, 224, 23, 185, 6, 350, 822, 457, 489, 133, 31, 830, 386, 671, 999, 255, 222, 944, 952, 637, 523, 494, 916, 95, 734, 908, 90, 541, 470, 941, 876, 264, 880, 761, 535, 738, 128, 772, 39, 553, 656, 603, 868, 292, 117, 966, 259, 619, 836, 818, 493, 592, 380, 500, 599, 839, 268, 67, 591, 126, 773, 635, 800, 842, 536, 668, 896, 260, 664, 506, 280, 435, 618, 398, 533, 647, 373, 713, 745, 478, 129, 844, 640, 886, 972, 62, 636, 79, 600, 263, 52, 719, 665, 376, 351, 623, 276, 66, 316, 813, 663, 831, 160, 237, 567, 928, 543, 508, 638, 487, 234, 997, 307, 480, 620, 890, 216, 147, 271, 989, 872, 994, 488, 291, 331, 8, 769, 481, 924, 166, 89, 824, -4, 590, 416, 17, 814, 728, 18, 673, 662, 410, 727, 667, 631, 660, 625, 683, 33, 436, 930, 91, 141, 948, 138, 113, 253, 56, 432, 744, 302, 211, 262, 968, 945, 396, 240, 594, 684, 958, 343, 879, 155, 395, 288, 550, 482, 557, 826, 598, 795, 914, 892, 690, 964, 981, 150, 179, 515, 205, 265, 823, 799, 190, 236, 24, 498, 229, 420, 753, 936, 191, 366, 935, 434, 311, 920, 167, 817, 220, 219, 741, -2, 674, 330, 909, 162, 443, 412, 974, 294, 864, 971, 760, 225, 681, 689, 608, 931, 427, 687, 466, 894, 303, 390, 242, 339, 252, 20, 218, 499, 232, 184, 490, 4, 957, 597, 477, 354, 677, 691, 25, 580, 897, 542, 186, 359, 346, 409, 655, 979, 853, 411, 344, 358, 559, 765, 383, 484, 181, 82, 514, 582, 593, 77, 228, 921, 348, 453, 274, 449, 106, 657, 783, 782, 811, 333, 305, 784, 581, 746, 858, 249, 479, 652, 270, 429, 614, 903, 102, 378, 575, 119, 196, 12, 990, 356, 277, 169, 70, 518, 282, 676, 137, 622, 616, 357, 913, 161, 3, 589, 327 ]
python
Can you not usedsort
orsorted
?
– Eli Sadoff
Dec 10 '16 at 1:38
2
OP mentioned "should run in O(n)".
– Robᵩ
Dec 10 '16 at 1:38
What else do we know about the array? Is there a missing positive integer? Is there only one? Are there duplicate values?
– Robᵩ
Dec 10 '16 at 1:39
If the input known to be non-negative? If it's something like a shuffled range from 0 to n, with a single number removed, this is trivial, but you need to be more clear on the known qualities of the input.
– ShadowRanger
Dec 10 '16 at 1:43
1
I'd start by addingprint("Swapping %d"%i)
in the swap branch of theif
. What do you learn from its output?
– Robᵩ
Dec 10 '16 at 1:45
|
show 4 more comments
I have the following task:
Given an unsorted integer array, find the first missing positive integer. Your algorithm should run in O(n) time and use constant space.
After thinking and getting a hint, I decided to change the input list A. The following is the code:
def firstMissingPositive(A):
m=max(A)
ln=len(A)
i=0
while i<ln:
if A[i]>=1 and A[i]<=ln:
if A[A[i]-1]!=m+1:
A[A[i]-1], A[i] = m+1, A[A[i]-1]
else:
i+=1
else:
i+=1
for i in range(ln):
if A[i]!=m+1:
return i+1
When I run it, it takes a long time. What shall I do to make it a bit faster?
EDIT: here is the list A.
A=[ 417, 929, 845, 462, 675, 175, 73, 867, 14, 201, 777, 407, 80, 882, 785, 563, 209, 261, 776, 362, 730, 74, 649, 465, 353, 801, 503, 154, 998, 286, 520, 692, 68, 805, 835, 210, 819, 341, 564, 215, 984, 643, 381, 793, 726, 213, 866, 706, 97, 538, 308, 797, 883, 59, 328, 743, 694, 607, 729, 821, 32, 672, 130, 13, 76, 724, 384, 444, 884, 192, 917, 75, 551, 96, 418, 840, 235, 433, 290, 954, 549, 950, 21, 711, 781, 132, 296, 44, 439, 164, 401, 505, 923, 136, 317, 548, 787, 224, 23, 185, 6, 350, 822, 457, 489, 133, 31, 830, 386, 671, 999, 255, 222, 944, 952, 637, 523, 494, 916, 95, 734, 908, 90, 541, 470, 941, 876, 264, 880, 761, 535, 738, 128, 772, 39, 553, 656, 603, 868, 292, 117, 966, 259, 619, 836, 818, 493, 592, 380, 500, 599, 839, 268, 67, 591, 126, 773, 635, 800, 842, 536, 668, 896, 260, 664, 506, 280, 435, 618, 398, 533, 647, 373, 713, 745, 478, 129, 844, 640, 886, 972, 62, 636, 79, 600, 263, 52, 719, 665, 376, 351, 623, 276, 66, 316, 813, 663, 831, 160, 237, 567, 928, 543, 508, 638, 487, 234, 997, 307, 480, 620, 890, 216, 147, 271, 989, 872, 994, 488, 291, 331, 8, 769, 481, 924, 166, 89, 824, -4, 590, 416, 17, 814, 728, 18, 673, 662, 410, 727, 667, 631, 660, 625, 683, 33, 436, 930, 91, 141, 948, 138, 113, 253, 56, 432, 744, 302, 211, 262, 968, 945, 396, 240, 594, 684, 958, 343, 879, 155, 395, 288, 550, 482, 557, 826, 598, 795, 914, 892, 690, 964, 981, 150, 179, 515, 205, 265, 823, 799, 190, 236, 24, 498, 229, 420, 753, 936, 191, 366, 935, 434, 311, 920, 167, 817, 220, 219, 741, -2, 674, 330, 909, 162, 443, 412, 974, 294, 864, 971, 760, 225, 681, 689, 608, 931, 427, 687, 466, 894, 303, 390, 242, 339, 252, 20, 218, 499, 232, 184, 490, 4, 957, 597, 477, 354, 677, 691, 25, 580, 897, 542, 186, 359, 346, 409, 655, 979, 853, 411, 344, 358, 559, 765, 383, 484, 181, 82, 514, 582, 593, 77, 228, 921, 348, 453, 274, 449, 106, 657, 783, 782, 811, 333, 305, 784, 581, 746, 858, 249, 479, 652, 270, 429, 614, 903, 102, 378, 575, 119, 196, 12, 990, 356, 277, 169, 70, 518, 282, 676, 137, 622, 616, 357, 913, 161, 3, 589, 327 ]
python
I have the following task:
Given an unsorted integer array, find the first missing positive integer. Your algorithm should run in O(n) time and use constant space.
After thinking and getting a hint, I decided to change the input list A. The following is the code:
def firstMissingPositive(A):
m=max(A)
ln=len(A)
i=0
while i<ln:
if A[i]>=1 and A[i]<=ln:
if A[A[i]-1]!=m+1:
A[A[i]-1], A[i] = m+1, A[A[i]-1]
else:
i+=1
else:
i+=1
for i in range(ln):
if A[i]!=m+1:
return i+1
When I run it, it takes a long time. What shall I do to make it a bit faster?
EDIT: here is the list A.
A=[ 417, 929, 845, 462, 675, 175, 73, 867, 14, 201, 777, 407, 80, 882, 785, 563, 209, 261, 776, 362, 730, 74, 649, 465, 353, 801, 503, 154, 998, 286, 520, 692, 68, 805, 835, 210, 819, 341, 564, 215, 984, 643, 381, 793, 726, 213, 866, 706, 97, 538, 308, 797, 883, 59, 328, 743, 694, 607, 729, 821, 32, 672, 130, 13, 76, 724, 384, 444, 884, 192, 917, 75, 551, 96, 418, 840, 235, 433, 290, 954, 549, 950, 21, 711, 781, 132, 296, 44, 439, 164, 401, 505, 923, 136, 317, 548, 787, 224, 23, 185, 6, 350, 822, 457, 489, 133, 31, 830, 386, 671, 999, 255, 222, 944, 952, 637, 523, 494, 916, 95, 734, 908, 90, 541, 470, 941, 876, 264, 880, 761, 535, 738, 128, 772, 39, 553, 656, 603, 868, 292, 117, 966, 259, 619, 836, 818, 493, 592, 380, 500, 599, 839, 268, 67, 591, 126, 773, 635, 800, 842, 536, 668, 896, 260, 664, 506, 280, 435, 618, 398, 533, 647, 373, 713, 745, 478, 129, 844, 640, 886, 972, 62, 636, 79, 600, 263, 52, 719, 665, 376, 351, 623, 276, 66, 316, 813, 663, 831, 160, 237, 567, 928, 543, 508, 638, 487, 234, 997, 307, 480, 620, 890, 216, 147, 271, 989, 872, 994, 488, 291, 331, 8, 769, 481, 924, 166, 89, 824, -4, 590, 416, 17, 814, 728, 18, 673, 662, 410, 727, 667, 631, 660, 625, 683, 33, 436, 930, 91, 141, 948, 138, 113, 253, 56, 432, 744, 302, 211, 262, 968, 945, 396, 240, 594, 684, 958, 343, 879, 155, 395, 288, 550, 482, 557, 826, 598, 795, 914, 892, 690, 964, 981, 150, 179, 515, 205, 265, 823, 799, 190, 236, 24, 498, 229, 420, 753, 936, 191, 366, 935, 434, 311, 920, 167, 817, 220, 219, 741, -2, 674, 330, 909, 162, 443, 412, 974, 294, 864, 971, 760, 225, 681, 689, 608, 931, 427, 687, 466, 894, 303, 390, 242, 339, 252, 20, 218, 499, 232, 184, 490, 4, 957, 597, 477, 354, 677, 691, 25, 580, 897, 542, 186, 359, 346, 409, 655, 979, 853, 411, 344, 358, 559, 765, 383, 484, 181, 82, 514, 582, 593, 77, 228, 921, 348, 453, 274, 449, 106, 657, 783, 782, 811, 333, 305, 784, 581, 746, 858, 249, 479, 652, 270, 429, 614, 903, 102, 378, 575, 119, 196, 12, 990, 356, 277, 169, 70, 518, 282, 676, 137, 622, 616, 357, 913, 161, 3, 589, 327 ]
python
python
edited Dec 10 '16 at 3:23
highsky
asked Dec 10 '16 at 1:36
highskyhighsky
457
457
Can you not usedsort
orsorted
?
– Eli Sadoff
Dec 10 '16 at 1:38
2
OP mentioned "should run in O(n)".
– Robᵩ
Dec 10 '16 at 1:38
What else do we know about the array? Is there a missing positive integer? Is there only one? Are there duplicate values?
– Robᵩ
Dec 10 '16 at 1:39
If the input known to be non-negative? If it's something like a shuffled range from 0 to n, with a single number removed, this is trivial, but you need to be more clear on the known qualities of the input.
– ShadowRanger
Dec 10 '16 at 1:43
1
I'd start by addingprint("Swapping %d"%i)
in the swap branch of theif
. What do you learn from its output?
– Robᵩ
Dec 10 '16 at 1:45
|
show 4 more comments
Can you not usedsort
orsorted
?
– Eli Sadoff
Dec 10 '16 at 1:38
2
OP mentioned "should run in O(n)".
– Robᵩ
Dec 10 '16 at 1:38
What else do we know about the array? Is there a missing positive integer? Is there only one? Are there duplicate values?
– Robᵩ
Dec 10 '16 at 1:39
If the input known to be non-negative? If it's something like a shuffled range from 0 to n, with a single number removed, this is trivial, but you need to be more clear on the known qualities of the input.
– ShadowRanger
Dec 10 '16 at 1:43
1
I'd start by addingprint("Swapping %d"%i)
in the swap branch of theif
. What do you learn from its output?
– Robᵩ
Dec 10 '16 at 1:45
Can you not used
sort
or sorted
?– Eli Sadoff
Dec 10 '16 at 1:38
Can you not used
sort
or sorted
?– Eli Sadoff
Dec 10 '16 at 1:38
2
2
OP mentioned "should run in O(n)".
– Robᵩ
Dec 10 '16 at 1:38
OP mentioned "should run in O(n)".
– Robᵩ
Dec 10 '16 at 1:38
What else do we know about the array? Is there a missing positive integer? Is there only one? Are there duplicate values?
– Robᵩ
Dec 10 '16 at 1:39
What else do we know about the array? Is there a missing positive integer? Is there only one? Are there duplicate values?
– Robᵩ
Dec 10 '16 at 1:39
If the input known to be non-negative? If it's something like a shuffled range from 0 to n, with a single number removed, this is trivial, but you need to be more clear on the known qualities of the input.
– ShadowRanger
Dec 10 '16 at 1:43
If the input known to be non-negative? If it's something like a shuffled range from 0 to n, with a single number removed, this is trivial, but you need to be more clear on the known qualities of the input.
– ShadowRanger
Dec 10 '16 at 1:43
1
1
I'd start by adding
print("Swapping %d"%i)
in the swap branch of the if
. What do you learn from its output?– Robᵩ
Dec 10 '16 at 1:45
I'd start by adding
print("Swapping %d"%i)
in the swap branch of the if
. What do you learn from its output?– Robᵩ
Dec 10 '16 at 1:45
|
show 4 more comments
6 Answers
6
active
oldest
votes
look to me that doing it in both O(n) and constant space is kind of impossible. (I stand corrected, the link of Rockybilly give such solution)
To do it in constant space one is kind of forced to sort the list and that is O(n log n) for most sorting algorithms, and the ones here looks like insertion sort which is in average O(n2)
So FWIW I choose to discard the constant space in order to do it as close to O(n) as I can think of which give me a 2n solution (in the worse case scenario, in average is n+k) (which in big O notation is still O(n) )
def firstMissingSince(sequence, start=1):
uniques = set()
maxitem = start-1
for e in sequence:
if e >= start:
uniques.add(e)
if e > maxitem:
maxitem = e
return next( x for x in range(start, maxitem+2) if x not in uniques )
(version 2 bellow )
I could have used set(sequence)
, and max(sequence)
but both are O(n), so I combined them in the same loop, and I use set
for two reason: first is a potential reduction in space by ignoring duplicates and in the same way I only care for number greater or equal to my lower bound (which I also make generic) and second is for the O(1) membership testing.
The last line is a simple linear search for the missing element with the property that default to start if the maximum element is lower to start or is the maximum+1 if the array have no missing element between start and its maximum.
here are some tests borrow from the others answers...
assert 1 == firstMissingSince(A)
assert 2 == firstMissingSince([1,4,3,6,5])
assert 2 == firstMissingSince([1,44,3,66,55])
assert 6 == firstMissingSince([1,2,3,4,5])
assert 4 == firstMissingSince([-6, 3, 10, 14, 17, 6, 14, 1, -5, -8, 8, 15, 17, -10, 2, 7, 11, 2, 7, 11])
assert 4 == firstMissingSince([18, 2, 13, 3, 3, 0, 14, 1, 18, 12, 6, -1, -3, 15, 11, 13, -8, 7, -8, -7])
assert 4 == firstMissingSince([-6, 3, 10, 14, 17, 6, 14, 1, -5, -8, 8, 15, 17, -10, 2, 7, 11, 2, 7, 11])
assert 3 == firstMissingSince([7, -7, 19, 6, -3, -6, 1, -8, -1, 19, -8, 2, 4, 19, 5, 6, 6, 18, 8, 17])
the answer of Rockybilly make me realize that I don't need to know the maximum value at all, so here is version 2
from itertools import count
def firstMissingSince(sequence, start=1):
uniques = set(sequence) # x for x in sequence if x>=start
return next( x for x in count(start) if x not in uniques )
It would appear there is indeed a O(n) and constant space solution. It is quite elegant, which uses values as indexes to change the original list.
– Rockybilly
Dec 13 '16 at 0:46
add a comment |
def first_missing_positive(nums):
bit = 0
for n in nums:
if n > 0:
bit |= 1 << (n - 1)
flag = 0
while bit != 0:
if (bit & 1 == 0):
break
flag += 1
bit >>= 1
return flag + 1
O(1) space complexity and O(n) time complexity solution.
add a comment |
FWIW, here is how I did it:
def firstMissingPositive(A):
for i in range(len(A)):
while A[i] != i+1 and 0 < A[i] < len(A):
value = A[i]-1
A[i], A[value] = A[value], A[i]
for i, value in enumerate(A, 1):
if i != value:
return i
return len(A)+1
assert firstMissingPositive([1,4,3,6,5]) == 2
assert firstMissingPositive([1,44,3,66,55]) == 2
assert firstMissingPositive([1,2,3,4,5]) == 6
assert firstMissingPositive(A) == 1
value = A[i]-1
definite improvement to make that evaluation separate from the assignment. I didn't realize (or never thought about) how those multple assignments work - it's pretty subtle.
– wwii
Dec 10 '16 at 4:18
assert f([18, 2, 13, 3, 3, 0, 14, 1, 18, 12, 6, -1, -3, 15, 11, 13, -8, 7, -8, -7]) == 4
?
– wwii
Dec 10 '16 at 5:08
@wwii - yes, you are right. I falsely assumed that there would be no duplicates.
– Robᵩ
Dec 11 '16 at 11:52
add a comment |
May not be the complete cause for long run times but I did find a bug that will cause an infinite loop. I started by creating random integer arrays of length 20.
a = [random.randint(-10, 20) for _ in range(20)]
Added two print statements to see what was happening.
while i<ln:
print(A)
if A[i]>=1 and A[i]<=ln:
if A[A[i]-1]!=m+1:
print("Swapping %d"%i)
A[A[i]-1], A[i] = m+1, A[A[i]-1]
else:
...
With this array as input you get into an infinite loop:
a = [-6, 3, 10, 14, 17, 6, 14, 1, -5, -8, 8, 15, 17, -10, 2, 7, 11, 2, 7, 11]
>>>
...
[18, 18, -8, -10, -6, 6, 14, 18, -5, 18, 18, 15, 17, 18, 2, 7, 18, 18, 7, 11]
Swapping 5
[18, 18, -8, -10, -6, 6, 14, 18, -5, 18, 18, 15, 17, 18, 2, 7, 18, 18, 7, 11]
Swapping 5
[18, 18, -8, -10, -6, 6, 14, 18, -5, 18, 18, 15, 17, 18, 2, 7, 18, 18, 7, 11]
...
Turns out that if A[A[i]-1]
equals A[i]
then you end up always putting the same number back into A[i]
. In this case i == 5
, A[5] == 6
and A[A[i]-1] == 6
. In this statement,
A[A[i]-1], A[i] = m+1, A[A[i]-1]
The right hand side is evaluated; m+1
is assigned to A[5]
; then 6 is assigned to A[5]
. I fixed it for this one case by swapping the assignment order:
A[i], A[A[i]-1] = A[A[i]-1], m+1
With the list you added to the question, it now throws an IndexError with my mod. Even though the right hand side gets evaluated first, it appears that A[A[i]-1]
on the left hand side doesn't get evaluated till after the first assignment is made and a large number has been placed in A[i]
.
Plagiarizing Rob's solution - evaluate [A[i]-1
before any swaps are made:
def firstMissingPositive(A):
m=max(A)
ln=len(A)
print('max:, len:'.format(m, ln))
i=0
while i<ln:
## print(A[:20])
if A[i]>=1 and A[i]<=ln:
if A[A[i]-1]!=m+1:
## print("Swapping %d"%i)
v = A[i]-1
A[i], A[v] = A[v], m+1
else:
i+=1
else:
i+=1
for i in range(ln):
if A[i]!=m+1:
return i+1
And it still sometimes returns a wrong result so minus one for me. It produces wrong results for the following:
[18, 2, 13, 3, 3, 0, 14, 1, 18, 12, 6, -1, -3, 15, 11, 13, -8, 7, -8, -7]
[-6, 3, 10, 14, 17, 6, 14, 1, -5, -8, 8, 15, 17, -10, 2, 7, 11, 2, 7, 11]
[7, -7, 19, 6, -3, -6, 1, -8, -1, 19, -8, 2, 4, 19, 5, 6, 6, 18, 8, 17]
add a comment |
Here is my solution.
from collections import defaultdict
def firstMissingPositive(A):
d = defaultdict(int)
for i in A:
d[i] = 1
j = 1
while True:
if d[j] == 0:
return j
j += 1
Space complexity: O(n)
Time complexity: O(n + k). Which is considered O(n). Also ignored hashing complexity.
By the way: Googling gives the answer you seek, constant space and O(n) time.
mmm, if you think about it, our solution are very similar, the difference is that I use a set and some extra check, but the core idea is the same...
– Copperfield
Dec 13 '16 at 1:23
also, you don't need defaultdict, you can use a regular dict with dict.fromkeys(A) for the same effect, only that the check is different
– Copperfield
Dec 13 '16 at 1:29
@Copperfield I used it to shorten code. Which I always try to achieve if possible :D
– Rockybilly
Dec 13 '16 at 1:41
add a comment |
def firstMissingPositve(nums):
if nums == []:
return 1
else:
a = max(nums)
for i in range(1 , a+2):
if i not in nums:
c = i
return c
2
Welcome to Stack Overflow, and thanks for answering this question! In order to maximize the usefulness of this answer, I would recommend editing to add some context about what your code does and why.
– Pikachu the Purple Wizard
Mar 7 at 1:15
add a comment |
Your Answer
StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");
StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "1"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);
else
createEditor();
);
function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f41071290%2ffind-the-first-missing-positive-integer-in-python%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
6 Answers
6
active
oldest
votes
6 Answers
6
active
oldest
votes
active
oldest
votes
active
oldest
votes
look to me that doing it in both O(n) and constant space is kind of impossible. (I stand corrected, the link of Rockybilly give such solution)
To do it in constant space one is kind of forced to sort the list and that is O(n log n) for most sorting algorithms, and the ones here looks like insertion sort which is in average O(n2)
So FWIW I choose to discard the constant space in order to do it as close to O(n) as I can think of which give me a 2n solution (in the worse case scenario, in average is n+k) (which in big O notation is still O(n) )
def firstMissingSince(sequence, start=1):
uniques = set()
maxitem = start-1
for e in sequence:
if e >= start:
uniques.add(e)
if e > maxitem:
maxitem = e
return next( x for x in range(start, maxitem+2) if x not in uniques )
(version 2 bellow )
I could have used set(sequence)
, and max(sequence)
but both are O(n), so I combined them in the same loop, and I use set
for two reason: first is a potential reduction in space by ignoring duplicates and in the same way I only care for number greater or equal to my lower bound (which I also make generic) and second is for the O(1) membership testing.
The last line is a simple linear search for the missing element with the property that default to start if the maximum element is lower to start or is the maximum+1 if the array have no missing element between start and its maximum.
here are some tests borrow from the others answers...
assert 1 == firstMissingSince(A)
assert 2 == firstMissingSince([1,4,3,6,5])
assert 2 == firstMissingSince([1,44,3,66,55])
assert 6 == firstMissingSince([1,2,3,4,5])
assert 4 == firstMissingSince([-6, 3, 10, 14, 17, 6, 14, 1, -5, -8, 8, 15, 17, -10, 2, 7, 11, 2, 7, 11])
assert 4 == firstMissingSince([18, 2, 13, 3, 3, 0, 14, 1, 18, 12, 6, -1, -3, 15, 11, 13, -8, 7, -8, -7])
assert 4 == firstMissingSince([-6, 3, 10, 14, 17, 6, 14, 1, -5, -8, 8, 15, 17, -10, 2, 7, 11, 2, 7, 11])
assert 3 == firstMissingSince([7, -7, 19, 6, -3, -6, 1, -8, -1, 19, -8, 2, 4, 19, 5, 6, 6, 18, 8, 17])
the answer of Rockybilly make me realize that I don't need to know the maximum value at all, so here is version 2
from itertools import count
def firstMissingSince(sequence, start=1):
uniques = set(sequence) # x for x in sequence if x>=start
return next( x for x in count(start) if x not in uniques )
It would appear there is indeed a O(n) and constant space solution. It is quite elegant, which uses values as indexes to change the original list.
– Rockybilly
Dec 13 '16 at 0:46
add a comment |
look to me that doing it in both O(n) and constant space is kind of impossible. (I stand corrected, the link of Rockybilly give such solution)
To do it in constant space one is kind of forced to sort the list and that is O(n log n) for most sorting algorithms, and the ones here looks like insertion sort which is in average O(n2)
So FWIW I choose to discard the constant space in order to do it as close to O(n) as I can think of which give me a 2n solution (in the worse case scenario, in average is n+k) (which in big O notation is still O(n) )
def firstMissingSince(sequence, start=1):
uniques = set()
maxitem = start-1
for e in sequence:
if e >= start:
uniques.add(e)
if e > maxitem:
maxitem = e
return next( x for x in range(start, maxitem+2) if x not in uniques )
(version 2 bellow )
I could have used set(sequence)
, and max(sequence)
but both are O(n), so I combined them in the same loop, and I use set
for two reason: first is a potential reduction in space by ignoring duplicates and in the same way I only care for number greater or equal to my lower bound (which I also make generic) and second is for the O(1) membership testing.
The last line is a simple linear search for the missing element with the property that default to start if the maximum element is lower to start or is the maximum+1 if the array have no missing element between start and its maximum.
here are some tests borrow from the others answers...
assert 1 == firstMissingSince(A)
assert 2 == firstMissingSince([1,4,3,6,5])
assert 2 == firstMissingSince([1,44,3,66,55])
assert 6 == firstMissingSince([1,2,3,4,5])
assert 4 == firstMissingSince([-6, 3, 10, 14, 17, 6, 14, 1, -5, -8, 8, 15, 17, -10, 2, 7, 11, 2, 7, 11])
assert 4 == firstMissingSince([18, 2, 13, 3, 3, 0, 14, 1, 18, 12, 6, -1, -3, 15, 11, 13, -8, 7, -8, -7])
assert 4 == firstMissingSince([-6, 3, 10, 14, 17, 6, 14, 1, -5, -8, 8, 15, 17, -10, 2, 7, 11, 2, 7, 11])
assert 3 == firstMissingSince([7, -7, 19, 6, -3, -6, 1, -8, -1, 19, -8, 2, 4, 19, 5, 6, 6, 18, 8, 17])
the answer of Rockybilly make me realize that I don't need to know the maximum value at all, so here is version 2
from itertools import count
def firstMissingSince(sequence, start=1):
uniques = set(sequence) # x for x in sequence if x>=start
return next( x for x in count(start) if x not in uniques )
It would appear there is indeed a O(n) and constant space solution. It is quite elegant, which uses values as indexes to change the original list.
– Rockybilly
Dec 13 '16 at 0:46
add a comment |
look to me that doing it in both O(n) and constant space is kind of impossible. (I stand corrected, the link of Rockybilly give such solution)
To do it in constant space one is kind of forced to sort the list and that is O(n log n) for most sorting algorithms, and the ones here looks like insertion sort which is in average O(n2)
So FWIW I choose to discard the constant space in order to do it as close to O(n) as I can think of which give me a 2n solution (in the worse case scenario, in average is n+k) (which in big O notation is still O(n) )
def firstMissingSince(sequence, start=1):
uniques = set()
maxitem = start-1
for e in sequence:
if e >= start:
uniques.add(e)
if e > maxitem:
maxitem = e
return next( x for x in range(start, maxitem+2) if x not in uniques )
(version 2 bellow )
I could have used set(sequence)
, and max(sequence)
but both are O(n), so I combined them in the same loop, and I use set
for two reason: first is a potential reduction in space by ignoring duplicates and in the same way I only care for number greater or equal to my lower bound (which I also make generic) and second is for the O(1) membership testing.
The last line is a simple linear search for the missing element with the property that default to start if the maximum element is lower to start or is the maximum+1 if the array have no missing element between start and its maximum.
here are some tests borrow from the others answers...
assert 1 == firstMissingSince(A)
assert 2 == firstMissingSince([1,4,3,6,5])
assert 2 == firstMissingSince([1,44,3,66,55])
assert 6 == firstMissingSince([1,2,3,4,5])
assert 4 == firstMissingSince([-6, 3, 10, 14, 17, 6, 14, 1, -5, -8, 8, 15, 17, -10, 2, 7, 11, 2, 7, 11])
assert 4 == firstMissingSince([18, 2, 13, 3, 3, 0, 14, 1, 18, 12, 6, -1, -3, 15, 11, 13, -8, 7, -8, -7])
assert 4 == firstMissingSince([-6, 3, 10, 14, 17, 6, 14, 1, -5, -8, 8, 15, 17, -10, 2, 7, 11, 2, 7, 11])
assert 3 == firstMissingSince([7, -7, 19, 6, -3, -6, 1, -8, -1, 19, -8, 2, 4, 19, 5, 6, 6, 18, 8, 17])
the answer of Rockybilly make me realize that I don't need to know the maximum value at all, so here is version 2
from itertools import count
def firstMissingSince(sequence, start=1):
uniques = set(sequence) # x for x in sequence if x>=start
return next( x for x in count(start) if x not in uniques )
look to me that doing it in both O(n) and constant space is kind of impossible. (I stand corrected, the link of Rockybilly give such solution)
To do it in constant space one is kind of forced to sort the list and that is O(n log n) for most sorting algorithms, and the ones here looks like insertion sort which is in average O(n2)
So FWIW I choose to discard the constant space in order to do it as close to O(n) as I can think of which give me a 2n solution (in the worse case scenario, in average is n+k) (which in big O notation is still O(n) )
def firstMissingSince(sequence, start=1):
uniques = set()
maxitem = start-1
for e in sequence:
if e >= start:
uniques.add(e)
if e > maxitem:
maxitem = e
return next( x for x in range(start, maxitem+2) if x not in uniques )
(version 2 bellow )
I could have used set(sequence)
, and max(sequence)
but both are O(n), so I combined them in the same loop, and I use set
for two reason: first is a potential reduction in space by ignoring duplicates and in the same way I only care for number greater or equal to my lower bound (which I also make generic) and second is for the O(1) membership testing.
The last line is a simple linear search for the missing element with the property that default to start if the maximum element is lower to start or is the maximum+1 if the array have no missing element between start and its maximum.
here are some tests borrow from the others answers...
assert 1 == firstMissingSince(A)
assert 2 == firstMissingSince([1,4,3,6,5])
assert 2 == firstMissingSince([1,44,3,66,55])
assert 6 == firstMissingSince([1,2,3,4,5])
assert 4 == firstMissingSince([-6, 3, 10, 14, 17, 6, 14, 1, -5, -8, 8, 15, 17, -10, 2, 7, 11, 2, 7, 11])
assert 4 == firstMissingSince([18, 2, 13, 3, 3, 0, 14, 1, 18, 12, 6, -1, -3, 15, 11, 13, -8, 7, -8, -7])
assert 4 == firstMissingSince([-6, 3, 10, 14, 17, 6, 14, 1, -5, -8, 8, 15, 17, -10, 2, 7, 11, 2, 7, 11])
assert 3 == firstMissingSince([7, -7, 19, 6, -3, -6, 1, -8, -1, 19, -8, 2, 4, 19, 5, 6, 6, 18, 8, 17])
the answer of Rockybilly make me realize that I don't need to know the maximum value at all, so here is version 2
from itertools import count
def firstMissingSince(sequence, start=1):
uniques = set(sequence) # x for x in sequence if x>=start
return next( x for x in count(start) if x not in uniques )
edited Dec 13 '16 at 2:02
answered Dec 12 '16 at 23:36
CopperfieldCopperfield
4,1732918
4,1732918
It would appear there is indeed a O(n) and constant space solution. It is quite elegant, which uses values as indexes to change the original list.
– Rockybilly
Dec 13 '16 at 0:46
add a comment |
It would appear there is indeed a O(n) and constant space solution. It is quite elegant, which uses values as indexes to change the original list.
– Rockybilly
Dec 13 '16 at 0:46
It would appear there is indeed a O(n) and constant space solution. It is quite elegant, which uses values as indexes to change the original list.
– Rockybilly
Dec 13 '16 at 0:46
It would appear there is indeed a O(n) and constant space solution. It is quite elegant, which uses values as indexes to change the original list.
– Rockybilly
Dec 13 '16 at 0:46
add a comment |
def first_missing_positive(nums):
bit = 0
for n in nums:
if n > 0:
bit |= 1 << (n - 1)
flag = 0
while bit != 0:
if (bit & 1 == 0):
break
flag += 1
bit >>= 1
return flag + 1
O(1) space complexity and O(n) time complexity solution.
add a comment |
def first_missing_positive(nums):
bit = 0
for n in nums:
if n > 0:
bit |= 1 << (n - 1)
flag = 0
while bit != 0:
if (bit & 1 == 0):
break
flag += 1
bit >>= 1
return flag + 1
O(1) space complexity and O(n) time complexity solution.
add a comment |
def first_missing_positive(nums):
bit = 0
for n in nums:
if n > 0:
bit |= 1 << (n - 1)
flag = 0
while bit != 0:
if (bit & 1 == 0):
break
flag += 1
bit >>= 1
return flag + 1
O(1) space complexity and O(n) time complexity solution.
def first_missing_positive(nums):
bit = 0
for n in nums:
if n > 0:
bit |= 1 << (n - 1)
flag = 0
while bit != 0:
if (bit & 1 == 0):
break
flag += 1
bit >>= 1
return flag + 1
O(1) space complexity and O(n) time complexity solution.
answered Nov 13 '18 at 13:07
Nikhil KulkarniNikhil Kulkarni
111
111
add a comment |
add a comment |
FWIW, here is how I did it:
def firstMissingPositive(A):
for i in range(len(A)):
while A[i] != i+1 and 0 < A[i] < len(A):
value = A[i]-1
A[i], A[value] = A[value], A[i]
for i, value in enumerate(A, 1):
if i != value:
return i
return len(A)+1
assert firstMissingPositive([1,4,3,6,5]) == 2
assert firstMissingPositive([1,44,3,66,55]) == 2
assert firstMissingPositive([1,2,3,4,5]) == 6
assert firstMissingPositive(A) == 1
value = A[i]-1
definite improvement to make that evaluation separate from the assignment. I didn't realize (or never thought about) how those multple assignments work - it's pretty subtle.
– wwii
Dec 10 '16 at 4:18
assert f([18, 2, 13, 3, 3, 0, 14, 1, 18, 12, 6, -1, -3, 15, 11, 13, -8, 7, -8, -7]) == 4
?
– wwii
Dec 10 '16 at 5:08
@wwii - yes, you are right. I falsely assumed that there would be no duplicates.
– Robᵩ
Dec 11 '16 at 11:52
add a comment |
FWIW, here is how I did it:
def firstMissingPositive(A):
for i in range(len(A)):
while A[i] != i+1 and 0 < A[i] < len(A):
value = A[i]-1
A[i], A[value] = A[value], A[i]
for i, value in enumerate(A, 1):
if i != value:
return i
return len(A)+1
assert firstMissingPositive([1,4,3,6,5]) == 2
assert firstMissingPositive([1,44,3,66,55]) == 2
assert firstMissingPositive([1,2,3,4,5]) == 6
assert firstMissingPositive(A) == 1
value = A[i]-1
definite improvement to make that evaluation separate from the assignment. I didn't realize (or never thought about) how those multple assignments work - it's pretty subtle.
– wwii
Dec 10 '16 at 4:18
assert f([18, 2, 13, 3, 3, 0, 14, 1, 18, 12, 6, -1, -3, 15, 11, 13, -8, 7, -8, -7]) == 4
?
– wwii
Dec 10 '16 at 5:08
@wwii - yes, you are right. I falsely assumed that there would be no duplicates.
– Robᵩ
Dec 11 '16 at 11:52
add a comment |
FWIW, here is how I did it:
def firstMissingPositive(A):
for i in range(len(A)):
while A[i] != i+1 and 0 < A[i] < len(A):
value = A[i]-1
A[i], A[value] = A[value], A[i]
for i, value in enumerate(A, 1):
if i != value:
return i
return len(A)+1
assert firstMissingPositive([1,4,3,6,5]) == 2
assert firstMissingPositive([1,44,3,66,55]) == 2
assert firstMissingPositive([1,2,3,4,5]) == 6
assert firstMissingPositive(A) == 1
FWIW, here is how I did it:
def firstMissingPositive(A):
for i in range(len(A)):
while A[i] != i+1 and 0 < A[i] < len(A):
value = A[i]-1
A[i], A[value] = A[value], A[i]
for i, value in enumerate(A, 1):
if i != value:
return i
return len(A)+1
assert firstMissingPositive([1,4,3,6,5]) == 2
assert firstMissingPositive([1,44,3,66,55]) == 2
assert firstMissingPositive([1,2,3,4,5]) == 6
assert firstMissingPositive(A) == 1
answered Dec 10 '16 at 3:52
RobᵩRobᵩ
117k13142223
117k13142223
value = A[i]-1
definite improvement to make that evaluation separate from the assignment. I didn't realize (or never thought about) how those multple assignments work - it's pretty subtle.
– wwii
Dec 10 '16 at 4:18
assert f([18, 2, 13, 3, 3, 0, 14, 1, 18, 12, 6, -1, -3, 15, 11, 13, -8, 7, -8, -7]) == 4
?
– wwii
Dec 10 '16 at 5:08
@wwii - yes, you are right. I falsely assumed that there would be no duplicates.
– Robᵩ
Dec 11 '16 at 11:52
add a comment |
value = A[i]-1
definite improvement to make that evaluation separate from the assignment. I didn't realize (or never thought about) how those multple assignments work - it's pretty subtle.
– wwii
Dec 10 '16 at 4:18
assert f([18, 2, 13, 3, 3, 0, 14, 1, 18, 12, 6, -1, -3, 15, 11, 13, -8, 7, -8, -7]) == 4
?
– wwii
Dec 10 '16 at 5:08
@wwii - yes, you are right. I falsely assumed that there would be no duplicates.
– Robᵩ
Dec 11 '16 at 11:52
value = A[i]-1
definite improvement to make that evaluation separate from the assignment. I didn't realize (or never thought about) how those multple assignments work - it's pretty subtle.– wwii
Dec 10 '16 at 4:18
value = A[i]-1
definite improvement to make that evaluation separate from the assignment. I didn't realize (or never thought about) how those multple assignments work - it's pretty subtle.– wwii
Dec 10 '16 at 4:18
assert f([18, 2, 13, 3, 3, 0, 14, 1, 18, 12, 6, -1, -3, 15, 11, 13, -8, 7, -8, -7]) == 4
?– wwii
Dec 10 '16 at 5:08
assert f([18, 2, 13, 3, 3, 0, 14, 1, 18, 12, 6, -1, -3, 15, 11, 13, -8, 7, -8, -7]) == 4
?– wwii
Dec 10 '16 at 5:08
@wwii - yes, you are right. I falsely assumed that there would be no duplicates.
– Robᵩ
Dec 11 '16 at 11:52
@wwii - yes, you are right. I falsely assumed that there would be no duplicates.
– Robᵩ
Dec 11 '16 at 11:52
add a comment |
May not be the complete cause for long run times but I did find a bug that will cause an infinite loop. I started by creating random integer arrays of length 20.
a = [random.randint(-10, 20) for _ in range(20)]
Added two print statements to see what was happening.
while i<ln:
print(A)
if A[i]>=1 and A[i]<=ln:
if A[A[i]-1]!=m+1:
print("Swapping %d"%i)
A[A[i]-1], A[i] = m+1, A[A[i]-1]
else:
...
With this array as input you get into an infinite loop:
a = [-6, 3, 10, 14, 17, 6, 14, 1, -5, -8, 8, 15, 17, -10, 2, 7, 11, 2, 7, 11]
>>>
...
[18, 18, -8, -10, -6, 6, 14, 18, -5, 18, 18, 15, 17, 18, 2, 7, 18, 18, 7, 11]
Swapping 5
[18, 18, -8, -10, -6, 6, 14, 18, -5, 18, 18, 15, 17, 18, 2, 7, 18, 18, 7, 11]
Swapping 5
[18, 18, -8, -10, -6, 6, 14, 18, -5, 18, 18, 15, 17, 18, 2, 7, 18, 18, 7, 11]
...
Turns out that if A[A[i]-1]
equals A[i]
then you end up always putting the same number back into A[i]
. In this case i == 5
, A[5] == 6
and A[A[i]-1] == 6
. In this statement,
A[A[i]-1], A[i] = m+1, A[A[i]-1]
The right hand side is evaluated; m+1
is assigned to A[5]
; then 6 is assigned to A[5]
. I fixed it for this one case by swapping the assignment order:
A[i], A[A[i]-1] = A[A[i]-1], m+1
With the list you added to the question, it now throws an IndexError with my mod. Even though the right hand side gets evaluated first, it appears that A[A[i]-1]
on the left hand side doesn't get evaluated till after the first assignment is made and a large number has been placed in A[i]
.
Plagiarizing Rob's solution - evaluate [A[i]-1
before any swaps are made:
def firstMissingPositive(A):
m=max(A)
ln=len(A)
print('max:, len:'.format(m, ln))
i=0
while i<ln:
## print(A[:20])
if A[i]>=1 and A[i]<=ln:
if A[A[i]-1]!=m+1:
## print("Swapping %d"%i)
v = A[i]-1
A[i], A[v] = A[v], m+1
else:
i+=1
else:
i+=1
for i in range(ln):
if A[i]!=m+1:
return i+1
And it still sometimes returns a wrong result so minus one for me. It produces wrong results for the following:
[18, 2, 13, 3, 3, 0, 14, 1, 18, 12, 6, -1, -3, 15, 11, 13, -8, 7, -8, -7]
[-6, 3, 10, 14, 17, 6, 14, 1, -5, -8, 8, 15, 17, -10, 2, 7, 11, 2, 7, 11]
[7, -7, 19, 6, -3, -6, 1, -8, -1, 19, -8, 2, 4, 19, 5, 6, 6, 18, 8, 17]
add a comment |
May not be the complete cause for long run times but I did find a bug that will cause an infinite loop. I started by creating random integer arrays of length 20.
a = [random.randint(-10, 20) for _ in range(20)]
Added two print statements to see what was happening.
while i<ln:
print(A)
if A[i]>=1 and A[i]<=ln:
if A[A[i]-1]!=m+1:
print("Swapping %d"%i)
A[A[i]-1], A[i] = m+1, A[A[i]-1]
else:
...
With this array as input you get into an infinite loop:
a = [-6, 3, 10, 14, 17, 6, 14, 1, -5, -8, 8, 15, 17, -10, 2, 7, 11, 2, 7, 11]
>>>
...
[18, 18, -8, -10, -6, 6, 14, 18, -5, 18, 18, 15, 17, 18, 2, 7, 18, 18, 7, 11]
Swapping 5
[18, 18, -8, -10, -6, 6, 14, 18, -5, 18, 18, 15, 17, 18, 2, 7, 18, 18, 7, 11]
Swapping 5
[18, 18, -8, -10, -6, 6, 14, 18, -5, 18, 18, 15, 17, 18, 2, 7, 18, 18, 7, 11]
...
Turns out that if A[A[i]-1]
equals A[i]
then you end up always putting the same number back into A[i]
. In this case i == 5
, A[5] == 6
and A[A[i]-1] == 6
. In this statement,
A[A[i]-1], A[i] = m+1, A[A[i]-1]
The right hand side is evaluated; m+1
is assigned to A[5]
; then 6 is assigned to A[5]
. I fixed it for this one case by swapping the assignment order:
A[i], A[A[i]-1] = A[A[i]-1], m+1
With the list you added to the question, it now throws an IndexError with my mod. Even though the right hand side gets evaluated first, it appears that A[A[i]-1]
on the left hand side doesn't get evaluated till after the first assignment is made and a large number has been placed in A[i]
.
Plagiarizing Rob's solution - evaluate [A[i]-1
before any swaps are made:
def firstMissingPositive(A):
m=max(A)
ln=len(A)
print('max:, len:'.format(m, ln))
i=0
while i<ln:
## print(A[:20])
if A[i]>=1 and A[i]<=ln:
if A[A[i]-1]!=m+1:
## print("Swapping %d"%i)
v = A[i]-1
A[i], A[v] = A[v], m+1
else:
i+=1
else:
i+=1
for i in range(ln):
if A[i]!=m+1:
return i+1
And it still sometimes returns a wrong result so minus one for me. It produces wrong results for the following:
[18, 2, 13, 3, 3, 0, 14, 1, 18, 12, 6, -1, -3, 15, 11, 13, -8, 7, -8, -7]
[-6, 3, 10, 14, 17, 6, 14, 1, -5, -8, 8, 15, 17, -10, 2, 7, 11, 2, 7, 11]
[7, -7, 19, 6, -3, -6, 1, -8, -1, 19, -8, 2, 4, 19, 5, 6, 6, 18, 8, 17]
add a comment |
May not be the complete cause for long run times but I did find a bug that will cause an infinite loop. I started by creating random integer arrays of length 20.
a = [random.randint(-10, 20) for _ in range(20)]
Added two print statements to see what was happening.
while i<ln:
print(A)
if A[i]>=1 and A[i]<=ln:
if A[A[i]-1]!=m+1:
print("Swapping %d"%i)
A[A[i]-1], A[i] = m+1, A[A[i]-1]
else:
...
With this array as input you get into an infinite loop:
a = [-6, 3, 10, 14, 17, 6, 14, 1, -5, -8, 8, 15, 17, -10, 2, 7, 11, 2, 7, 11]
>>>
...
[18, 18, -8, -10, -6, 6, 14, 18, -5, 18, 18, 15, 17, 18, 2, 7, 18, 18, 7, 11]
Swapping 5
[18, 18, -8, -10, -6, 6, 14, 18, -5, 18, 18, 15, 17, 18, 2, 7, 18, 18, 7, 11]
Swapping 5
[18, 18, -8, -10, -6, 6, 14, 18, -5, 18, 18, 15, 17, 18, 2, 7, 18, 18, 7, 11]
...
Turns out that if A[A[i]-1]
equals A[i]
then you end up always putting the same number back into A[i]
. In this case i == 5
, A[5] == 6
and A[A[i]-1] == 6
. In this statement,
A[A[i]-1], A[i] = m+1, A[A[i]-1]
The right hand side is evaluated; m+1
is assigned to A[5]
; then 6 is assigned to A[5]
. I fixed it for this one case by swapping the assignment order:
A[i], A[A[i]-1] = A[A[i]-1], m+1
With the list you added to the question, it now throws an IndexError with my mod. Even though the right hand side gets evaluated first, it appears that A[A[i]-1]
on the left hand side doesn't get evaluated till after the first assignment is made and a large number has been placed in A[i]
.
Plagiarizing Rob's solution - evaluate [A[i]-1
before any swaps are made:
def firstMissingPositive(A):
m=max(A)
ln=len(A)
print('max:, len:'.format(m, ln))
i=0
while i<ln:
## print(A[:20])
if A[i]>=1 and A[i]<=ln:
if A[A[i]-1]!=m+1:
## print("Swapping %d"%i)
v = A[i]-1
A[i], A[v] = A[v], m+1
else:
i+=1
else:
i+=1
for i in range(ln):
if A[i]!=m+1:
return i+1
And it still sometimes returns a wrong result so minus one for me. It produces wrong results for the following:
[18, 2, 13, 3, 3, 0, 14, 1, 18, 12, 6, -1, -3, 15, 11, 13, -8, 7, -8, -7]
[-6, 3, 10, 14, 17, 6, 14, 1, -5, -8, 8, 15, 17, -10, 2, 7, 11, 2, 7, 11]
[7, -7, 19, 6, -3, -6, 1, -8, -1, 19, -8, 2, 4, 19, 5, 6, 6, 18, 8, 17]
May not be the complete cause for long run times but I did find a bug that will cause an infinite loop. I started by creating random integer arrays of length 20.
a = [random.randint(-10, 20) for _ in range(20)]
Added two print statements to see what was happening.
while i<ln:
print(A)
if A[i]>=1 and A[i]<=ln:
if A[A[i]-1]!=m+1:
print("Swapping %d"%i)
A[A[i]-1], A[i] = m+1, A[A[i]-1]
else:
...
With this array as input you get into an infinite loop:
a = [-6, 3, 10, 14, 17, 6, 14, 1, -5, -8, 8, 15, 17, -10, 2, 7, 11, 2, 7, 11]
>>>
...
[18, 18, -8, -10, -6, 6, 14, 18, -5, 18, 18, 15, 17, 18, 2, 7, 18, 18, 7, 11]
Swapping 5
[18, 18, -8, -10, -6, 6, 14, 18, -5, 18, 18, 15, 17, 18, 2, 7, 18, 18, 7, 11]
Swapping 5
[18, 18, -8, -10, -6, 6, 14, 18, -5, 18, 18, 15, 17, 18, 2, 7, 18, 18, 7, 11]
...
Turns out that if A[A[i]-1]
equals A[i]
then you end up always putting the same number back into A[i]
. In this case i == 5
, A[5] == 6
and A[A[i]-1] == 6
. In this statement,
A[A[i]-1], A[i] = m+1, A[A[i]-1]
The right hand side is evaluated; m+1
is assigned to A[5]
; then 6 is assigned to A[5]
. I fixed it for this one case by swapping the assignment order:
A[i], A[A[i]-1] = A[A[i]-1], m+1
With the list you added to the question, it now throws an IndexError with my mod. Even though the right hand side gets evaluated first, it appears that A[A[i]-1]
on the left hand side doesn't get evaluated till after the first assignment is made and a large number has been placed in A[i]
.
Plagiarizing Rob's solution - evaluate [A[i]-1
before any swaps are made:
def firstMissingPositive(A):
m=max(A)
ln=len(A)
print('max:, len:'.format(m, ln))
i=0
while i<ln:
## print(A[:20])
if A[i]>=1 and A[i]<=ln:
if A[A[i]-1]!=m+1:
## print("Swapping %d"%i)
v = A[i]-1
A[i], A[v] = A[v], m+1
else:
i+=1
else:
i+=1
for i in range(ln):
if A[i]!=m+1:
return i+1
And it still sometimes returns a wrong result so minus one for me. It produces wrong results for the following:
[18, 2, 13, 3, 3, 0, 14, 1, 18, 12, 6, -1, -3, 15, 11, 13, -8, 7, -8, -7]
[-6, 3, 10, 14, 17, 6, 14, 1, -5, -8, 8, 15, 17, -10, 2, 7, 11, 2, 7, 11]
[7, -7, 19, 6, -3, -6, 1, -8, -1, 19, -8, 2, 4, 19, 5, 6, 6, 18, 8, 17]
edited May 23 '17 at 12:24
Community♦
11
11
answered Dec 10 '16 at 3:48
wwiiwwii
11k31948
11k31948
add a comment |
add a comment |
Here is my solution.
from collections import defaultdict
def firstMissingPositive(A):
d = defaultdict(int)
for i in A:
d[i] = 1
j = 1
while True:
if d[j] == 0:
return j
j += 1
Space complexity: O(n)
Time complexity: O(n + k). Which is considered O(n). Also ignored hashing complexity.
By the way: Googling gives the answer you seek, constant space and O(n) time.
mmm, if you think about it, our solution are very similar, the difference is that I use a set and some extra check, but the core idea is the same...
– Copperfield
Dec 13 '16 at 1:23
also, you don't need defaultdict, you can use a regular dict with dict.fromkeys(A) for the same effect, only that the check is different
– Copperfield
Dec 13 '16 at 1:29
@Copperfield I used it to shorten code. Which I always try to achieve if possible :D
– Rockybilly
Dec 13 '16 at 1:41
add a comment |
Here is my solution.
from collections import defaultdict
def firstMissingPositive(A):
d = defaultdict(int)
for i in A:
d[i] = 1
j = 1
while True:
if d[j] == 0:
return j
j += 1
Space complexity: O(n)
Time complexity: O(n + k). Which is considered O(n). Also ignored hashing complexity.
By the way: Googling gives the answer you seek, constant space and O(n) time.
mmm, if you think about it, our solution are very similar, the difference is that I use a set and some extra check, but the core idea is the same...
– Copperfield
Dec 13 '16 at 1:23
also, you don't need defaultdict, you can use a regular dict with dict.fromkeys(A) for the same effect, only that the check is different
– Copperfield
Dec 13 '16 at 1:29
@Copperfield I used it to shorten code. Which I always try to achieve if possible :D
– Rockybilly
Dec 13 '16 at 1:41
add a comment |
Here is my solution.
from collections import defaultdict
def firstMissingPositive(A):
d = defaultdict(int)
for i in A:
d[i] = 1
j = 1
while True:
if d[j] == 0:
return j
j += 1
Space complexity: O(n)
Time complexity: O(n + k). Which is considered O(n). Also ignored hashing complexity.
By the way: Googling gives the answer you seek, constant space and O(n) time.
Here is my solution.
from collections import defaultdict
def firstMissingPositive(A):
d = defaultdict(int)
for i in A:
d[i] = 1
j = 1
while True:
if d[j] == 0:
return j
j += 1
Space complexity: O(n)
Time complexity: O(n + k). Which is considered O(n). Also ignored hashing complexity.
By the way: Googling gives the answer you seek, constant space and O(n) time.
edited Dec 13 '16 at 0:30
answered Dec 13 '16 at 0:19
RockybillyRockybilly
1,918721
1,918721
mmm, if you think about it, our solution are very similar, the difference is that I use a set and some extra check, but the core idea is the same...
– Copperfield
Dec 13 '16 at 1:23
also, you don't need defaultdict, you can use a regular dict with dict.fromkeys(A) for the same effect, only that the check is different
– Copperfield
Dec 13 '16 at 1:29
@Copperfield I used it to shorten code. Which I always try to achieve if possible :D
– Rockybilly
Dec 13 '16 at 1:41
add a comment |
mmm, if you think about it, our solution are very similar, the difference is that I use a set and some extra check, but the core idea is the same...
– Copperfield
Dec 13 '16 at 1:23
also, you don't need defaultdict, you can use a regular dict with dict.fromkeys(A) for the same effect, only that the check is different
– Copperfield
Dec 13 '16 at 1:29
@Copperfield I used it to shorten code. Which I always try to achieve if possible :D
– Rockybilly
Dec 13 '16 at 1:41
mmm, if you think about it, our solution are very similar, the difference is that I use a set and some extra check, but the core idea is the same...
– Copperfield
Dec 13 '16 at 1:23
mmm, if you think about it, our solution are very similar, the difference is that I use a set and some extra check, but the core idea is the same...
– Copperfield
Dec 13 '16 at 1:23
also, you don't need defaultdict, you can use a regular dict with dict.fromkeys(A) for the same effect, only that the check is different
– Copperfield
Dec 13 '16 at 1:29
also, you don't need defaultdict, you can use a regular dict with dict.fromkeys(A) for the same effect, only that the check is different
– Copperfield
Dec 13 '16 at 1:29
@Copperfield I used it to shorten code. Which I always try to achieve if possible :D
– Rockybilly
Dec 13 '16 at 1:41
@Copperfield I used it to shorten code. Which I always try to achieve if possible :D
– Rockybilly
Dec 13 '16 at 1:41
add a comment |
def firstMissingPositve(nums):
if nums == []:
return 1
else:
a = max(nums)
for i in range(1 , a+2):
if i not in nums:
c = i
return c
2
Welcome to Stack Overflow, and thanks for answering this question! In order to maximize the usefulness of this answer, I would recommend editing to add some context about what your code does and why.
– Pikachu the Purple Wizard
Mar 7 at 1:15
add a comment |
def firstMissingPositve(nums):
if nums == []:
return 1
else:
a = max(nums)
for i in range(1 , a+2):
if i not in nums:
c = i
return c
2
Welcome to Stack Overflow, and thanks for answering this question! In order to maximize the usefulness of this answer, I would recommend editing to add some context about what your code does and why.
– Pikachu the Purple Wizard
Mar 7 at 1:15
add a comment |
def firstMissingPositve(nums):
if nums == []:
return 1
else:
a = max(nums)
for i in range(1 , a+2):
if i not in nums:
c = i
return c
def firstMissingPositve(nums):
if nums == []:
return 1
else:
a = max(nums)
for i in range(1 , a+2):
if i not in nums:
c = i
return c
edited Mar 7 at 1:10
BML91
7492726
7492726
answered Mar 7 at 0:34
user11162722user11162722
1
1
2
Welcome to Stack Overflow, and thanks for answering this question! In order to maximize the usefulness of this answer, I would recommend editing to add some context about what your code does and why.
– Pikachu the Purple Wizard
Mar 7 at 1:15
add a comment |
2
Welcome to Stack Overflow, and thanks for answering this question! In order to maximize the usefulness of this answer, I would recommend editing to add some context about what your code does and why.
– Pikachu the Purple Wizard
Mar 7 at 1:15
2
2
Welcome to Stack Overflow, and thanks for answering this question! In order to maximize the usefulness of this answer, I would recommend editing to add some context about what your code does and why.
– Pikachu the Purple Wizard
Mar 7 at 1:15
Welcome to Stack Overflow, and thanks for answering this question! In order to maximize the usefulness of this answer, I would recommend editing to add some context about what your code does and why.
– Pikachu the Purple Wizard
Mar 7 at 1:15
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f41071290%2ffind-the-first-missing-positive-integer-in-python%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Can you not used
sort
orsorted
?– Eli Sadoff
Dec 10 '16 at 1:38
2
OP mentioned "should run in O(n)".
– Robᵩ
Dec 10 '16 at 1:38
What else do we know about the array? Is there a missing positive integer? Is there only one? Are there duplicate values?
– Robᵩ
Dec 10 '16 at 1:39
If the input known to be non-negative? If it's something like a shuffled range from 0 to n, with a single number removed, this is trivial, but you need to be more clear on the known qualities of the input.
– ShadowRanger
Dec 10 '16 at 1:43
1
I'd start by adding
print("Swapping %d"%i)
in the swap branch of theif
. What do you learn from its output?– Robᵩ
Dec 10 '16 at 1:45