从整数中查找重复元素
Find the duplicate element from an integer
上周我参加了面试。他们问了一个在整数值中寻找重复元素的问题。我知道程序使用数组,但他们要求我不用数组。请帮我在没有数组的整数中找到重复的元素。
问题:
从整数中查找重复的元素,显示没有重复编号的元素。如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;
}
我实际上理解这个问题的意思是应该给出一个整数,而不是整数数组作为输入:
他们问了一个在整数值中查找重复元素的问题。
这里有一个解决这个问题的方法。在我最初的解中,主函数是递归的。这个函数似乎可以工作,但是我误解了这个问题要求首先从低阶数字中取出重复的数字。我的递归解先去除了高阶数字。这意味着对于提供的样本输入,43456
求值为3456
,而不是期望的4356
。
我重新设计了remove_dups()
函数来满足这个要求。它不再是递归的。该函数通过使用输入的数字,除去重复项后,取最高阶数字并将其与剩余数字中的最高阶数字组合,从而构建一个新数字。
使用了三个辅助函数。remove_digits()
函数用于从一个数字中删除所有出现的数字。get_place()
和remove_place()
函数用于在给定的位置上获取一个数字,其中一个位置用1,10,100,…
下面是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
。我错误地认为这个问题与模数运算符有关,只是将所有内容更改为unsigned
。将想要的负数转换为正数,然后将结果乘以-1,似乎很简单。下面是原始代码的函数原型:
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
值不能表示为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("%ldn", 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;
}
下面是一些示例输出:
Enter a number (q to quit): -43456
-4356
Enter a number (q to quit): 43456
4356
Enter a number (q to quit): -12321
-123
Enter a number (q to quit): 299792458
297458
Enter a number (q to quit): 0
0
Enter a number (q to quit): 1
1
Enter a number (q to quit): -1
-1
Enter a number (q to quit): q
标题>这是一个草图:
对于输入中的每个整数,从开始遍历输入,并将每个整数与当前整数进行比较。如果有匹配,则继续下一个输入整数。如果你到达开头,它不是重复的,所以打印它。
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
对于您的示例
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 onlyn");
else
printf("%u %un", i, unique(i));
}
- 使用堆查找第K个最大元素的时间复杂性
- 查找矩阵C++中每一列和每一行的最小和最大元素
- C++如何在向量中查找最常见的元素
- 查找两个排序向量中共有的元素
- 在对向量中查找元素的索引
- 查找数组中第一个最小值和最后一个最大值元素之间的算术平均值
- 查找矩阵中单元格的相邻元素
- 为什么使用数组元素查找最大数字的程序不起作用?
- 查找第一个数组中不存在的元素
- 查找最小的下一个更大的元素
- 在最小堆中查找最大元素
- 在向量中查找大于 0(或通常为 k)的最小元素的最佳方法是什么?
- set::find 查找不存在的元素
- 在集合中查找使用结构C++的元素
- 从斐波那契序列 c++ 中的数组中查找正确的元素时出错
- 用于查找数组中最大元素的出现次数的代码,给出分段错误
- 查找数组中指示性较大但数组中值较小的元素
- C++结构集无法按元素查找/擦除
- 如何在OpenCV中使用Matlab的512元素查找表数组?
- 使用数组的元素查找总和'k'