Lecture 100 on the basics of algorithm zero (Lecture 27) string algorithm - high precision

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

1556. Thousands separator

analysis:
    this question is easy to understand. It starts from the tail and adds a '.' character every three numbers.

Code idea:

  1. First, we need to convert the integer n into the numeric string num and calculate its length len.
  2. Starting from the tail, len - 1, copy each character into a new string ret, and insert a dot character every three characters.
  3. 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:

  1. First, we need to convert the string s into a single number and put it into an array.
  2. Add all the values in the array to get the total sum.
  3. 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:

  1. Two variables max1 and max2 are defined and initialized to - 1.
  2. First, we need to judge whether it is a number.
  3. 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:

  1. First, use the function sscanf() to convert all the time and record it in the array time.
  2. Sort the array (here we sort in descending order).
  3. 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:

  1. First, we need to deal with special cases, such as I, V, x, l, C, D, M. And their two adjacent numbers.
  2. 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:

  1. 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.
  2. 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;
    
}

Tags: C Algorithm leetcode

Posted on Tue, 16 Nov 2021 06:22:05 -0500 by bogins