第四十九题:丑数
题目:
我们把只包含因子 2、3、5 的数称作丑数。求按从小到大的顺序的第 1500 个丑数。例如,6、8都是丑数,但 14 不是,因为它包含因子 7.习惯上我们把 1 当做第一个丑数。
解题程序:
#include<iostream> #include<stdio.h> using namespace std; // 解法一:逐个判断每个整数是不是抽数的解法,直观但不够高效 bool IsUgly(int number) { while( number % 2 == 0 ) number /= 2; while( number % 3 == 0 ) number /= 3; while( number % 5 == 0 ) number /= 5; return (number == 1) ? true:false; } int GetUglyNumber(int index) { if( index <= 0 ) { return 0; } int number = 0; int uglyFound = 0; while(uglyFound < index) { ++number; if( IsUgly(number) ) { ++uglyFound; } } return number; } // 解法二:创建数组保存已经找到的丑数,用时间换空间 // 获取三个数中最小的数字 int Min(int num1,int num2,int num3) { int min = num1 < num2 ? num1:num2; min = min < num3 ? min:num3; return min; } int GetUglyNumber1(int index) { if(index <= 0) return 0; int *pUglyNumbers = new int[index]; for(int i=0;i<index;i++) { pUglyNumbers[i] = 0; } pUglyNumbers[0] = 1; int nextUglyIndex = 1; int *pMultiply2 = pUglyNumbers; int *pMultiply3 = pUglyNumbers; int *pMultiply5 = pUglyNumbers; while(nextUglyIndex < index) { int min = Min(*pMultiply2*2,*pMultiply3*3,*pMultiply5*5); pUglyNumbers[nextUglyIndex] = min; //printf("*pMultiply2 = %d,*pMultiply3 = %d,*pMultiply5 = %d\n",*pMultiply2,*pMultiply3,*pMultiply5); //printf("min = %d,pUglyNumbers[nextUglyIndex] = %d\n",min,pUglyNumbers[nextUglyIndex]); while( *pMultiply2 * 2 <= pUglyNumbers[nextUglyIndex] ) ++pMultiply2; while( *pMultiply3*3 <= pUglyNumbers[nextUglyIndex] ) ++pMultiply3; while( *pMultiply5*5 <= pUglyNumbers[nextUglyIndex] ) ++pMultiply5; ++nextUglyIndex; } int ugly = pUglyNumbers[nextUglyIndex-1]; delete []pUglyNumbers; pUglyNumbers = NULL; return ugly; } // 测试用例 void test() { int index; printf("请输入 index: \n"); scanf("%d",&index); printf("解法一:\n"); int ret = GetUglyNumber(index); if( ret ) printf("第 %d 个丑数是: %d\n",index,ret); else printf("程序出错!\n"); printf("解法一:\n"); ret = GetUglyNumber1(index); if( ret ) printf("第 %d 个丑数是: %d\n",index,ret); else printf("程序出错!\n"); } int main(void) { test(); return 0; }
题目一:字符串中第一个只出现一次的字符
在字符串中找出第一个只出现一次的字符。如输入“abaccdeff”,则输出 'b'。
解题程序:
#include<iostream> #include<stdio.h> using namespace std; char FirstNotRepeartingChar(char *str) { if( str == NULL ) return '\0'; const int tableSize = 256; unsigned int hashTable[tableSize]; for(int i=0;i<tableSize;i++) { hashTable[i] = 0; } char *pHashKey = str; while( *pHashKey != '\0' ) { printf("*pHashKey = %d\n",*pHashKey); hashTable[*pHashKey++]++; } pHashKey = str; while(*pHashKey != '\0') { if(hashTable[*pHashKey] == 1) return *pHashKey; pHashKey++; } return '\0'; } // 测试用例 void test() { char str[100] = ""; printf("请输入字符串:\n"); scanf("%s",str); char c = FirstNotRepeartingChar(str); if(c != '\0') printf("第一个只出现一次的字符: %c\n",c); else printf("程序出错\n"); } int main(void) { test(); return 0; }
题目二:字符流中第一个只出现一次的字符
请实现一个函数,用来找出字符流中第一个只出现一次的字符。例如,当字符流中只读出当前两个字符 "go” 时,第一个只出现一次的字符是 'g' ;当从该字符流中读出前 6 个字符“gegoole”时,第一个只出现一次的字符是 'l'。
解题程序:
#include<iostream> #include<limits> #include<stdio.h> using namespace std; class CharStatistics { public: CharStatistics():index(0) { for(int i=0;i<256;i++) { occurrence[i] = -1; } } void Insert(char ch) { if(occurrence[ch] == -1) occurrence[ch] = index; else if(occurrence[ch] >= 0) occurrence[ch] = -2; index++; } char FirstAppearOnce() { char ch = '\0'; int minIndex = numeric_limits<int>::max(); for(int i=0;i<256;i++) { if(occurrence[i] >=0 && occurrence[i] <minIndex) { ch = char(i); minIndex = occurrence[i]; } } return ch; } private: int index; int occurrence[256]; }; // 测试用例 void test() { CharStatistics chars; chars.Insert('g'); chars.Insert('o'); chars.Insert('o'); chars.Insert('g'); chars.Insert('l'); chars.Insert('e'); char c = chars.FirstAppearOnce(); if(c != '\0') { printf("字符流中只出现一次的字符是 :%c\n",c); } else { printf("程序出错\n"); } } int main(void) { test(); return 0; }