刷题笔记,剑指 Offer 58 - I. 翻转单词顺序。

这题思路很简单,因为这个是简单题。主要就是要分割每个单词,然后逆序组成新的字符串。有两种办法,一个是背API,利用自带的函数帮助我们完成去除首尾空格和按空格分割。另一个如官方题解所示,自己实现双指针,分割字符串。

难点

为什么我要写这篇题解,因为我面试这题挂了。这题思路上没有任何难点,难点主要在于,如果是用自带函数,在线面试过程中,我们没办法查看函数定义,甚至没办法使用标准输出(stdout),需要背API。如果是自己实现双指针,需要极度留意边界问题。

背API

Go 中负责去除首尾空格的函数为strings.Trim,函数签名为func Trim(s, cutset string) strings参数为要处理的字符串,sep为需要前后去除的字符串,返回值是处理好的字符串。在这里,我们只需要输入s = strings.Trim(s, " ")就能去除首尾的所有空格。

其次,我们需要将字符串按空格分割成一个个单词,单词间的可能空格不只一个,比如"abc defg"。这里我们要注意,绝对不能使用strings.Split Split只能去除单个空格,如果有多个空格,将会分割成多个长度为0的空字符串。比如上面的例子会分割成["abc", "", "", "", "", "defg"]。因此我们需要使用strings.Fields,函数签名如下func Fields(s string) []string。该函数能去除单词之间一个或多个的空格,返回字符串切片。使用上面的例子,会返回["abc","defg"],符合我们的要求。

如果有更多个性化的分割需求,可以使用strings.FieldsFunc,函数签名如下func FieldsFunc(s string, f func(rune) bool) []string,需要你写一个函数f。对于符合f函数的要求的一个或多个字符,都会被视为分隔符,而被分割。下面注释的例子写得比较清楚,假如我们还是要按空格分割,就写一个匿名函数func(c rune)bool{ return c==' ' },注意该函数的参数必须是rune类型。

最后拼接字符串时,记得单词间要有空格,但是末尾不要有空格。

func reverseWords(s string) string {
    s = strings.Trim(s, " ")
    words := strings.Fields(s)
    //words := strings.FieldsFunc(s, func(c rune) bool {
    //    return c==' '
    //})
    result := ""
    for i := len(words) - 1; i >= 0; i-- {
        result += words[i]
        if i != 0 {
            result += " "
        }
    }
    return result

}

手动实现双指针

手动实现双指针,需要留意边界问题,需要注意的点我都在注释下方写上了。首先我们使用一个左右指针l,r。去除首尾空格。注意不要让l大于r,否则会有异常,因此我们对于l指针的遍历,需要用l条件判定。而后的分割操作。我们使用两个指针i,j,同时指向单词末尾。先让i跳过所有非空格,去到第一个空格,此时s[i+1:j+1]就是一个单词了,因此将此加入到列表中。随后让i继续前进,跳过所有空格,去到下一个单词的末尾,同时让j跟上i,也就j=i。这时就可以进入下一个循环了。当去到正序一个单词时,i指针此时应该为-1,在将正序第一个单词加入列表后,外层循环i>=0会判定跳出。

最后拼接字符串时,记得单词间要有空格,但是末尾不要有空格。

func reverseWords(s string) string {

    l,r:=0,len(s)-1
    for ;r>=0 && s[r]==' ';r--{}
    //注意判断条件是l=0;{
        //跳过非空格
        //注意条件是i>=0,而非i>0
        for ;i>=0 && s[i]!=' ';i--{}
        words=append(words,s[i+1:j+1])

        //再跳过单词间的空格
        //注意条件是i>=0,而非i>0
        for ;i>=0 && s[i]==' ';i--{}
        j=i
    }
    result:=""
    for i,w:=range words{
        result+=w
        if i!=len(words)-1{
            result+=" "
        }
    }
    return result
}

你可能感兴趣的:(golang字符串处理刷题)