从整数中查找重复元素

时间:2016-10-21 01:06:50

标签: c++ c

上周我参加了面试。他们问一个问题,找到一个整数值的重复元素。我知道程序使用数组,但他们问我没有数组。请帮我找到没有数组的整数中的重复元素。

问题:

从整数中查找重复元素,显示没有重复数字的元素。像I / P:43456 O / P:4356。条件:不应使用数组

编码:

void printRepeating(int arr[], int size) {
    int i;
    printf("The repeating elements are: \n");
    for (i = 0; i < size; i++) {
        if (arr[abs(arr[i])] >= 0)
            arr[abs(arr[i])] = -arr[abs(arr[i])]; elseprintf(" %d ", abs(arr[i]));
    }
}
int main() {
    int arr[] = { 1, 2, 3, 1, 3, 6, 6 };
    int arr_size = sizeof(arr) / sizeof(arr[0]);
    printRepeating(arr, arr_size);
    getchar();
    return 0;
}

3 个答案:

答案 0 :(得分:2)

我实际上理解这个问题意味着应该给出一个整数,而不是一个整数数组:

  

他们问了一个问题,即找到一个整数值的重复元素。

这是一个解决此问题的解决方案。在我的原始解决方案中,主要功能是递归的。这个功能似乎有效,但是我误解了这个问题要求首先从低位数字中取出重复的数字。我的递归解决方案首先删除了高位数字。这意味着,对于提供的示例输入,User评估为43456而不是所需的3456

我重新设计了4356功能以满足此要求。它不再是递归的。该功能通过消耗输入数字来建立一个新数字,取出最高位数,并在删除重复数据后将其与剩余数字的最高位数组合。

使用了三个辅助函数。 remove_dups()函数用于从数字中删除所有出现的数字。 remove_digits()get_place()函数用于获取给定位置的数字,其中地点由1,10,100,...表示,并从给定位置移除数字,分别

以下是remove_place()函数如何工作的示例:

get_place()

get_place(1234, 100) --> (1234 % (10 * 100) - 1234 % 100) / 100 --> (1234 % 1000 - 1234 % 100) / 100 --> (234 - 34) / 100 --> 200 / 100 --> 2 函数的工作原理示例:

remove_place()

更新

我最初发布的代码没有处理负数。这是因为当我最初使用负数进行测试时,结果不正确。在这个破碎的版本中,我在函数中使用了remove_place(1234, 100) --> (1234 / (10 * 100)) * 100 + 1234 % 100 --> (1234 / 1000) * 100 + 34 --> 1 * 100 + 34 --> 100 + 34 --> 134 个值,long参数除外,它们是plc。我错误地认为这个问题与模数运算符有关,只是将所有内容都更改为unsigned long。似乎将所需的负数转换为正数,然后将结果乘以-1就足够简单了。以下是原始破损代码的函数原型:

unsigned

但进一步的考虑表明,原始问题是long get_place(long num, unsigned long plc); long remove_place(long num, unsigned long plc); long remove_digits(long num, long d); long remove_dups(long num); 值无法转换为unsigned long值,因为long值无法表示为unsigned long 1}}值。这导致了longget_place()函数中的一些垃圾结果。将所有内容更改为remove_place()可解决此问题,但代价是排除负输入值。但是,通过更好地理解问题,我更改了所有函数参数并将值返回到unsigned long类型。这解决了问题,并允许正确处理负输入值。

以下是代码:

long

以下是一些示例输出:

#include <stdio.h>

long get_place(long num, long plc);
long remove_place(long num, long plc);
long remove_digits(long num, long d);
long remove_dups(long num);

int main(void)
{
    long number;

    printf("Enter a number (q to quit): ");
    while (scanf("%ld", &number) == 1) {
        printf("%ld\n", remove_dups(number));
        printf("Enter a number (q to quit): ");
    }

    return 0;
}

/* return digit at plc = 1, 10, 100, ... */
long get_place(long num, long plc)
{
    return (num % ( 10 * plc) - num % plc) / plc;
}

/* remove digit at plc = 1, 10, 100, ..., and return result */
long remove_place(long num, long plc)
{
    return (num / (10 * plc)) * plc + num % plc;
}

/* remove all occurrences of d in num and return result */
long remove_digits(long num, long d)
{
    long place = 1;
    while (num / place) {
        if (get_place(num, place) == d)
            num = remove_place(num, place);
        else
            place *= 10;
    }

    return num;
}

long remove_dups(long num)
{
    long result, next_digit;
    long last_place = 1;

    result = 0;
    while (num) {
        for(last_place = 1; (num / (10 * last_place)); last_place *= 10)
            continue;

        next_digit = get_place(num, last_place);
        result = result * 10 + next_digit;
        num = remove_digits((num % last_place), next_digit);
    }
    return result;
}

答案 1 :(得分:1)

这是一个粗略的草图:

对于输入中的每个整数,将输入移向开头,并将每个整数与当前整数进行比较。如果匹配,则转到下一个输入整数。如果你到达开头,它不是重复的,所以打印它。

void printRepeating(const int arr[], size_t size) {
    const int* begin = arr;
    const int* end = arr + size;
    if ( begin == end ) return;
    // First element cannot be a duplicate, so always print it
    std::cout << *begin;
    // Traverse input array
    const int* curr = begin;
    while ( ++curr < end ) {
        // Traverse back to find a duplicate
        const int* curr_rev = curr - 1;
        for ( ; curr_rev >= begin && *curr != *curr_rev; --curr_rev );
        if ( curr_rev < begin )
            // Reached the beginning, so it cannot be a duplicate
            std::cout << " " << *curr;
    }
}

虽然我不确定,是否在数组未定义行为之前构造指向元素的指针,这是一个轻微的变化,它从前到后遍历输入以找到重复。这只是主循环 - 其他一切如上:

    // Traverse input array
    const int* curr = begin;
    while ( ++curr < end ) {
        // Traverse again to find a duplicate
        const int* cmp = begin;
        for ( ; cmp < curr && *cmp != *curr; ++cmp );
        if ( cmp == curr )
            // Reached current integer, so it cannot be a duplicate
            std::cout << " " << *curr;
    }

鉴于此计划:

int main() {
    const int arr[]{ 1, 2, 3, 1, 3, 6, 6 };
    printRepeating( arr, std::end( arr ) - std::begin( arr ) );
}

产生以下输出:

1 2 3 6

答案 2 :(得分:0)

为您的例子

  

I / P:43456 O / P:4356

考虑这一点的一种方法是,只有当数字不在数字的更重要部分中时,才输出数字。因此,我们通过从最小到最重要的每个数字。如果数字(lastdig(num))出现在数字(butlastdig(num))的更重要部分,我们将其丢弃,否则我们会保留它。

#include <stdbool.h>
#include <stdio.h>

inline unsigned lastdig(unsigned n) { return n%10; }
inline unsigned butlastdig(unsigned n) { return n/10; }
inline bool is_single_digit(unsigned n) { return n<10; }

bool is_in(unsigned digit, unsigned num)
{
    if (is_single_digit(num))
        return digit==num;
    else
        return (digit==lastdig(num)) || is_in(digit, butlastdig(num));
}

unsigned unique(unsigned num)
{
    unsigned last, butlast;

    if (is_single_digit(num))
        return num;
    last=lastdig(num);        
    butlast=unique(butlastdig(num));

    if (is_in(last, butlast))
        return butlast;
    else
        return butlast*10 + last;
}

main(int argc, char **argv)
{
    int i=atoi(argv[1]);
    if (i < 0)
        printf("nonnegative numbers only\n");
    else
        printf("%u %u\n", i, unique(i));
}