[C++] 9 OJ questions about string

Either vulgar or lonely...
Insert image description here



1. Just reverse the letters

Insert image description here

1.
The difficulty of this question is very simple. We can define two variables to represent the subscripts of valid characters at the beginning and end of the array, and then traverse from the front and back to the middle respectively. Stop as soon as we encounter a letter and use Library function swap performs exchange.

class Solution {
    
    
public:
    string reverseOnlyLetters(string s) {
    
    
        size_t begin=0,end=s.size()-1;
        while(begin<end)
        {
    
    
            while(begin<end && !isalpha(s[begin]))
            //字符串有可能全不是字母,begin要保证小于end,否则陷入死循环
            {
    
    
                ++begin;
            }
            while(begin<end && !isalpha(s[end]))
            {
    
    
                --end;
            }
            swap(s[begin],s[end]);
            ++begin;
            --end;
        }
        return s;

    }
};

2. The first unique character in the string (the idea of ​​​​counting sorting)

Insert image description here
1.
This question uses the idea of ​​counting and sorting. The ascll code corresponding to each letter is essentially a number. We can regard this number as the subscript of the counting array count, and then add the element corresponding to this subscript +1 , in this way, if the element corresponding to a certain subscript in the array count is 1, it proves that the letter deduced by the ascll code of this subscript only appears once in the original string, and then the string array is traversed from front to back. Look at which character is in the counting array. The corresponding element of the character subscript is 1. If such a character is encountered during the traversal from front to back, it means that this character is the first unique character in the string , and then Just return directly.

class Solution {
    
    
public:
    int firstUniqChar(string s) {
    
    
        int count[128]={
    
    0};
        int size=s.size();
        for(int i=0;i<size;i++)
        {
    
    
            count[s[i]]++;
        }
       
        for(int i=0;i<size;i++)
        {
    
    
            if(1==count[s[i]])
            {
    
    
                return i;
            }
        }
        return -1;
    }
};

class Solution {
    
    
public:
    int firstUniqChar(string s) {
    
    
        int count[26]={
    
    0};
        
        for(auto ch : s)
        {
    
    
            count[ch - 'a']++;
        }
       
        for(int i = 0; i < s.size(); i++)
        {
    
    
            if(count[s[i] - 'a'] == 1)
                return i;
        }
        return -1;
    }
};

3. Add strings (just do the work of adding carries)

Insert image description here
1.
The more questions like this have a relatively long logical chain, the more we should define more variables, because the more effective variables there are, the less burden we have on thinking and the clearer the logic. Of course, doing more questions and reading advanced code are also very important factors, which can help us define multiple effective variables.

2.
When two judgment situations arise, we must be good at using the ternary operator, which can help us reduce the branch condition judgment of if and affect our thinking logic.

3.
Whether it is addition, subtraction, multiplication or division of numbers, don’t forget to add the previous carry when calculating the high bit. What is more efficient than head insertion is tail insertion. We can first tail insert into the returned result string, and then use The library function template reverse can reverse the string by passing iterators from the beginning and end of the string. The time complexity is O(N), while the time complexity of head insertion is O(N²).

Insert image description here

class Solution {
    
    
public:
    string addStrings(string num1, string num2) {
    
    
        string retstr;
        int carry=0;
        int end1 = num1.size()-1,end2 = num2.size()-1;
        while(end1 >= 0 || end2 >= 0)
        {
    
    
            int value1 = end1 >= 0 ? num1[end1]-'0' : 0;
            int value2 = end2 >= 0 ? num2[end2]-'0' : 0;
            int ret = value1 + value2 + carry;
            //表示下一位计算时,要加上前面位的进位。
            carry = ret/10;
            ret %= 10;
            retstr.insert(0, 1, ret + '0');
            //用'ret'来进行头插,会发生int到char类型的截断,不要胡搞。
            --end1;
            --end2;
                    
        }
        if(carry == 1)
            retstr.insert(0, 1, '1');
        return retstr;
    }
};

4. Convert string to integer

Insert image description here
1.
You can traverse the string from back to front, convert each character into an integer, and then multiply it by the corresponding bit weight. We can implement the mypow function ourselves for this bit weight, because the pow function provided by the library returns a double type. data. Finally, add the integer corresponding to each character to ret.

class Solution {
    
    
public:

    int mypow(int num, int cnt)
    {
    
    
        int ret = 1;
        while(cnt>0)
        {
    
    
            ret *= num;
            cnt--;
        }
        return ret;
    }
    int StrToInt(string str) {
    
    
        int retnum = 0;
        int size = str.size();
        int end = str.size()-1;

        if(str[end] == '+' || str[end] == '-')
            return 0;

        //从后向前进行遍历,将字符对应的数字加到retnum即可
        while(end >= 0 && (
             (str[end] >= '1' && str[end] <= '9') 
             || str[end] == '+' 
             || str[end] == '-'))
        {
    
    
            int num = (str[end] - '0') * mypow(10, size - end -1);
            retnum += num;
            --end;
            if(end == 0 && str[end] == '-')
            {
    
    
                retnum *= -1;
                return retnum;
            }
            if(end ==0 && str[end] == '+')
            {
    
    
                return retnum;
            }
        }

        if(end >= 0)
            return 0;

        return retnum;
    }
};

5. Reverse words in a string III

Insert image description here
1.
The essential idea of ​​this question is still the front and back pointers. End serves as the front pointer. We let its next position point to a space, and use a flag to record the position of the space to facilitate subsequent iterations of begin and end.
So just reverse the characters between begin and end each time. After the reversal is completed, let begin and end iterate backwards until the last part of the word is reversed.

class Solution {
    
    
public:
    string reverseWords(string s) {
    
    
        int begin = 0, end = 0;
        int size = s.size() - 1;
        while(begin <= size && s[end] != '\0')
        {
    
    
            while(s[end+1] != ' ')
            {
    
    
                if(s[end + 1] == '\0')
                    break;
                ++end; 
            }
            int flag = end + 1;//flag是空格的位置
            while(begin < end)
            {
    
    
                swap(s[begin++], s[end--]);
            }
            begin = flag + 1;
            end = begin;
        }
        return s;
    }
};

6. String multiplication (high-precision algorithm: large number multiplication)

Insert image description here
1.
Use reverse and iterator to reverse both strings, then traverse one of the strings, take out the characters from position to high position and multiply each character with another string. The string result is temporarily stored in the tmp object, and then the tmp string is misaligned and added to the result string. The misaligned addition is not required for the first time, but the misaligned addition is required for each subsequent multiplication result.

Insert image description here

class Solution 
{
    
    
public:
  void MulItem(string &tmp, string &num1, char a)
  {
    
    
    int i = 0, sign=0;
    int mul = 0;
    while(i < num1.size())
    {
    
    
      mul = (num1[i]-'0') * (a-'0') + sign;
      if(mul >= 10)
      {
    
    
        sign = mul / 10;
        mul %= 10;
      }
      else
        sign = 0;

      tmp.push_back(mul+'0');
      i++;
    }

    if(sign > 0)
      tmp.push_back(sign+'0'); 
  }   
  //对应位相加,sign进位采用引用传递
  int AddItem(int a, int b, int &sign)
  {
    
    
    int add = a+b+sign;
    if(add >= 10)
    {
    
    
      sign = 1;
      add -= 10;
    }
    else
      sign = 0;
    return add;
  }
  //错位相加
  void MoveAdd(string &result, string &tmp, int k)
  {
    
    
    int i, j;
    i = k;
    j = 0;
    int sign = 0;

    while(i<result.size() &&j<tmp.size())
    {
    
    
      result[i] = AddItem(result[i]-'0', tmp[j]-'0', sign) + '0';
      i++;
      j++;
    }

    if( i<result.size()&&sign)//在错位相加之后,下一次的tmp字符串可能为0,这个时候需要在原有的result字符串的基础上进行上一次result和tmp字符串相加之后可能遗留下来的进位。
      result[i] = AddItem(result[i]-'0', 0, sign)+'0';

    while(j < tmp.size())//如果tmp字符串不为0,则错位相加之后,tmp字符串肯定还没有遍历完,所以还需要将剩余的字符在加到result上面去(利用push_back)
    {
    
    
      int v = AddItem(0, tmp[j]-'0', sign);
      result.push_back(v+'0');
      j++;
    }
    if(sign)//最后的最后,如果在tmp的剩余字符串加完之后,还留有进位,则需要继续将进位尾插到result字符串对象里面
      result.push_back(sign+'0');
  }

  string multiply(string num1, string num2) 
  {
    
    
    //先翻转数据,方便进位处理
     reverse(num1.begin(), num1.end());
     reverse(num2.begin(), num2.end());

     string tmp, result;
     for(int i=0; i<num2.size(); ++i)
     {
    
    
      //使用num2的每一个数据乘以num1
       MulItem(tmp, num1, num2[i]);
       //将乘得的结果进行错位相加
       MoveAdd(result, tmp, i);
       tmp.clear();
     }    
     while(result.size()!=1 && result.back()=='0')//如果进位之后的字符串尾部出现0,我们需要手动将其pop掉
      result.pop_back();

    //翻转数据,恢复数据

     reverse(result.begin(), result.end());

     return result;

  }

};

7. Verify whether a string is a palindrome

Insert image description here
1.
There are two ways to solve this problem. The first is to pick out all the letters and numeric characters and insert them into a new string class object. Then we traverse from the head and tail of the object to the middle to determine whether is a palindrome string.
The second is to compare directly in the original string and filter out non-letter and numeric characters while traversing. Pay attention to the situation where there are no letters or numbers. In this case, we can directly return true.

class Solution {
    
    
public:
    bool isPalindrome(string s) {
    
    
        // string palin_array;
        // int begin1 = 0, end1 = s.size() - 1;
        // //1.先将字符串中大写字母替换为小写字母
        // for(int i = begin1; i <= end1; i++)
        // {
    
    
        //     if(s[i] >= 'A' && s[i] <= 'Z')
        //         s[i] += 32;
        // }
        // //2.将字母和数字放到palin_array数组里面
        // for(int i = begin1; i <= end1; i++)
        // {
    
    
        //     if(s[i] >= 'a' && s[i] <= 'z' || s[i] >= '0' && s[i] <= '9')
        //         palin_array.push_back(s[i]);
        // }
        // if(palin_array.size() == 0)
        //     return true;
        // int begin2 = 0, end2 = palin_array.size() - 1;
        // int palin_tail = palin_array.size() - 1;
        // //3.判断palin_array数组的字符串是否是回文
        // while(begin2 != palin_tail)
        // {
    
    
        //     if(palin_array[begin2] != palin_array[end2])
        //         return false;

        //     begin2++;
        //     end2--;
        // }
        //  return true;

        //1.先将字符串中大写字母替换为小写字母
        int begin1 = 0, end1 = s.size() - 1, tail = s.size() - 1;
        for(int i = begin1; i <= end1; i++)
        {
    
    
            if(s[i] >= 'A' && s[i] <= 'Z')
                s[i] += 32;
        }
        //2.在s数组里直接进行首尾元素的比较
        while(begin1 <= tail)
        {
    
    
            while(!(s[begin1] >= 'a' && s[begin1] <= 'z' ||
            s[begin1] >= '0' && s[begin1] <= '9') && begin1 <= tail)
            {
    
    
                begin1++;
                if(begin1 > tail )
                    return true;
            }
            
            while(!(s[end1] >= 'a' && s[end1] <= 'z' ||
            s[end1] >= '0' && s[end1] <= '9') && end1 >= 0)
            {
    
    
                end1--;
            }

            if(s[begin1] != s[end1])
            {
    
    
                return false;
            }
            //如果字符相等,继续进行比较
            begin1++;
            end1--;
        }
        return true;

    }
};

8. Reverse string II (reverse the first k characters of the 2k interval of the string)

Insert image description here
1. The logic of this question is very clear. We only need to find character groups that make up 2k in size, and then reverse the first k characters in each group according to the method of front and rear pointers. The remaining characters are divided into two situations. They are processed separately, and the processing method is also very simple. See the code for details.

2.
This question is not very difficult, but when I was doing it, some minor problems with the code logic occurred, and I still couldn't find the loophole after reading the code many times, so this troubled me very much.
Even for debugging, it is not easy for us to debug such an interface type, because if we want to debug, we need to add member variables ourselves, which is quite troublesome. But in fact, there are solutions to such interface type debugging, we just need to do it Just make it a static function of a class, and then use the class name plus domain qualifier to call this static function in the main function, so that you can easily debug it. For interface types, making it static is very easy to use. Wouldn't it be nice to be able to call idiom functions without defining a class object?

3.
Here is a review of the knowledge about static members of a class. There are two ways to call static members of a class, one is through the object.static member method, and the other is through the class name::static member method. transfer.
For non-static members, they cannot be called through the class name::, because the non-static member function has this pointer, so when calling, you must specify who the calling object is. Because of this, static members without this pointer Functions can only be called through class names. This will facilitate our debugging

class Solution {
    
    
public:
    static string reverseStr(string s, int k) {
    
    

        //1.先判断这个字符串中有几个凑成2k大小的字符组,留下的字符个数是多少
        int group_cnt = s.size() / (2 * k);
        int remaining_char = s.size() % (2 * k);
        //2.将前group_cnt个字符组每每进行字符反转
        int prev_begin1 = 0, prev_end1 = k - 1;
        while (group_cnt--)
        {
    
    
            //记录原先begin1和end1的位置,下面循环的时候,begin1和end1会发生改变
            int begin1 = prev_begin1, end1 = prev_end1;
            while (begin1 < end1)
            {
    
    
                swap(s[begin1++], s[end1--]);
            }

            prev_begin1 += (2 * k);
            prev_end1 += (2 * k);
        }

        //3.将剩余的字符分为两种情况,然后进行反转
        int begin2 = s.size() - remaining_char;
        int end2 = s.size() - 1;
        if (remaining_char < k)//剩余字符全部反转
        {
    
    
            while (begin2 < end2)
                swap(s[begin2++], s[end2--]);
        }
        else//反转剩余字符的前k个字符
        {
    
    
            int end3 = end2 - (remaining_char - k);
            while (begin2 < end3)
                swap(s[begin2++], s[end3--]);
        }
        return s;

    }
};

9. The length of the last word in the string (use of getline())

Insert image description here
1. For this question, you can use getline to get a line of string, then use the rfind function to find the position of the space before the last word, and finally subtract the subscript of the space position from the string size (actually the subscript of the \0 position) , then subtract 1, because the difference between the two subscripts is the number of intervals, and the number of characters in the interval needs to be subtracted by 1 more.

#include <iostream>
#include <string>
using namespace std;

int main() 
{
    
    
    string str;
    getline(cin,str);
    int pos = str.rfind(' ');
    cout << str.size() - pos  - 1 << endl;
}

Guess you like

Origin blog.csdn.net/erridjsis/article/details/129143070