LeetCode-空格替换问题

简介: 笔者比较笨,所以会写的很详细,方便自己后序复盘和分享给别人!希望大佬们不要嫌弃我的事多~哈哈哈!感谢大佬们支持!

题目

b365632b5f0e4344862fb003e7df37c8.png

笔者比较笨,所以会写的很详细,方便自己后序复盘和分享给别人!希望大佬们不要嫌弃我的事多~哈哈哈!感谢大佬们支持!


题目链接:https://leetcode-cn.com/problems/ti-huan-kong-ge-lcof/


思路

  • 根据规律可知,替换之后的长度 = 原来替换前的长度 +空格个数*2 (不包括\0) ->所以替换后末尾要手动放\0,或者替换过程把\0也放过去
  • 所以:第一步:遍历字符串,求出空格个数
  • 求出替换之后的长度记为:newlength 原来的长度记为:length
  • 进行填充,从后往前填充,用两个变量来控制, i 下标范围:[0,length] ->这种情况包含了\0,要把\0也替换过去 而若下标范围为:[0,length) ->这种情况是没有把\0也替换过去,所以最后要在newlength位置手动放\0
  • pos取值范围:[0,newlength] /[0,newlength)
  • 如果i指向的字符不是空格,就把此时的字符放到pos位置,pos–,i–
  • 如果是空格就放%20到pos位置,pos–三次,i–一次

手动最后位置放\0

235f87483173433d8a087351604559af.png

方法1:从后往前替换

写法1:下标范围为:**[0,newlength) **和 [0,newlength) 最后拷贝完手动放\0

8225768b5eef4c60a60589e38c8a9989.png

#include<stdio.h>
#include<string.h>
void ReplaceSpace(char* str, int length)
{
    //1.计算空格的个数
    int i = 0;
    int spcount = 0;
    for (i = 0; i < length; i++)
    {
      if (str[i] == ' ')
        spcount++;
    }
    //2.计算替换空格后新的长度和最后的位置
    int newlengh = length + spcount * 2;
    int pos = newlengh - 1;
    //3.从后往前填充
    for (i = length - 1; i >= 0; i--)
    {
      //空格
      if (str[i] == ' ')
      {
        str[pos--] = '0';
        str[pos--] = '2';
        str[pos--] = '%';
      }
      //非空格
      else
      {
        str[pos--] = str[i];
      }
    }
    //最后手动在newlength位置放\0
    str[newlengh] = '\0';
}
int main()
{
  char arr[20] = " We Are Happy";
  ReplaceSpace(arr, strlen(arr));
  printf("%s\n", arr);
  return 0;
}

写法2:下标范围为:[0,newlength][0,newlength] 直接把\0也后移

6743f3a7e5ce4594bb0fc1686073a19d.png

void ReplaceSpace(char* str, int length)
{
  assert(str);
  //统计空格的个数
  int count = 0;
  for (int i = 0; i < length; i++)
  {
    if (str[i] == ' ')
    {
      count++;
    }
  }
  //计算替换后的长度 = 原来长度+空格个数*2
  int newlength = length + count * 2;
  int pos = newlength;
  //替换 -从后往前覆盖
  //如果不是空格就把pos位置的字符放到pos位置
  //如果是空格就在pos位置往前放%20
  // \0也要替换,所以长度为:[0,length]
  //从后往前存放
  for (int i = length; i >= 0; i--)
  {
    if (str[i] == ' ')
    {
      //如果是空格就在pos位置往前放 %20
      str[pos--] = '0';
      str[pos--] = '2';
      str[pos--] = '%';
    }
    else
    {
      str[pos--] = str[i];
    }
  }
}
int main()
{
  char arr[50] = " WeAreHappy";
  ReplaceSpace(arr, strlen(arr));
  printf("%s\n", arr);
  return 0;
}

方法2:开辟新空间

思路

  • 第一步:遍历字符串,求出空格个数为count
  • 求出替换之后的长度记为:newlength 原来的长度记为:length,newlength = length + count*2 求出字符串的长度是不包含\0的!!
  • 开辟一个大小为newlength+1大小的数组arr (多加一个空间是为了存放\0
  • 分别使用变量控制下标 i 控制str数组 j控制arr数组
    如果i指向的不是空格,就把i指向的内容放到arr数组的j位置,i++,j++
    如果是i指向的是空格,就在arr数组后面覆盖%20,j++三次,然后i++跳过空格,
    不管怎样i都要++
  • 最后把arr数组的内容拷贝回去,然后释放掉arr
#include<stdlib.h>
//开辟新空间
void ReplaceSpace(char* str, int length)
{
    //统计空格个数
  int count = 0;
  int i = 0;
  for (i = 0; i < length; i++)
  {
    if (str[i] == ' ')
    {
      count++;
    }
  }
  int newlength = length + count * 2;  //计算出的长度不包括\0
  char* arr = (char*)malloc(sizeof(char) * (newlength+1));//要存放\0,所以要多开辟一个空间
  if (arr == NULL)
  {
    printf("malloc fail\n");
    exit(-1);
  }
  //分别使用变量控制下标 i 控制str数组 j控制arr数组
  //如果i指向的不是空格,就放到arr数组的j位置,i++,j++ 
  //如果是i指向的是空格,就在arr数组中替换为%20,i++一次,j++三次
  //不管怎样i都要++
  int j = 0;
  for (i = 0; i < length; i++)
  {
        //i指向的是空格
    if (str[i] == ' ')
    {
      arr[j++] = '%';
      arr[j++] = '2';
      arr[j++] = '0';
    }
    else
    {    
      arr[j++] = str[i];
    }
  }
    //在newlength位置放\0
  arr[newlength] = '\0';
  //拷贝回去,把\0也拷贝过去,所以范围为:[0,newlength]
  for (j = 0; j <=newlength; j++)
  {
    str[j] = arr[j];
  }
    //最后要释放空间
  free(arr);
  arr = NULL;
}
int main()
{
  char arr[50] = "WeAre Happy";
  ReplaceSpace(arr, strlen(arr));
  printf("%s\n", arr);
  return 0;
}

代码

char* replaceSpace(char* s){
    /*
  int i = 0;
  int len = strlen(s);
  int count = 0;
  //统计空格个数
  for(i = 0;i<len;i++)
  {
      if(s[i] == ' ')
      {
          count++;
      }
  }
  //开辟新空间
  int newlength = count*2+len;
  char* str = (char*)malloc(sizeof(char)*(newlength+1));    //多开辟一个空间存放\0
  int j = 0;
  for(i = 0;i<len;i++)
    {
        if(s[i] == ' ')
        {
            str[j++] = '%';
            str[j++] = '2';
            str[j++] = '0';   
        }
        else
        {
            str[j++] = s[i];
        }
    }
    str[j] = '\0';
    //或者str[newlength] = '\0'  在最后位置放\0
    return str;
    */
    //法2:原地扩容
    int i = 0;
  int len = strlen(s);
  int count = 0;
  //统计空格个数
  for(i = 0;i<len;i++)
  {
      if(s[i] == ' ')
      {
          count++;
      }
  }
  //开辟新空间
  int newlength = count*2+len;
  s = (char*)realloc(s,sizeof(char)*(newlength+1));    //多开辟一个空间存放\0
  //从后往前
  int pos = newlength;
  s[pos] = '\0';
  for(i = len ;i> 0;i--)
  {
      if(s[i] == ' ')
      {
          s[pos--] = '0';
          s[pos--] = '2';
          s[pos--] = '%';
      }
      else{
          s[pos--] = s[i];
      }
  } 
  return s;
}
相关文章
|
7月前
|
C++ Python
leetcode-283:移动零
leetcode-283:移动零
30 0
|
4月前
|
算法
LeetCode第66题加一
LeetCode第66题"加一"的解题方法,通过遍历数组从后向前处理每一位的加法,并考虑进位情况,最终实现给定数字加一的功能。
LeetCode第66题加一
顺手牵羊(LeetCode844.)
好多同学说这是双指针法,但是我认为叫它顺手牵羊法更合适
82 0
leetcode第55题
当自己按照 45 题的思路写完的时候,看 Solution 的时候都懵逼了,这道题竟然这么复杂?不过 Solution 把问题抽象成动态规划的思想,以及优化的过程还是非常值得学习的。
leetcode第55题
|
算法
leetcode第34题
第二种思路,参考这里。 我们开始更新 start 的时候,是 mid + 1,如果剩两个元素,例如 2 4,target = 6 的话,此时 mid = 0,start = mid + 1 = 1,我们返回 start + 1 = 2。如果 mid 是右端点,那么 mid = 1,start = mid + 1 = 2,这样就可以直接返回 start 了,不需要在返回的时候加 1 了。
110 0
leetcode第34题
leetcode第51题
较经典的回溯问题了,我们需要做的就是先在第一行放一个皇后,然后进入回溯,放下一行皇后的位置,一直走下去,如果已经放的皇后的数目等于 n 了,就加到最后的结果中。然后再回到上一行,变化皇后的位置,然后去找其他的解。 期间如果遇到当前行所有的位置都不能放皇后了,就再回到上一行,然后变化皇后的位置。再返回到下一行。 说起来可能还费力些,直接看代码吧。
leetcode第51题
leetcode第48题
将一个矩阵顺时针旋转 90 度,并且不使用额外的空间。大概属于找规律的题,没有什么一般的思路,观察就可以了。 解法一 可以先转置,然后把每列对称交换交换一下
leetcode第48题
|
算法
leetcode第42题
也就是红色区域中的水, 数组是 height = [ 0, 1, 0, 2, 1, 0, 1, 3, 2, 1, 2, 1 ] 。 原则是高度小于 2,temp ++,高度大于等于 2,ans = ans + temp,temp = 0。 temp 初始化为 0 ,ans 此时等于 2。 height [ 0 ] 等于 0 < 2,不更新。 height [ 1 ] 等于 1 < 2,不更新。 height [ 2 ] 等于 0 < 2, 不更新。 height [ 3 ] 等于 2 >= 2, 开始更新 height [ 4 ] 等于 1 < 2,temp = temp + 1 = 1。 h
107 0
leetcode第42题
leetcode第31题
我们想几个问题。 要想使得数字变大,只要任意一位变大就可以。 要想得到刚好大于原来的数字,要变个位。 这里变大数字,只能利用交换。 如果从个位开始,从右往左进行,找一个比个位大的,交换过来,个位的数字交换到了更高位,由于个位的数字较小,所以交换过去虽然个位变大了,但数字整体变小了。例如 1 3 2,把 2 和 3 交换,变成 1 2 3,个位变大了,但整体数字变小了。 个位不行,我们再看十位,如果从十位左边找一个更大的数字交换过来,和个位的情况是一样的,数字会变小。例如 4 1 2 3,把 2 和 4 交换,2 1 4 3,数字会变小。如果从
leetcode第31题