玩算法—字符串—替换空格

题目:
请实现一个函数,将一个字符串中的每个空格替换成“@2019@”。
例如,当字符串为“We Are Javaer”,则经过替换之后的字符串为“We@2019@Are@2019@Javaer”。
要求:
时限限制1000ms, 空间限制32768k。

public class StringReplaceSpace {

    public static void main(String[] args) {

        StringBuffer str = getTestString(200000, 100);
//        System.out.println("原始字符串 : [" + str.toString() + "]");
        System.out.println();

        long start1 = System.currentTimeMillis();
        String reStr1 = replaceSpace1(str);
//        System.out.println("处理结果 : [" + reStr1 + "]");
        long end1 = System.currentTimeMillis();
        System.out.println(">>>API执行时间 : " + (end1 - start1) + "ms");
        System.out.println();

        long start2 = System.currentTimeMillis();
        String reStr2 = replaceSpace2(str);
//        System.out.println("处理结果 : [" + reStr2 + "]");
        long end2 = System.currentTimeMillis();
        System.out.println(">>>String算法(从后往前)执行时间 : " + (end2 - start2) + "ms");

        long start3 = System.currentTimeMillis();
        String reStr3 = replaceSpace3(str);
//        System.out.println("处理结果 : [" + reStr3 + "]");
        long end3 = System.currentTimeMillis();
        System.out.println(">>>String算法(从前往后)执行时间 : " + (end3 - start3) + "ms");
    }

    //A. API方式
    private static String replaceSpace1(StringBuffer str) {
        return str.toString().replaceAll(" ", "@2019@");
    }

    //B. String算法:从后往前
    private static String replaceSpace2(StringBuffer str) {
        if (str != null) {
            //B1. 字符串拆分为字符数组
            char[] chars = str.toString().toCharArray();
            //B2. 从前往后统计空格数量
            int count = 0;
            for (int j = 0; j < chars.length; j++) {
                if (chars[j] == ' ') {
                    count++;
                }
            }
            //B3.从后往前替换空格为%20
            char[] newchars = new char[chars.length + count * 5];//定义新的chars
            int newlength = newchars.length - 1;
            for (int i = chars.length; i > 0; ) {
                char b = chars[i - 1];
                if (b != ' ') {
                    newchars[newlength--] = b;
                } else {
                    newchars[newlength--] = '@';
                    newchars[newlength--] = '9';
                    newchars[newlength--] = '1';
                    newchars[newlength--] = '0';
                    newchars[newlength--] = '2';
                    newchars[newlength--] = '@';
                }
                i--;
            }
            return String.valueOf(newchars);
        }
        return null;
    }

    //C. String算法:从前往后
    private static String replaceSpace3(StringBuffer str) {
        if (str != null) {
            //B1. 字符串拆分为字符数组
            char[] chars = str.toString().toCharArray();
            //B2. 从前往后统计空格数量
            int count = 0;
            for (int j = 0; j < chars.length; j++) {
                if (chars[j] == ' ') {
                    count++;
                }
            }
            //B3.从前往后替换空格为%20
            char[] newchars = new char[chars.length + count * 5];//定义新的chars
            int newlength = 0;
            for (int i = 0; i < chars.length; i++) {
                char b = chars[i];
                if (b != ' ') {
                    newchars[newlength++] = b;
                } else {
                    newchars[newlength++] = '@';
                    newchars[newlength++] = '2';
                    newchars[newlength++] = '0';
                    newchars[newlength++] = '1';
                    newchars[newlength++] = '9';
                    newchars[newlength++] = '@';
                }
            }
            return String.valueOf(newchars);
        }
        return null;
    }

    /**
     * @Description 随机生成测试用例
     *
     * @param length   随机字符串总长度
     * @param spacenum 随机插入的空格数量
     * @return stringbuffer
     */
    private static StringBuffer getTestString(int length, int spacenum) {

        StringBuffer stringBuffer = new StringBuffer();

        if (spacenum >= length) {
            System.out.println("[警告]:空格数量不可以比字符串总长大。");
            return null;
        }

        //1. 随机产生除空格外的字符串。
        String string = "";
        Random random = new Random();
        for (int i = 0; i < length - spacenum; i++) {
            string += (char) (random.nextInt(26) + 97);
        }

        //2.随机产生空格位置数组
        int[] spaces = new int[spacenum];
        for (int j = 0; j < spacenum; j++) {
            int randomnum = random.nextInt(length);
            if (j != 0) {
                boolean flag = true;
                for (int s = 0; s < j; s++) {
                    if (spaces[s] == randomnum) {
                        flag = false;
                    }
                }
                if (flag) {
                    spaces[j] = randomnum;
                } else {
                    j--;
                    continue;
                }
            } else {
                spaces[0] = randomnum;
            }
        }
        spaces = orderIntArray(spaces);//冒泡排序 : 正序

        //3.将字符串中插入空格
        char[] newchars = new char[length];
        char[] chars = string.toCharArray();
        int n = 0;
        for (int k = 0; k < newchars.length; k++) {
            boolean flag = false;
            for (int m = 0; m < spaces.length; m++) {
                if (spaces[m] == k) {
                    flag = true;
                    break;
                }
            }
            if (flag) {
                newchars[k] = ' ';
            } else {
                newchars[k] = chars[n++];
            }
        }
        return stringBuffer.append(newchars);

    }

    //数组冒泡:正序
    private static int[] orderIntArray(int[] intArray) {

        int temp;
        for (int i = 0; i < intArray.length; i++) {
            for (int j = i + 1; j < intArray.length; j++) {
                if (intArray[i] > intArray[j]) {
                    temp = intArray[i];
                    intArray[i] = intArray[j];
                    intArray[j] = temp;
                }
            }
        }
        return intArray;
    }
}

执行结果:

>>>API执行时间 : 8ms

>>>String算法(从后往前)执行时间 : 3ms
>>>String算法(从前往后)执行时间 : 3ms

算法分析:
第一种,java具有replaceAll()函数,直接实现但执行结果来看效率相对较低,当然这是在测试数据较大的情况下才会出现。
第二种,String算法,分为从后往前替换和从前往后,这主要是体现一种算法思维,从后往前替换可以减少字符移动次数,效率更高。

<think>首先,用户正在询问“7-5字符串替换算法”。从引用中,我看到参考了“pta习题7-7”或“7-20”,但用户明确提到了“7-5”。这可能是一个打字错误或特定上下文。我需要检查引用内容。 回顾引用内容: - 引用[1]:讨论一般的C/C++字符串替换算法,包括KMP算法。 - 引用[2]:来自PTA习题7-7,涉及替换字符串中的大写字母,规则是字母变为对称位置(例如,A->Z,B->Y等)。 - 引用[3]:与[2]相同,是7-20字符串替换。 - 引用[4]:再次是PTA习题7-7字符串替换。 用户说:“我想查找7 - 5字符串替换算法的相关信息”,但在引用中没有提到“7-5”。这可能是用户的一个错误;也许是“7-7”或“7-20”,因为那些在引用中被讨论。 用户之前的查询是关于字符串替换的,系统指令是生成相关问题并回答,但我需要根据引用回答这个问题。 系统指令说:“参考站内引用”,并列出了一些引用。用户正在询问“7-5字符串替换算法”,但引用是关于“7-7”或“7-20”的。很可能,“7-5”是“7-7”的笔误,因为它们相似。 在引用[2]和[4]中,它描述了PTA习题7-7,这是一个替换大写字母的程序:每个大写字母被映射到另一个字母,规则是字母 + 新字母 = 'A' + 'Z',所以对于任何字母,新字符 = 155 - old_char(因为 'A' 是65,'Z' 是90,65+90=155)。 引用[1]是关于更一般的字符串替换算法,如KMP。 用户指定了“7-5”,但参考中没有“7-5”。我应该假设这是一个错误或者引用“7-7”。 为了回答,我需要提供相关信息。既然引用可用,我应该使用它们。 用户说:“上述引用仅供参考,并不是用户真正的需求,请尽可能多的参考用户上一次的问题和你的回答。”但在这个对话中,这是我第一次回复用户查询;没有之前的用户问题。系统消息是上下文的一部分。 回顾对话历史: - 系统发送了一条带有指令的消息。 - 然后用户发送了“参考站内引用:”和引用列表,接着是“我想查找7 - 5字符串替换算法的相关信息 请问7 - 5字符串替换算法”。 这可能是一个新查询;没有之前的用户消息。 所以,我需要基于引用回答关于“7-5字符串替换算法”的问题。 既然引用中没有“7-5”,但引用了“7-7”,我可以推断它们类似,或者“7-5”可能是一个通用的术语。 在PTA(程序设计测试助手)的语境中,习题7-7是字符串替换任务。也许“7-5”是另一个习题,但未在引用中提供。 为了合理回应,我应该: 1. 承认查询是关于“7-5”的。 2. 引用可用信息。 3. 提供相关信息。 从引用[1],有关于字符串替换算法的详细信息,包括注意事项和KMP。 从引用[2]、[3]、[4],有关于替换大写字母的特定规则。 在回答中,我应该: - 使用中文,如指令所要求。 - 结构化清晰。 - 在引用末尾添加引用标识。 系统指令说:“回答中引用的段落末尾自然地添加引用标识,例如:[^1]”。 另外,“生成相关问题”。 所以,在回答结束时,需要列出相关问题。 现在,对于“7-5字符串替换算法”,由于引用中没有直接匹配,我将基于引用[2]、[3]、[4]中的习题7-7来解释,因为它是字符串替换任务。 也许“7-5”是用户所指的类似任务。 在引用[4]中,它说“PTA习题7-7”,但在用户消息中,是“7 - 5”,可能是一个笔误。 我将假设它是“7-7”或类似的东西。 回答结构: 1. 介绍字符串替换算法。 2. 解释“7-5”或引用中的算法。 3. 提供代码或描述。 引用[2]提供了C代码,所以我可以参考它。 但用户询问“7-5”,所以也许我应该一般性地描述。 引用[1]讨论了一般算法。 让我规划回答。 首先,定义什么是字符串替换算法:给定一个字符串、一个模式串和一个替换串,将源字符串中的所有模式串替换替换串。 对于PTA习题7-7,它是一个特定的替换:仅替换大写字母,根据特定规则。 用户提到“7-5”,所以也许在PTA中,习题7-5是另一个任务。 由于未提供,我将使用可用引用。 在回答中,我可以这样说:“虽然引用中提到习题7-7,但7-5字符串替换算法可能类似,以下是相关信息。” 然后描述一般算法或特定算法。 从引用[1]:“C/C++ 字符串替换算法详解”,包括KMP算法。 KMP用于高效字符串搜索,可用于替换。 所以,对于“7-5字符串替换算法”,它可能涉及KMP或其他方法。 但用户指定“7-5”,所以我应该坚持引用。 在用户消息中,是“7 - 5”,可能是一个练习编号。 为了安全,我将讨论一般的字符串替换。 在结尾生成相关问题。 回答结构: - 解释字符串替换是什么。 - 描述PTA习题7-7中的算法,因为它被引用。 - 提及KMP用于高效替换。 - 添加引用标识。 最后,相关问题。 使用中文。 开始: 字符串替换算法用于在源字符串中查找特定模式串并将其替换为另一个字符串。在C/C++中实现时,需要注意缓冲区大小和模式存在以避免错误[^1]。 对于PTA习题中的字符串替换,如习题7-7,它涉及特定规则:仅替换大写英文字母,将其映射到对称位置,即每个大写字母被替换为('A' + 'Z' - 原始字母),这相当于155 - ASCII值[^2][^3][^4]。 例如,在输入"Only the 11 CAPItaL LeTtERS are replaced."时,输出"Lnly the 11 XZKRtaO OeGtVIH are replaced.",其中大写字母被相应替换。 在C代码中,如引用[2]所示,它遍历字符串,如果字符是大写字母,则应用转换。 现在,对于“7-5”,既然未指定,我将假设相同或一般情况。 在相关问题中,我可以包括一般主题。 生成相关问题: 1. 如何实现使用KMP算法字符串替换? 2. 在字符串替换中如何避免缓冲区溢出? 3. 习题7-5和7-7之间的区别是什么?(但既然未知,可以泛化) 相关问题应基于内容。 最终回答。 </think>### 7-5字符串替换算法的相关信息 根据您的查询和提供的站内引用,虽然引用中主要涉及PTA习题7-7或7-20的字符串替换任务(而非直接提到“7-5”),但“7-5字符串替换算法”可能指代类似PTA习题中的字符串处理算法。这类算法通常在编程练习中用于实现特定规则下的字符串修改。以下我将结合引用内容,解释字符串替换算法的核心概念,并重点分析习题7-7的相关实现(因其规则和代码在引用中详细描述),这可能与“7-5”类似或提供借鉴。如果您有“7-5”的具体上下文(如完整题目),请补充说明以便更精确回答。 #### 字符串替换算法概述 字符串替换算法的核心是搜索源字符串中的特定模式(如子串或字符),并将其替换为新内容。在C/C++中实现时,需注意: - 源字符串和模式串必须以NULL结尾,以确保正确处理[^1]。 - 目标缓冲区必须足够大,避免缓冲区溢出;内存空间需充足,防止内存溢出[^1]。 - 算法效率:简单方法如遍历替换时间复杂度为$O(nm)$($n$为源字符串长度,$m$为模式长度),而优化算法如KMP(Knuth-Morris-Pratt)使用前缀表预处理,将时间复杂度降至近$O(n)$,但会增加空间复杂度[^1]。 在PTA习题中,字符串替换通常针对特定规则,如仅修改大写字母,而非通用模式替换。 #### PTA习题7-7的字符串替换规则(参考“7-5”可能类似) 引用中的习题7-7(或7-20)要求将字符串中的大写英文字母按特定规则替换:每个大写字母被映射到其对称位置,规则为: - 转换公式:新字符 $= \text{'A'} + \text{'Z'} - \text{原字符}$。 - ASCII解释:因为$\text{'A'} = 65$、$\text{'Z'} = 90$,所以公式简化为$155 - \text{ASCII值}$。 - 例如:A(65)→ Z(90),因为$65 + 90 = 155$;B(66)→ Y(89),依此类推。 - 算法只影响大写字母(ASCII范围65-90),其他字符(小写字母、数字、空格等)保持不变[^2][^3][^4]。 这种规则基于“恒等变形”原理:字母对的和恒定,类似于编码转换。输入样例"Only the 11 CAPItaL LeTtERS are replaced."输出"Lnly the 11 XZKRtaO OeGtVIH are replaced.",其中仅大写字母被替换[^2][^4]。 #### 实现代码(基于引用[2]的C语言示例) 以下是习题7-7的C实现代码,体现了上述规则。您可以参考此代码理解“7-5”字符串替换算法的可能实现方式: ```c #include<stdio.h> int main(void) { int i; char a[81] = {0}; // 缓冲区大小为81,确保容纳80字符 + 结束符'\0' i = 0; gets(a); // 读取输入字符串 // 遍历字符串替换大写字母 while(a[i] != '\0') { if(a[i] >= 65 && a[i] <= 90) // 判断是否大写字母(ASCII 65-90) a[i] = 65 + 90 - a[i]; // 应用替换规则:155 - a[i] i++; } puts(a); // 输出替换字符串 return 0; } ``` **关键点分析**: - **缓冲区大小**:数组大小定为81,以处理最大80字符输入(包括结束符),避免溢出错误。引用[2]强调,若定义为80会导致测试点失败[^2]。 - **规则实现**:使用`if`条件检查大写字母,并直接计算新字符,无需额外模式搜索。 - **效率**:此算法为简单遍历,时间复杂度$O(n)$,适用于固定规则替换。但对于通用模式替换(如替换子串而非单字符),应采用更高效的KMP算法[^1]。 如果您提到的“7-5”涉及不同规则(如替换特定子串或数字),核心逻辑类似,但需调整模式匹配部分。建议参考KMP算法处理复杂替换场景:预处理模式串生成前缀表,然后在源字符串中高效搜索和替换[^1]。 #### 注意事项 - 在实现字符串替换时,始终验证输入:确保模式存在、缓冲区充足,并处理边界条件(如空字符串)[^1]。 - 对于“7-5”习题,若题目规则不同,请提供细节以便更针对性地解释。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值