Java 缺少多个数字的未排序数组
给定一个大小为N的数组,其中有多个等于-1的缺失数字,我需要找到缺失的数字并打印更新的数组,数组中[1-N]中的所有数字都不允许对数组进行排序 我试着先在纸上解决它,但没能 例如: 数组[2,4,6,5,-1,8,-1] 结果: [2,4,6,5,3,8,7]或[2,4,6,5,3,8,7]它们中的任何一个都是好的,并且其时间复杂度应该更高 即使是一个提示也有助于实现对缺失数字的查找,当Java 缺少多个数字的未排序数组,java,Java,给定一个大小为N的数组,其中有多个等于-1的缺失数字,我需要找到缺失的数字并打印更新的数组,数组中[1-N]中的所有数字都不允许对数组进行排序 我试着先在纸上解决它,但没能 例如: 数组[2,4,6,5,-1,8,-1] 结果: [2,4,6,5,3,8,7]或[2,4,6,5,3,8,7]它们中的任何一个都是好的,并且其时间复杂度应该更高 即使是一个提示也有助于实现对缺失数字的查找,当c为常数时,O(c*N)仍然是线性时间。这意味着“线性时间”要求仍然允许您在阵列上进行多次传递,只要传递的数量
c
为常数时,O(c*N)仍然是线性时间。这意味着“线性时间”要求仍然允许您在阵列上进行多次传递,只要传递的数量不变。(只要通过次数不是N
的函数)
因此:
过程1:使用所有值(缺失值和存在值)填充贴图
传递2:从映射中删除数组中可以找到的每个值
第3步:将数组中的每个-1
替换为映射中的一个数字,从映射中删除该数字。O(c*N)
在c
为常数时仍然是线性时间。这意味着“线性时间”要求仍然允许您在阵列上进行多次传递,只要传递的数量不变。(只要通过次数不是N
的函数)
因此:
过程1:使用所有值(缺失值和存在值)填充贴图
传递2:从映射中删除数组中可以找到的每个值
第3步:用映射中的数字替换数组中的每个
-1
,从映射中删除该数字。用数字1-n填充位集:
BitSet bits = new BitSet(n + 1);
bits.set(1, n + 1, true);
迭代数组,取消位集中非-1的位:
for (int b : arr) {
if (b != -1) bits.clear(b);
}
迭代数组并用位集中的一个设置位替换-1s:
for (int a = 0, prev = 0; a < arr.length; ++a) {
if (arr[a] == -1) {
arr[a] = prev = bits.nextSetBit(prev + 1);
}
}
for(int a=0,prev=0;a
用数字1-n填充位集:
BitSet bits = new BitSet(n + 1);
bits.set(1, n + 1, true);
迭代数组,取消位集中非-1的位:
for (int b : arr) {
if (b != -1) bits.clear(b);
}
迭代数组并用位集中的一个设置位替换-1s:
for (int a = 0, prev = 0; a < arr.length; ++a) {
if (arr[a] == -1) {
arr[a] = prev = bits.nextSetBit(prev + 1);
}
}
for(int a=0,prev=0;a
好吧,这是我的尝试。它必须比我原来想象的做更多的簿记工作
int[] vals = { 2, -1,6,-1,-1};
// min value is the start of the sequence
int min = Integer.MAX_VALUE;
int bitmap = 0;
// records the -1 indices.
List<Integer> missing = new ArrayList<>();
// loops at most n times.
for (int i = 0; i < vals.length; i++) {
int v = vals[i];
if (v >= 0) {
// set value in bitmap
bitmap |= (1 << v);
// and find minimum entry
if (v < min) {
min = v;
}
} else {
// save index of missing numbers.
missing.add(i);
}
}
// get rid of low order zero bits.
bitmap>>=min;
int i = 0;
// Loops at most, n times
while(!missing.isEmpty()) {
// check bitmap for a missing number in sequence
if ((bitmap & 1) == 0) {
// and fill it in
vals[missing.get(0)] = i + min;
missing.remove(0);
}
bitmap>>=1;
i++;
}
System.out.println(Arrays.toString(vals));
int[]vals={2,-1,6,-1,-1};
//最小值是序列的开始
int min=整数最大值;
int位图=0;
//记录-1指数。
缺少列表=新建ArrayList();
//循环次数最多为n次。
对于(int i=0;i=0){
//在位图中设置值
位图|=(1>=最小值;
int i=0;
//循环次数最多为n次
而(!missing.isEmpty()){
//按顺序检查位图是否缺少数字
如果((位图&1)==0){
//填写
VAL[缺少。获取(0)]=i+min;
缺失。删除(0);
}
位图>>=1;
i++;
}
System.out.println(Arrays.toString(vals));
好吧,这是我的尝试。它必须比我原来想象的做更多的簿记工作
int[] vals = { 2, -1,6,-1,-1};
// min value is the start of the sequence
int min = Integer.MAX_VALUE;
int bitmap = 0;
// records the -1 indices.
List<Integer> missing = new ArrayList<>();
// loops at most n times.
for (int i = 0; i < vals.length; i++) {
int v = vals[i];
if (v >= 0) {
// set value in bitmap
bitmap |= (1 << v);
// and find minimum entry
if (v < min) {
min = v;
}
} else {
// save index of missing numbers.
missing.add(i);
}
}
// get rid of low order zero bits.
bitmap>>=min;
int i = 0;
// Loops at most, n times
while(!missing.isEmpty()) {
// check bitmap for a missing number in sequence
if ((bitmap & 1) == 0) {
// and fill it in
vals[missing.get(0)] = i + min;
missing.remove(0);
}
bitmap>>=1;
i++;
}
System.out.println(Arrays.toString(vals));
int[]vals={2,-1,6,-1,-1};
//最小值是序列的开始
int min=整数最大值;
int位图=0;
//记录-1指数。
缺少列表=新建ArrayList();
//循环次数最多为n次。
对于(int i=0;i=0){
//在位图中设置值
位图|=(1>=最小值;
int i=0;
//循环次数最多为n次
而(!missing.isEmpty()){
//按顺序检查位图是否缺少数字
如果((位图&1)==0){
//填写
VAL[缺少。获取(0)]=i+min;
缺失。删除(0);
}
位图>>=1;
i++;
}
System.out.println(Arrays.toString(vals));
您发布的两个数组似乎是相等的。“它们中的任何一个都很好”为什么不包含1?@AndyTurner,因为只缺少两个数组,这意味着缺少1、3和7,因为最大值为8,它们需要构成一个范围。@WJS“数组中从[1-n]开始的所有数字是多少?”那么是什么意思?@AndyTurner我想这是在显示一个合法范围的值。所以[1-n]的任何子范围都是有效的。你发布的两个数组似乎是相等的。“它们中的任何一个都是好的”为什么不包含1?@AndyTurner,因为只缺少两个,这意味着缺少1、3和7,因为最大值为8,它们需要构成一个范围。@WJS“从[1-n]开始的数组中的所有数字”是什么意思?@AndyTurner我认为这显示了一个合法范围的值。那么[1-n]的任何子范围将是有效的。在实践中,对于除超大数据集以外的任何数据集,这可能比我的映射解决方案更有效。但在理论上,这可能没有线性运行时间,因为nextSetBit()
函数可能会对下一位执行线性搜索。(我不确定这一点,但我无法想象他们还能如何实现它。)因此,nextSetBit()
的时间复杂度是N
的函数,随后是N
wherenextSetBit()上循环的时间复杂度
被使用为N
平方。@MikeNakis不,它仍然是线性的。您不必每次都从位集的开头开始搜索。气泡排序中的内部循环也不是每次都从数组的开头开始,但它仍然被视为O(N^2)
算法。这是