我在序列中有大量数字,但缺少一个数字。如何使用Java 8+找出效率缺失的空白?
我就是这样:
public class PAMissingNumber {
public static void main(String[] args) {
List<Integer> listInteger = Arrays.asList(1, 2, 3, 4, 6, 7, 8, 9, 10); //imagine that this list is huge
Collections.sort(listInteger);
int result = 0;
int sequence = listInteger.get(0);
for (int i = 0; i < listInteger.size(); i++) {
if (sequence!= listInteger.get(i)) {
result = sequence;
break;
} else {
sequence++;
}
}
System.out.println("The missing number is : " + result);
}
}
有人可以帮我更有效地编码吗?
答案 0 :(得分:3)
Eugene’s answer指向正确的方向。如果列表未排序且并非始终以一个开头,则通用解决方案为
IntSummaryStatistics iss = listInteger.stream()
.mapToInt(Integer::intValue).summaryStatistics();
long from = iss.getMin(), to = iss.getMax(), sum = iss.getSum();
int diff = (int)((from+to)*(to-from+1)/2 - sum);
System.out.println(diff);
一种替代方法是使用BitSet
:
BitSet bs = listInteger.stream().collect(BitSet::new, BitSet::set, BitSet::or);
System.out.println(bs.nextClearBit(bs.nextSetBit(0)));
这确实需要一些临时存储,但是即使丢失了多个值,它仍然可以正常工作。
答案 1 :(得分:1)
如果您的电话号码以1
开头,那么实际上很简单。
所有数字的总和由公式x(x+1)/2
计算,这意味着您的列表是否为[1,2,3,4,5,6,7,8,9,10]
:
sum = 10 * 11 / 2 = 55;
您所要做的就是将所有数字相加并做一个差值(这也意味着列表中没有重复的数字):
List<Integer> listInteger = Arrays.asList(1, 2, 3, 4, 6, 7, 8, 9, 10);
int max = Collections.max(listInteger);
int sum = max * (max + 1) / 2;
int diff = sum - listInteger.stream().mapToInt(Integer::intValue).sum();
System.out.println(diff);
考虑到Kartik的好评,可以写成:
List<Integer> listInteger = Arrays.asList(2, 3, 4, 6, 7, 8);
IntSummaryStatistics summaryStatistics =
listInteger.stream()
.collect(Collectors.summarizingInt(Integer::intValue));
int max = summaryStatistics.getMax();
int min = summaryStatistics.getMin();
int sum = (int) summaryStatistics.getSum();
System.out.println((max - min + 1) * (max + min) / 2 - sum);