1, Concept definition
high precision is actually that when a number cannot be represented by the data type given by the program, we usually use an array for storage and simulation calculation.
2, Column recommendation
Algorithm basis of brother Hero: 100 lectures on zero basics of algorithms (Lecture 27) string algorithms (VII) - high precision
3, After class exercises
3.1 thousand separator
analysis:
this question is easy to understand. It starts from the tail and adds a '.' character every three numbers.
Code idea:
- First, we need to convert the integer n into the numeric string num and calculate its length len.
- Starting from the tail, len - 1, copy each character into a new string ret, and insert a dot character every three characters.
- Reverse ret.
The code is as follows:
void reserve(char* ret, int len){ int l = 0, r = len - 1; while(l < r){ char tmp = *(ret + l); *(ret + l) = *(ret + r); *(ret + r) = tmp; l++;r--; } } char * thousandSeparator(int n){ char* nums = (char*)malloc(sizeof(char) * 32); //Convert to string sprintf(nums, "%d", n); //Calculation length int len = strlen(nums); char* ret = (char*)malloc(sizeof(char) * 42); int retSize = 0; int k = 0; //Copy nums from the tail into ret for(int i = len - 1; i >= 0; i--){ //Insert. Character if(k % 3 == 0 && k != 0){ ret[retSize++] = '.'; } ret[retSize++] = nums[i]; k++; } ret[retSize] = '\0'; //reversal reserve(ret, retSize); return ret; }
3.2 sum of digits after string conversion
Title Link:
1945. Sum of digits after string conversion
Topic analysis:
the title gives a string composed of lowercase letters, and from 'a' = 1... 'z' = 26, each character represents a number. The title requires that it be converted into a number, and then the numbers on each bit are added for k operations.
Code idea:
- First, we need to convert the string s into a single number and put it into an array.
- Add all the values in the array to get the total sum.
- Because we may have to repeat this operation many times, we still need to continue to split the sum and put it into the array, and update the length of the array at the same time. Until k operations are completed
The code is as follows:
void Mul(int* nums, int* numsSize, int sum){ int n = 0; while(sum){ nums[n++] = sum % 10; sum /= 10; } *numsSize = n; } int Sum(int* nums, int numsSize){ int sum = 0; for(int i = 0; i < numsSize; i++){ sum += nums[i]; } return sum; } int getLucky(char * s, int k){ int nums[201] = { 0 }; int len = strlen(s); int numsSize = 0; //Convert letters to numbers for(int i = 0; i < len; i++){ int m = s[i] - 'a' + 1; //There should be two digits, so it needs to be split and stored while(m){ nums[numsSize++] = m % 10; m /= 10; } } int sum = 0; while(k--){ //Calculate the sum of the numbers sum = Sum(nums, numsSize); //If k == 0, there is no need to split and exit directly if(k == 0)break; //split Mul(nums, &numsSize, sum); } return sum; }
3.3 the second largest number in the string
Title Link:
1796. The second largest number in a string
analysis:
the topic requires us to find the second largest number, so we need to use two variables max1 and max2 to store the first two large numbers respectively. If there is no second one, it returns - 1.
Code idea:
- Two variables max1 and max2 are defined and initialized to - 1.
- First, we need to judge whether it is a number.
- Then compare the size and assign the largest to max1 and the second largest to max2.
The code is as follows:
bool isNum(char ch){ if(ch >= '0' && ch <= '9')return true; return false; } int secondHighest(char * s){ int n = strlen(s); int max1 = -1, max2 = -1; for(int i = 0; i < n; i++){ //Judgment number if(isNum(s[i])){ int m = s[i] - '0'; //Record the first two maximum values if(max1 < m){ max2 = max1; max1 = m; } else if(max2 < m && m < max1){ max2 = m; } } } return max2; }
3.4 minimum time difference
Title Link:
539. Minimum time difference
analysis:
this problem allows us to calculate the minimum time difference, but it gives a string to represent the time, so we can convert the hours into minutes through the sscanf() function, record them, and finally sort them to find the shortest time difference.
Code idea:
- First, use the function sscanf() to convert all the time and record it in the array time.
- Sort the array (here we sort in descending order).
- Traverse all adjacent time points to find the shortest time difference. We should note that time is periodic, [22:00, 14:00, 00:00]. In such a group of data, the difference between 22 hours and 0 is not 22 hours, but 2 hours. Therefore, we need to judge whether 1440 - time[i] + time[i + 1] or time[i] - time[i + 1] is smaller.
The code is as follows:
int cmp(const int* a, const int* b){ return *b - *a; } int findMinDifference(char ** timePoints, int timePointsSize){ int* time = (int*)malloc(sizeof(int) * timePointsSize); //Convert characters, record, and convert time units for(int i = 0; i < timePointsSize; i++){ int h, m; sscanf(timePoints[i], "%d:%d", &h, &m); time[i] = h * 60 + m; } //Descending sort qsort(time, timePointsSize, sizeof(int), cmp); //for(int i = 0; i < timePointsSize; i++)printf("%d ", time[i]); int min = 1440;//1440 minutes a day //Find the minimum time difference for(int i = 0; i < timePointsSize - 1; i++){ min = fmin(min, fmin(time[i] - time[i + 1], 1440 - time[i] + time[i + 1])); } //Judge whether there is a smaller time difference between the maximum time and the minimum time due to periodicity min = fmin(min, 1440 - time[0] + time[timePointsSize - 1]); return min; }
3.5 Roman numeral to integer
Title Link:
13. Roman numeral to integer
analysis:
in this question, we use Roman numerals to represent each character respectively. Among them, we should pay attention to whether the Roman numerals will change a large character whenever we encounter the two numbers of 5 and 1, such as I, II, III, IV, V and VI.
Code idea:
- First, we need to deal with special cases, such as I, V, x, l, C, D, M. And their two adjacent numbers.
- Traverse the array and calculate
The code is as follows:
int romanToInt(char * s){ int num = 0; int len = strlen(s); for(int i = 0; i < len; i++){ if(s[i] == 'I' && s[i + 1] && s[i + 1] == 'V'){ num += 4; i++; continue; } if(s[i] == 'I' && s[i + 1] && s[i + 1] == 'X'){ num += 9; i++; continue; } if(s[i] == 'C' && s[i + 1] && s[i + 1] == 'M'){ num += 900; i++; continue; } if(s[i] == 'X' && s[i + 1] && s[i + 1] == 'C'){ num += 90; i++; continue; } if(s[i] == 'C' && s[i + 1] && s[i + 1] == 'D'){ num += 400; i++; continue; } if(s[i] == 'X' && s[i + 1] && s[i + 1] == 'L'){ num += 40; i++; continue; } switch(s[i]){ case 'M':num += 1000;break; case 'D':num += 500;break; case 'C':num += 100;break; case 'L':num += 50;break; case 'X':num += 10;break; case 'V':num += 5;break; case 'I':num += 1;break; default:break; } } return num; }
3.6 integer to Roman numeral
Title Link:
12. Integer to Roman numeral
Problem solution analysis link: Simulation method
The code is as follows:
const int values[] = {1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1}; const char* symbols[] = {"M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I"}; char * intToRoman(int num){ char* roman = (char*) malloc (sizeof(char) * 16); roman[0] = '\0'; for(int i = 0; i < 13; i++){ //Find the maximum number that num is greater than while(num >= values[i]){ //Subtract this number num -= values[i]; //Copy the symbols[i] corresponding to values[i] strcpy(roman + strlen(roman), symbols[i]); } //When num == 0, the conversion has been completed if(num == 0){ break; } } return roman; }
3.7 string compression
Title Link:
Interview question 01.06. String compression
analysis:
the so-called compression of the title is actually to represent the continuously repeated letters with numbers. For example, aaaa is a4 after compression. Of course, if the compressed length is not less than the original string, the original string will be returned.
Code idea:
- First, we need to open up a strlen(S) length character array ret, define a char type variable ch for comparison, and define a cnt to calculate consecutive identical characters.
- When different characters are encountered, copy ch into ret, convert cnt into string, and copy it into ret, and then update CH and cnt
The code is as follows:
char* compressString(char* S){ char* ret = malloc(100001); int retSize = 0; int n = strlen(S); //exceptional case if(n == 0)return ""; int cnt = 0; char ch = S[0]; char k[5];// for(int i = 0; i < n; i++){ if(ch == S[i]){//Is the comparison the same cnt++; } else{//If not, store the number of original records in ret ret[retSize++] = ch; sprintf(k, "%d", cnt);//Convert cnt strcpy(ret + retSize, k);//Copy retSize += strlen(k); ch = S[i];//to update cnt = 1; } if(i == n - 1){ ret[retSize++] = ch; sprintf(k, "%d", cnt); strcpy(ret + retSize, k); retSize += strlen(k); } } if(retSize >= n)return S; ret[retSize] = '\0'; return ret; }