剑指offer(45):翻转句子中的单词顺序

本文介绍了一种算法,用于翻转英文句子中单词的顺序,但保持单词内部字符顺序不变。通过两次翻转操作实现目标,适用于字符串处理和面试准备。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目描述

输入一个英文句子,翻转句子中单词的顺序,但是单词内字符的顺序不变。标点符号和普通字母一样处理。 例如输入字符串”I am a student.”,输出”student. a am I”。

分析

关键是需要确定一个翻转函数,实现字符串的翻转。之后分两个步骤达到目的:第一步翻转整个句子;第二步以空格为分隔符翻转单词,是单词恢复原来的顺序。

主要注意边界条件的判断:字符串为null或者为空串时,返回空串;字符串只有一个单词(不包含空格)时,返回字符串本身;while循环条件为开始索引startIndex小于字符串长度;以及翻转单词的条件判断语句endIndex == length || charArr[endIndex] == ' '不能反序的问题。

牛客AC;

package com.problem;

/**
 * 输入一个英文句子,翻转句子中单词的顺序,但是单词内字符的顺序不变。标点符号和普通字母一样处理。
 * 例如输入字符串"I am a student.",输出"student. a am I"
 * 
 * @author Administrator
 *
 */

public class ReverseSentence {

    public static void main(String[] args) {
        ReverseSentence reverseSentence = new ReverseSentence();
         String str = "I am a student.";
        //String str = "Hello World!";
        System.out.println(reverseSentence.reverseSentence(str));
    }

    public String reverseSentence(String str) {
        if(str == null || str.length() <= 0)
            return "";

        // 将字符串转为字符数组,才能实现传址的方式,保存翻转后的更改
        // String作为函数传递并不会保存更改。
        char[] charArr = str.toCharArray();
        int length = charArr.length;
        int startIndex = 0;
        int endIndex = length - 1;

        // 扫描字符数组,统计空格的数目,如果不存在空格,则只有一个单词,不需要翻转
        int blankCount = 0;
        for(char c : charArr) {
            if(c == ' ')
                blankCount++;
        }
        if(blankCount <= 0)
            return str;

        // 1、翻转整个句子
        reverse(charArr, startIndex, endIndex);

        // 2、翻转句子中的单词
        startIndex = 0; // 前后索引重新赋值
        endIndex = 0;
        while(startIndex < length) {    // 注意循环终止条件
            if(charArr[startIndex] == ' ') {    // 起始索引的字符为空格,则同时移动两个索引
                startIndex++;
                endIndex++;

                // 后索引到达最后一个或者后索引所指的位空格时,翻转单词
                // 两个或语句不能反序,否则可能出现两个单词的情况时候翻转出错
                // 例如:如果反序,则输入"Hello world",输出"world elloH"
            } else if(endIndex == length || charArr[endIndex] == ' ' ) {
                endIndex--;     // endIndex所指的位空格,需要回退一位
                reverse(charArr, startIndex, endIndex);     // 翻转单词
                endIndex++;     // endIndex重新指向空格
                startIndex = endIndex;  // startIndex更新成与endIndex保持一致
            } else {    
                // 这里只需要调整endIndex向后搜索
                endIndex++;     
            }
        }
        String resStr = String.copyValueOf(charArr);
        return resStr;
    }

    /**
     * 翻转函数
     * @param charArr   需要翻转的字符数组
     * @param startIndex    开始索引
     * @param endIndex      结束索引
     */
    public void reverse(char[] charArr, int startIndex, int endIndex) {
        if(charArr == null || charArr.length <= 0 || startIndex > endIndex)
            return;

        // 前后索引方法,翻转字符数组
        while(startIndex < endIndex) {
            char tmp = charArr[startIndex];
            charArr[startIndex] = charArr[endIndex];
            charArr[endIndex] = tmp;
            startIndex++;
            endIndex--;
        }
    }
}

参考
1. 何海涛,剑指offer名企面试官精讲典型编程题(纪念版),电子工业出版社

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值