上周我参加了面试。他们问一个问题,找到一个整数值的重复元素。我知道程序使用数组,但他们问我没有数组。请帮我找到没有数组的整数中的重复元素。
问题:
从整数中查找重复元素,显示没有重复数字的元素。像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;
}
答案 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}}值。这导致了long
和get_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));
}