Click here to Skip to main content
15,891,905 members
Please Sign up or sign in to vote.
2.40/5 (5 votes)
See more:
There're 1 million numbers.All of them are 1~9.
like 1, 4, 6, 7, 7, 9,.....,2, 3
There's only one number repeated twice, how to find it out quickly?(c/c++)
P.S There digits are random inserted.

Sorry to all, I isn't good at English, It may be Ambiguity.
In the 1000000 digits , there's only one repeated twice, not one , not three, only twice.
The others may appear only once, may not appear, or may repeated 999998 times.
Posted
Updated 29-Jul-11 5:26am
v4
Comments
walterhevedeich 28-Jul-11 5:22am    
I smell homework. Is it? :)
YvesDaoust 29-Jul-11 4:52am    
A very nice example of how ambiguous a problem statement can be !
YvesDaoust 29-Jul-11 13:53pm    
Then see Solution 6, 1a.

Assuming the duplicate is randomly inserted, and that you mean there is only one position in the sequence where the same digit is repeated next to itself, then the only way to do it is to start at the beginning or the end and look at each pair of digits.
 
Share this answer
 
Comments
YvesDaoust 28-Jul-11 5:39am    
@OriginalGriff: in the meantime I deleted solution 1 (and couldn't read your comment in full). Was based on the assumtion that the digit is repeated twice regardless of ordering. On second thoughts very unlikely to be the true problem :)
YvesDaoust 29-Jul-11 4:30am    
This solution cannot be checked because it does not say what to do in the case of a digit repeated thrice.
You will not learn if we do your homework for you!

However, OriginalGriff's answer is the easiest solution, a plodding, donkey-work way of doing it, but probably the simplest one in order for you to get a pass on the work from your tutor.

Best of luck.
 
Share this answer
 
Comments
irshinning 28-Jul-11 21:59pm    
Sorry, I‘ve graduated from college for two years.
It's just an interview test question I found from internet. There may be lots solutions, but I want the most efficient one.
Anyway, thanks for your answer.
This is trivial: keep a trace of the previous digit processed and compare to the current one. Stop at equal.

C++
int Was= Digit[0];
for (i= 1; i < 1000000 && Was != Digit[i]; i++)
    Was= Digit[i];

if (i < 1000000) printf("Digit %d at positions %d and %d\n", Was, i - 1, i);
 
Share this answer
 
Comments
mbue 28-Jul-11 16:38pm    
Sorry you forgot the sort:

unsigned int findtwice(int* array,const unsigned int count)
{
enum{ NOTFOUND=-1 };
typedef struct { static int cmpi(void* a,void* b){ return *(int*)a-*(int*)b; } }_;
unsigned int i;
qsort(array,count,sizeof(int),_::cmpi);
for(i=1;(i<count)&&(array[i-1]!=array[i]);i++);
return i<count?i-1:NOTFOUND;
}

Regards.
irshinning 28-Jul-11 22:08pm    
Thanks for your solutions, YvesDaoust and mbue ^^
You've used qsort that's OK, but complexity of qsort is n*log(n). It isn't efficient enough I think..
YvesDaoust 29-Jul-11 4:28am    
YvesDaoust's solution is wrong, it accepts digits repeated thrice or more in a row.

mbue's solution is wrong, it accepts digits repeated thrice or more. And indeed qsorting is overkill, a histogram suffices and is O(n).
Well, simple way is to keep the last number kipping in mind and compare with the next number, if succeed stop if fail keep the next number in mind and look for the next number.

grow up
 
Share this answer
 
Comments
YvesDaoust 29-Jul-11 4:29am    
Also wrong for three times the same digit in a row.
Mohibur Rashid 29-Jul-11 4:51am    
First of all i dont know what is the above thing, I just answered according what the person asked. that is all
This is very simple if repeated numbers are on neighboring positions (by the way, sorting will not help):
C#
int list[] = {1,3,2,3,8,5,7,7,9};

bool main()
{

     for(int i=0;i<9;i++)
        {
         if (list[i]==list[i+1])
            {
            printf("position: %x, number: %x\n",i,list[i]);
            return true;
            }
        }

    printf("No repeated numbers found!\n");
    return false;
}

This is, actually, the obvious solution described by OriginalGriff.

Update (corrected after comments from YvesDaoust, see below):

1. Miscalculated the size of array.
2. To handle more than two repeated numbers in the row:
C#
int list[] = {1,3,3,3,8,5,7,7,9,5};

bool main()
{

     for(int i=0;i<9;i++)
        {
         if (list[i]==list[i+1])
            {
            if ((list[i+1]!=list[i+2])&&(list[i]!=list[i-1]))
                {
                printf("position: %x, number: %x\n",i,list[i]);
                return true;
                }
            }
        }

    printf("No only twice repeated numbers found!\n");
    return false;
}


3. I always try to follow the requirements given. Here - to make the search as efficient as possible.

P.S. How nice it could be if someone would point on errors in code proposing the right solution!
 
Share this answer
 
v6
Comments
YvesDaoust 29-Jul-11 9:57am    
See my comments to Solution 2 and Solution 4.

Caution, i<9 should be i<8.
Sergey Chepurin 29-Jul-11 10:33am    
1. Here should be i<9 (0<->8).
2. From the sample numbers provided and short description most of us assume that the requirements are: find the only two repeated numbers on neighboring positions out of one million random numbers from 1 to 9.
3. Sorting will not help in this case.
4. It is not obvious if sorting previous to search will gain the better results if two repeated numbers are on random positions.
YvesDaoust 29-Jul-11 10:02am    
"Sorting will not help": sorting solves another problem, repeated numbers not necessarily neighboring each other. (And does it in an unefficient way.)
YvesDaoust 29-Jul-11 13:47pm    
1. Sorry, list[8+1] does not exist.
2. Agreed. What about three repeated numbers on neighboring positions?
3. Sorting will solve a different problem.
4. Sorting is overkill. Frequency counting is enough.
C#
string millionNumbers = "...";
int repeated = -1;
for (int i =0; i <= 9; i++)
{
    string search = string.Format("{0},{0}", i);
    if (millionNumbers.Contains(search))
    {
        repeated = i;
        break;
    }
}
 
Share this answer
 
Comments
YvesDaoust 29-Jul-11 9:55am    
Unfortunately, this is doing 9 passes over the string, where 1 suffices.
#realJSOP 29-Jul-11 10:35am    
...only if the repeating number is 9. There's always a possibility of 9 passes, and always a possibility of just 1 pass.
YvesDaoust 29-Jul-11 13:51pm    
Well observed, 5 passes on average.
As the expression "repeated twice" sound a bit pleonastic to me, I cannot help imagining different interpretations, hence different algorithms.

1. A digit that is "repeated" can be a digit that appears two times or more in the sequence, anywhere. 1, 2, 3, 4, 2, 5, 2 has 2 repeated.

1a. With the meaning of (1.), "repeated twice" would mean appearing exactly two times, anywhere. 1, 2, 3, 4, 2, 5, 6 has 2 repeated twice.

1b. But doesn't it make more sense to say that when a digit is repeated two times, that means two copies in addition to the original. Hence, three instances ! With this interpretation 1, 2, 2, 7, 2, 4, 5 has 2 repeated twice.

2. Or "repeated" can be a digit that appears two times or more in a row in the sequence. 1, 2, 2, 2, 2, 2, 4, 5 has 2 repeated.

2a. With the meaning of (2.), "repeated twice" can be appearing exactly two times in a row, not more. 1, 2, 2, 4, 5 has 2 repeated twice. 1, 2, 2, 2, 4, 5 does not have 2 repeated twice.

2b. As in (1a.), consider two extra copies. Here 1, 2, 2, 2, 4, 5 has 2 repeated twice.

2c. But don't let's forget another interpretation: some digit can be repeated, as in (1.), and this occurs twice. I.e. 1, 2, 2, 2, 4, 3, 6, 2, 2, 9 has 2 repeated twice.

The algorithms:
1a. Compute the histogram of frequencies and find the bin where frequency = 2.

1b. Compute the histogram of frequencies and find the bin where frequency = 3.

2a. Keep a counter and keep the value of the previous digit. When you process a digit, if same as previous increment the counter; otherwise { if the counter is 2, stop } and reset the counter. In the end, check if the counter is 2.

2b. Keep a counter and keep the value of the previous digit. When you process a digit, if same as previous increment the counter; otherwise { if the counter is 3, stop } and reset the counter. In the end, check if the counter is 3.

2c. The hardest: compute an histogram of digit replications while keeping a counter and the value of the previous digit. When you process a digit, if same as previous increment the counter; otherwise, { if the counter is greater than 1, increment the corresponding bin } and reset the counter. In the end, if the counter is greater than 1, increment the corresponding bin. Find the bin where frequency = 2.


Important: following this analysis, none of the solutions proposed before are correct because they accept sequences longer than twice the same character.
 
Share this answer
 
v6
Comments
Аslam Iqbal 30-Jul-11 14:24pm    
I like your way of thinking. my 5
YvesDaoust 30-Jul-11 17:52pm    
Thanks.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900