问题描述
问题陈述:
给出一个32位带符号整数,整数的倒数。
注意:假设我们正在处理一个只能存储的环境 32位有符号整数范围内的整数:[−2 ^ 31,2 ^ 31 − 1]。对于 为此问题的目的,假定您的函数在以下情况下返回0 反向整数溢出。
我正在尝试实现递归函数reverseRec(),它适用于较小的值,但是对于边缘情况却一团糟。
int reverseRec(int x)
{
if(abs(x)<=9)
{
return x;
}
else
{
return reverseRec(x/10) + ((x%10)*(pow(10,(floor(log10(abs(x)))))));
}
}
int reverse(int x)
{
long long val = 0;
do{
val = val*10 + (x%10);
x /= 10;
}while(x);
return (val < INT_MIN || val > INT_MAX) ? 0 : val;
}
在这里,我使用long long类型的变量 val 来检查带符号int类型的 MAX 和 MIN 的结果,但是问题特别提到我们需要在32位整数范围内进行处理,尽管以某种方式被接受,但我只是好奇是否有一种方法可以仅使用int数据类型来实现递归函数?
还有一件事情,即使我考虑使用long long,也无法在递归函数reverseRec()中实现它。
解决方法
是否有一种方法可以仅使用
int
数据类型来实现递归函数?
(和)在取反的整数溢出时返回0
是的
对于此类+/-问题,我喜欢将int
值折叠到一侧并根据需要取反。折叠到一侧(-或+)可简化溢出检测,因为只有一侧需要测试
我宁愿折叠到负数一面,因为负数比正数多。 (使用32位int
,对于此问题确实没有任何影响。)
由于代码形成了相反的值,因此请测试以下r * 10 + least_digit
是否可能溢出。
仅int
的递归解决方案,用于反转int
。溢出返回0。
#include <limits.h>
#include <stdio.h>
static int reverse_recurse(int i,int r) {
if (i) {
int least_digit = i % 10;
if (r <= INT_MIN / 10 && (r < INT_MIN / 10 || least_digit < INT_MIN % 10)) {
return 1; /// Overflow indication
}
r = reverse_recurse(i / 10,r * 10 + least_digit);
}
return r;
}
// Reverse an int,overflow returns 0
int reverse_int(int i) {
// Proceed with negative values,they have more range than + side
int r = reverse_recurse(i > 0 ? -i : i,0);
if (r > 0) {
return 0;
}
if (i > 0) {
if (r < -INT_MAX) {
return 0;
}
r = -r;
}
return r;
}
测试
int main(void) {
int t[] = {0,1,42,1234567890,1234567892,INT_MAX,INT_MIN};
for (unsigned i = 0; i < sizeof t / sizeof t[0]; i++) {
printf("%11d %11d\n",t[i],reverse_int(t[i]));
if (t[i] != INT_MIN) {
printf("%11d %11d\n",-t[i],reverse_int(-t[i]));
}
}
}
输出
0 0
0 0
1 1
-1 -1
42 24
-42 -24
1234567890 987654321
-1234567890 -987654321
1234567892 0
-1234567892 0
2147483647 0
-2147483647 0
-2147483648 0
,
您可以添加第二个参数:
int reverseRec(int x,int reversed)
{
if(x == 0)
{
return reversed;
}
else
{
return reverseRec(x/10,reversed * 10 + x%10);
}
}
并调用传递第二个参数0的函数。如果需要负数,可以先检查符号,然后将绝对值传递给该函数。
,在尝试学习C编程时,我编写了这个问题,并得到了一些正确的结果和一些不正确的结果。我看不出差异的原因。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h> // requires adding link to math -lm as in: gcc b.c -lm -o q11
int ReverseInt(int startValue,int decimalPlace)
{
if(decimalPlace == 0) // if done returns value
{
return startValue;
}
int temp = startValue % 10; // gets units digit
int newStart = (startValue -temp)/10; // computes new starting value after removing one digit
int newDecimal = decimalPlace -1;
int value = temp*pow(10,decimalPlace);
return value + ReverseInt(newStart,newDecimal); // calls itself recursively until done
}
int main()
{
int x,decimalP,startValue;
printf("Input number to be reversed \n Please note number must be less than 214748364 :");
scanf("%d",&x);
if (x > 214748364)
{
printf("Input number to be reversed \n Please note number must be less than 214748364 :");
scanf("%d",&x);
}
decimalP = round(log10(x)); // computes the number of powers of 10 - 0 being units etc.
startValue = ReverseInt(x,decimalP); // calls function with number to be reversed and powers of 10
printf("\n reverse of %d is %d \n",x,startValue);
}
,输出为:1234的倒数是4321,然后4321的倒数是12340
我假设通过反转整数来表示将129转换为921或将120转换为21。
您需要一个初始方法来初始化您的递归函数。 您的递归函数必须计算出整数使用的小数位数。可以使用以10为底的对数值,然后将结果转换为整数来找到它。
-
大约
- log10(103) 2.04 => 2
将初始值乘以10以得到该位置并将其存储在名为temp的变量中 从初始值中减去该位置,并将其存储在名为newStart的变量中。
- 将该值除以10
从小数点后一位减去并存储在另一个名为newDecimal的变量中。
将乘数乘以10到小数点的幂,然后将其添加到初始值为newStart而小数位为newDecimal的函数中。
#include <stdio.h>
#include <math.h>
int ReverseInt(int startValue,int decimalPlace);
int main()
{
int i = -54;
int positive = i < 0? i*-1 : i;
double d = log10(positive);
int output = ReverseInt(positive,(int)d);
int correctedOutput = i < 0? output*-1 : output;
printf("%d \n",correctedOutput);
return 0;
}
int ReverseInt(int startValue,int decimalPlace)
{
if(decimalPlace == 0)
{
return startValue;
}
int temp = startValue % 10;
int newStart = (startValue -temp)/10;
int newDecimal = decimalPlace -1;
int value = temp*pow(10,newDecimal);
}
,
已经很晚了,没有比我更好的事情了。没有浮点计算。当然,整数必须足够大以容纳结果。否则是UB。
int rev(int x,int partial,int *max)
{
int result;
if(x / partial < 10 && (int)(x / partial) > -10)
{
*max = partial;
return abs(x % 10) * partial;
}
result = rev(x,partial * 10,max) + abs(((x / (int)(*max / partial)) % 10) * partial);
return result;
}
int reverse(int x)
{
int max;
return rev(x,&max) * ((x < 0) ? -1 : 1);
}
int main(void){
printf("%d",reverse(-456789));
}
unsigned rev(unsigned x,unsigned partial,unsigned *max)
{
unsigned result;
if(x / partial < 10)
{
*max = partial;
return (x % 10) * partial;
}
result = rev(x,max) + (x / (*max / partial) % 10) * partial;
return result;
}
unsigned reverse(unsigned x)
{
unsigned max;
return rev(x,&max);
}
int main(void){
printf("%u",reverse(123456));
}
当使用long long存储结果时,所有可能的整数都可以反转
long long rev(int x,long long partial,long long *max)
{
long long result;
if(x / partial < 10 && (int)(x / partial) > -10)
{
*max = partial;
return abs(x % 10) * partial;
}
result = rev(x,max) + abs(((x / (int)(*max / partial)) % 10) * partial);
return result;
}
long long reverse(int x)
{
long long max;
return rev(x,&max) * ((x < 0) ? -1 : 1);
}
int main(void){
printf("%d reversed %lld\n",INT_MIN,reverse(INT_MIN));
printf("%d reversed %lld\n",reverse(INT_MAX));
}