剑指offer73 翻转单词序列 Kotlin

描述

牛客最近来了一个新员工Fish,每天早晨总是会拿着一本英文杂志,写些句子在本子上。同事Cat对Fish写的内容颇感兴趣,有一天他向Fish借来翻看,但却读不懂它的意思。例如,“nowcoder. a am I”。后来才意识到,这家伙原来把句子单词的顺序翻转了,正确的句子应该是“I am a nowcoder.”。Cat对一一的翻转这些单词顺序可不在行,你能帮助他么?

数据范围:1≤n≤100 1≤n≤100 
进阶:空间复杂度 O(n) O(n)  ,时间复杂度 O(n) O(n)  ,保证没有只包含空格的字符串

示例

输入:"nowcoder. a am I"

返回值:"I am a nowcoder."

题目解析

题目要求是解决一个字符串单词顺序颠倒的问题。例如,给定一个字符串 "nowcoder. a am I",需要将其反转为 "I am a nowcoder."。这里的关键是理解字符串中的单词顺序被完全颠倒了,但单词内部的字母顺序没有变化。

解题思路

首先,我们需要将字符串按空格分割成单词数组,然后反转这个单词数组,使单词顺序恢复正常。如果单词后面紧跟着标点符号,需要将标点符号与单词一起反转,最后,将反转后的单词数组重新拼接成一个字符串。

根据这个需求,我们可以第一时间想到利用栈后进先出的特性来反转单词顺序,使用栈来存储单词。

使用栈

object Solution {
    fun ReverseSentence(ReverseSentence: String): String {
        val words = ReverseSentence.split(" ") // 分割字符串为单词列表
        val stack = arrayListOf<String>() // 创建一个模拟栈的列表

        // 将单词压入栈中(列表开头)
        words.forEach { word ->
            stack.add(0, word) // 在列表开头添加元素
        }

        // 从栈中弹出单词并拼接结果
        val builder = StringBuilder()
        while (stack.isNotEmpty()) {
            builder.append(stack.removeAt(0)) // 移除并获取列表第一个元素
            if (stack.isNotEmpty()) {
                builder.append(" ") // 添加空格,如果还有单词需要拼接
            }
        }

        return builder.toString()
    }
}

这种方法首先将单词压入栈中(使用列表实现),然后依次弹出单词并拼接成字符串。压栈和出栈操作都是线性时间的,但因为每个单词都要单独处理,所以总体时间复杂度是O(n),符合题目要求。方法需要额外的存储空间来模拟栈结构,空间复杂度为O(n),符合题目要求。

如果我们希望在空间效率上更进一步,应考虑使用不需要额外的存储空间,所有的操作都在原始字符数组上进行的双指针方法。

双指针方法

使用两个索引变量(指针)遍历字符串,一个从左到右,另一个从右到左,用于反转字符串中的字符或单词。在这个方法中,我们首先反转整个字符串,然后反转每个单词内部的字符。这需要两次遍历:第一次是反转整个字符串,第二次是反转每个单词。

object Solution {
    fun ReverseSentence(ReverseSentence: String): String {
        val chars = ReverseSentence.toCharArray()
        var i = 0  // 左指针
        var j = chars.size - 1  // 右指针

        // 首先反转整个字符串
        while (i < j) {
            swap(chars, i++, j--)
        }

        // 然后反转每个单词
        i = 0
        while (i < chars.size) {
            if (!chars[i].isWhitespace()) {
                var start = i
                while (i < chars.size && !chars[i].isWhitespace()) {
                    i++
                }
                var end = i - 1
                while (start < end) {
                    swap(chars, start++, end--)
                }
            }
            i++
        }

        return String(chars)
    }

    private fun swap(chars: CharArray, a: Int, b: Int) {
        val temp = chars[a]
        chars[a] = chars[b]
        chars[b] = temp
    }
}

空间复杂度:O(1),因为不需要额外的存储空间,所有的操作都在原始字符数组上进行。时间复杂度:O(n),其中n是字符串的长度。需要两次遍历整个字符串:一次用于反转整个字符串,另一次用于反转每个单词,符合题目要求。

  • 5
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值