Home > database >  print string based on the frequency of character in C
print string based on the frequency of character in C

Time:12-13

I was solving the question of leet code in C

Question:

Given a string s, sort it in decreasing order based on the frequency of the characters. The frequency of a character is the number of times it appears in the string.

Return the sorted string. If there are multiple answers, return any of them.

Example 1:

Input: s = "tree"
Output: "eert"
Explanation: 'e' appears twice while 'r' and 't' both appear once.
So 'e' must appear before both 'r' and 't'. Therefore "eetr" is also a valid answer.

I tried to use the different approach instead taking the array[255] and increasing the array value in specific char ASCII index. But I m getting segmentation fault. I not understand why I m getting segmentation voilation. Only assumption I made here is input str always be in UPPER CASE.

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

char *frequencySort(char *s)
{
    int strlenn = strlen(s);

    int fq[strlenn];

    // init with 1 because at least 1 time char occur in input str.
    for (int i = 0; i < strlenn; i  )
    {
        fq[i] = 1;
    }
    // count freq of string and replace dublicate char with *
    // ex: ABCDA => ABCD*
    for (int i = 0; i < strlenn - 1; i  )
    {
        if (s[i] == '*')
        {
            continue;
        }

        for (int j = (i   1); j < strlenn; j  )
        {
            if (s[i] == s[j])
            {
                fq[i]  ;
                s[j] = (char)'*';  // segmentation violation error shows here
                fq[j] = 0;
            }
        }
    }

    
    // sort freqency by in decending order and str char
    // ex: ABCDDDAA =  freq[3, 3, 1, 1] =  soredt str = [ A, D, B, C ]
    for (int i = 0; i < strlenn - 1; i  )
    {
        for (int j = i   1; j < strlenn; j  )
        {
            if (fq[i] < fq[j])
            {
                // swap
                int temp = fq[i];
                fq[i] = fq[j];
                fq[j] = temp;

                // swap string char
                char temp1 = s[i];
                s[i] = s[j]; // segmentation violation error shows here
                s[j] = temp1;
            }
        }
    }
    char *result = (char *)calloc(strlenn   1, sizeof(char));
    int l = 0;
    for (int i = 0; fq[i] != 0 && i < strlenn; i  )
    {
        int k = fq[i];

        while (k > 0)
        {
            printf("%c", s[i]);
            result[l  ] = s[i];
            k--;
        }
    }
    result[l] = '\0';
    return result;
}

int main()
{

    char *s = "ABCDDDAA";
    frequencySort(s);

    return 0;
}

Thanks!

CodePudding user response:

In frequencySort, you are modifying s (e.g.):

s[j] = (char)'*';  // segmentation violation error shows here

In main, the s argument comes from:

char *s = "ABCDDDAA";
frequencySort(s);

Here s is function scoped and goes on the stack.

But, because this is a pointer to a string literal, the actual string data goes into the .rodata section. This is mapped as read only. So, when we try to change it, we get a protection exception.

To fix this, define a string array:

char s[] = "ABCDDDAA";
frequencySort(s);

Now the literal data is [still] in the .rodata section. But, when main starts up, it is copied into the s array which is on the stack [which is writable].

  • Related