简体   繁体   中英

How can I find the missing integer in a string of random non-repeating integers in a range

I'm having trouble even beginning to think of how to do this.

I need to find a missing number in a string of random numbers that don't have separators.

Here's an example: 14036587109 . In this example, the missing number is 2 , the range is 0-10 (inclusive).

How can I write a JavaScript/Node.JS program to solve this?

The part I can't figure out is how the program separates the numbers; In the example above, how would the program know that the number 10 (before the last number) isn't the numbers 1 and 0 .

There are two things we know about the missing integer: the total number of digits in the input tells us the number of digits in the missing integer, and (as @samgak mentioned in a comment) counting the occurrences of each digit in the input tells us which digits the missing integer is made of. This may give us a quick path to the solution, if one of the permutations of those digits is missing from the input. If it doesn't, then:

Find the integers from highest to lowest number of digits; if the range is eg 0-999, then search the 3-digit integers first, then 2, then 1.

If an integer is only present at one location in the input, mark it as found, and remove it from the input.

Then, start again with the longest integers that haven't been found yet, and look at the ones that are present at two locations; try both options, and then check whether all other integers that rely on the digits we're using are also present; eg if 357 is present at two locations:

... 1235789 ... 2435768 ...
      357         357
     23          43
    123         243
     235         435
       578         576
        78          76
        789         768

When trying the first location for the 357, check whether there is another possibility for 23, 123, 235, 578, 78, and 789. For the second location, check 43, 243, 435, 576, 76 and 768.

If these checks show that only one of the options is possible, mark the number as found and remove it from the input.

Go on to do this for shorter integers, and for integers that are present at 3, 4, ... locations. If, after doing this to a certain point, there is still no result, you may have to recursively try several options, which will quickly lead to a huge number of options. (With especially crafted large input, it is probably possible to thwart this method and make it unusably slow.) But the average complexity with random input may be decent.


Actually, when you find an integer that is only present in one location in the input, but it is a permutation of the missing digits, you should not remove it, because it could be the missing integer. So the algorithm might be: remove all integers you can unequivocally locate in the input, then try removing all possible missing integers one by one, and look for inconsistencies, ie other missing numbers that don't have the correct length or digits.


It's all a question of heuristics, of course. You try something simple, if that doesn't work you try something more complicated, if that doesn't work, you try something even more complicated... and at each step there are several options, and each one could be optimal for some input strings but not for others.

Eg if the range is 0-5000, you'd start by marking the 4-digit integers that are only present at one location. But after that, you could do the same thing again (because integers that were present twice could have had one of their options removed) until there's no more improvement, or you could check integers that are present twice, or integers that are present up to x times, or move on to 3-digit integers... I don't think there's a straightforward way to know which of these options will give the best result.

This solution should work for any input string and any start/end range:

We can think about the numbers in the string as a pool of digits that we can choose from. We start at startRange and go through to endRange , looking for each number along the way in our pool of digits.

When we find a number that can be composed from our pool of digits, we delete those digits from our pool of digits, as those digits are already being used to form a number in our range.

As soon as we come across a number that cannot be composed from our pool of digits, that must be the missing number.

 const str = "14036587109"; // input const numsLeft = str.split("").map(num => parseInt(num)); // array of numbers const startRange = 0; const endRange = 10; for(let i = startRange; i <= endRange ; i++) { // check if number can be formed given the numbers left in numsLeft const numFound = findNum(numsLeft, i); if(!numFound) { console.log("MISSING: " + i); // prints 2 break; } } function findNum(numsLeft, i) { // array of digits const numsToFind = String(i).split("").map(num => parseInt(num)); // default is true, if all digits are found in numsLeft let found = true; numsToFind.forEach(num => { // find digit in numsLeft const numFoundIndex = numsLeft.indexOf(num); if(numFoundIndex < 0) { // digit was not found in numsLeft found = false; return; } else { // digit was found; delete digit from numsLeft numsLeft.splice(numFoundIndex, 1); } }); return found; } 

var input = '10436587109';
var range = [10,9,8,7,6,5,4,3,2,1,0];
var expr1 = new RegExp(range.join('|'),'g');
var expr2 = new RegExp('[0-9]','g');

var a = input.match(expr1).map(Number).concat(input.match(expr2).map(Number));
var x = range.filter(function(i){ return a.indexOf(i)===-1; });

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM