给定两个整数,分别表示分数的分子 numerator 和分母 denominator,以字符串形式返回小数。
如果小数部分为循环小数,则将循环的部分括在括号内。
示例 1:
输入: numerator = 1, denominator = 2 输出: "0.5"
示例 2:
输入: numerator = 2, denominator = 1 输出: "2"
示例 3:
输入: numerator = 2, denominator = 3 输出: "0.(6)"
这条题目说简单简单。。但是自己实现起来就各种问题。。。
一开始的思路是碰到重复的余数就说明进入了循环,但调试的时候发现不行,比如说1/6,前两次余数都是4。。。后来我改进成被除数。。但是由于我一开始用的是一个长度根据被除数确定的hash表,所以碰到INT_MIN的时候,内存不够了。。。再改。。。然后就是把小数部分和整数部分结合的时候。。。如果是循环小鼠的话,需要在循环部分加 ( ) 。这一段代码弄了很久。。。主要是之前写的贼几把乱。。脑子也贼几把乱。。。最后就是溢出的问题。。。真特么蛋疼。。。总之下面是我的代码,还是很乱。。但至少跑出来了,用时4ms。。。最下面是大佬的代码。。
char* i2a(int num) { char *s=(char *)malloc(sizeof(char)*12); int i=0,j=0; unsigned n; if(num<0) { n=(unsigned)-num; s[i++]='-'; j++; } else n=(unsigned)num; do { s[i++]=n%10+'0'; n/=10; } while(n); s[i--]=0; char tmp; while(j<i) { tmp=s[j]; s[j++]=s[i]; s[i--]=tmp; } return s; } int contain(int *visited,int x,int size) { int i; for(i=0;i<size;i++) if(visited[i]==x) return i+1; return 0; } char* fractionToDecimal(int numerator, int denominator) { long long x,y; int i,j,pos,size=0,flag; x=numerator<0?(unsigned)-numerator:numerator; y=denominator<0?(unsigned)-denominator:denominator; flag=(numerator<0)^(denominator<0); char *integer; if(numerator==INT_MIN&&denominator==-1) { integer=i2a(INT_MAX); integer[9]='8'; } else integer=i2a(numerator/denominator); int *visited=(int *)malloc(sizeof(int)*10000); char *decimal=(char *)malloc(sizeof(char)*10000); memset(visited,0,sizeof(int)*10000); memset(decimal,0,sizeof(char)*10000); x=x%y; while(x) { if((pos=contain(visited,x,size))) break; visited[size]=x; x*=10; decimal[size++]=x/y+'0'; x%=y; } if(!size) return integer; decimal[size]='\0'; int inlen=strlen(integer); if(integer[0]=='0'&&flag) { integer[0]='-'; integer[1]='0'; integer[2]='\0'; inlen++; } int delen=strlen(decimal); char *rs=(char *)malloc(sizeof(char)*(inlen+delen+4)); for(i=0;i<inlen;i++) rs[i]=integer[i]; rs[inlen]='.'; if(x) { for(i=1;i<pos;i++) rs[inlen+i]=decimal[i-1]; rs[inlen+pos]='('; for(i-=1,j=0;i<delen;j++) rs[inlen+pos+1+j]=decimal[i++]; rs[inlen+delen+2]=')'; rs[inlen+delen+3]='\0'; } else { for(i=0;i<delen;i++) rs[inlen+1+i]=decimal[i]; rs[inlen+delen+1]='\0'; } return rs; }
这是用时最短的大佬的代码。
char* fractionToDecimal(int numerator, int denominator) { int base[] = {1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000}; int map[1096] = {0}; char tmp[1096]; int p = 0; int sign = (numerator < 0) ^ (denominator < 0); long n1 = numerator < 0 ? -((long)numerator) : (long)numerator; long n2 = denominator < 0 ? -((long)denominator) : (long)denominator; if (sign && numerator) { tmp[p++] = '-'; } long integer = n1 / n2; if (integer) { int i = 9; while (integer / base[i] == 0) { i--; } while (i >= 0) { tmp[p++] = integer / base[i] + '0'; integer %= base[i]; i--; } } else { tmp[p++] = '0'; } long frac = n1 % n2; int repeat = 0; if (frac) { tmp[p++] = '.'; } while (frac) { int find = 0; for (int i = 0; i < p; i++) { if (map[i] == frac) { find = i; break; } } if (find) { repeat = find; break; } else { map[p] = frac; } tmp[p++] = frac * 10 / n2 + '0'; frac = (frac * 10) % n2; } tmp[p] = '\0'; int returnsize = p; if (repeat) { returnsize += 2; } char *ret = (char *)malloc(sizeof(char) * returnsize); if (repeat) { strncpy(ret, tmp, repeat); ret[repeat] = '('; strcpy(ret + repeat + 1, tmp + repeat); ret[p + 1] = ')'; ret[p + 2] = '\0'; } else { strcpy(ret, tmp); } return ret; }