经典的问题陈述是:给定未排序的整数数组A
,请找到A
中不存在的最小正整数。
[3, 2, 1, 6, 5] -> 4
[2, 3, 4, 5] -> 1
[1, 2, 3, 4] -> 5
在经典的问题陈述中,您只能得到一个数组,并且可以找到有关此问题的许多解决方案和资源,here,here和here。
在我的问题中,为您提供了两个数组,分别为A
和B
。构造长度为N
的数组C
,其“最小丢失整数”可能最大。 N
必须为C[i]
或A[i]
。
B[i]
如何用A = [1, 2, 4, 3], B = [1, 3, 2, 3] =-> C = [1, 2, 4, 3] answer = 5
A = [4, 2, 1, 6, 5], B = [3, 2, 1, 7, 7] =-> C = [3, 2, 1, 6, 5] answer = 4
A = [2, 3], B = [4, 5] =-> C = [2, 5] answer = 1
最坏的时间和空间复杂性来解决此问题?
假设:
O(N)
答案 0 :(得分:2)
此算法可对数字范围O(n)
中的数字加上处理输入的时间进行[0..n+2]
算术运算。
[1..n]
范围内的数字替换为n+2
。这不会改变结果。1, 2, 3, ..., n-1, n, n+2
的节点构造一个图,并且对于所有0 <= i < n
,在节点A[i]
和B[i]
之间存在一条边(假定索引为0的数组)。因此该图具有n+1
个节点和n
个边。现在,问题等同于找到一种方式来确定边的方向,以使最大度数为0的最小顶点成为可能。
对于每个具有v
个顶点和e
边的连接组件,e >= v-1
:
如果e == v-1
是一棵树。定向边缘的所有方法都将导致顶点的度数为0,并且可以证明对于树中的所有顶点,都存在一种定向边缘的方法,使其成为唯一度为0的顶点。
方法:
使树在该顶点处扎根,然后使每条边从父级直接指向子级。
当然,最好(贪婪地)选择度数为0的顶点作为具有最高编号的顶点。
如果e >= v
,则所连接的组件内部存在电路。然后,可以对边缘进行定向,以使所有顶点的度数都非零。
证明(以及构造边缘方向的方法)留给读者。
答案 1 :(得分:1)
如果您遍历数组并构建图,则在A或B中遇到的每个唯一整数都将成为一个顶点,并且每对整数A [i]和B [i]都会在两个顶点之间创建边,然后该图最多具有2×N个顶点,因此该图所占用的空间与N成线性关系。
然后,对于图形中的每个边,我们将决定其方向,即,它连接的两个整数中的哪个将在数组C中使用。最后,我们将再次遍历数组,对于每对整数,我们查看图中的相应边以了解要使用哪个整数。
我认为,确定图中方向的操作都可以在线性时间内完成(如果我错了,请纠正我),所以整个算法应该具有O(N)的时间和空间复杂度。
确定图中边缘方向的规则如下:
遍历数组并查找图形中的相应边时,请在两个顶点多重连接时标记您已经使用的整数,以便第二次使用另一个整数。之后,您可以选择其中一个。
示例:
A = [1,6,2,9,7,2,5,3,4,10]
B = [5,8,3,2,9,7,1,2,8,3]
图:
1===5 6---8---4 9---2===3---10
| |
--7--
我们找到循环[1> 5> 1]和[9> 2> 7> 9],以及非循环子图中的最高整数8。
有向图:
1<=>5 6<--8-->4 9-->2<=>3-->10
^ |
|-7<-
结果:
C = [1,6,2,2,9,7,5,3,4,10]
第一个丢失的整数是8,因为我们必须牺牲它以保存[6,8,4]子图中的4和6。
答案 2 :(得分:1)
请检查此代码段,我已经用Java 8编写了
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
public class Run {
private int solution(int[] A) {
List<Integer> positiveIntegerList = Arrays.stream(A).distinct().filter(e -> e > 0).boxed().sorted(Comparator.naturalOrder()).collect(Collectors.toList());
final int i = 1;
if (!positiveIntegerList.isEmpty()) {
final int missingMax = positiveIntegerList.get(positiveIntegerList.size() - i) + i;
List<Integer> range = IntStream.rangeClosed(i, positiveIntegerList.get(positiveIntegerList.size() - i))
.boxed().collect(Collectors.toList());
AtomicInteger index = new AtomicInteger();
return range.stream().filter(e -> !e.equals(positiveIntegerList.get(index.getAndIncrement()))).findFirst().
orElse(missingMax);
} else {
return i;
}
}
public static void main(String[] args) {
Run run = new Run();
int[] intArray = new int[]{1, 3, 6, 4, 1, 2};
System.out.println(run.solution(intArray));
}
}
答案 3 :(得分:0)
我已经尝试了在Python3中解决此问题的方法。欢迎提出建议和反馈。谢谢。
-
from typing import List
class Solution:
def firstMissingPositive(self, nums: List[int]) -> int:
#Remove all the negative values from the list
positive_list = [i for i in nums if i > 0]
#Appending Zero to list. In case of no postive values in the list.
positive_list.append(0)
#Sort and remove duplicates from the list using Sorted and set function
sorted_postive_list = sorted(set(positive_list))
#starting with (index, value) --> (0,0), Compare index and value, and if they don't match then next value should be the smallest positive number
return next((a for a, b in enumerate(sorted_postive_list, sorted_postive_list[0]) if a != b), sorted_postive_list[-1]+1)
if __name__ == "__main__":
num = [1,2,3,0]
a = Solution()
print(a.firstMissingPositive(num))