zoukankan      html  css  js  c++  java
  • 替换空格(C++和Python 实现)

    (说明:本博客中的题目题目详细说明参考代码均摘自 “何海涛《剑指Offer:名企面试官精讲典型编程题》2012年”)

    题目

        请实现一个函数,把字符串中的每个空格替换为 "%20" 。例如输入 "We are happy.", 则输出 "We%20are%20happy." 。

        进一步详细说明:

        在网络编程中,如果 URL 参数中含有特殊字符,如空格、'#'、':' 等,可能导致服务器端无法获得正确的参数值。我们需要这些特殊符号转换成服务器可以识别的字符。转换规则是在 '%' 后面跟上 ASCII 码的两位十六进制的表示。如空格的 ASCII 码是 32,即十六进制的 0x20,因此空格被替换成 "%20" 。再比如 '#' 的 ASCII 码为 35,即十六进制的 0x23,它在 URL 中被替换为 "%32"。再比如 ':' 的 ASCII 码为 50,即十六进制的 0x32,它在 URL 中被替换为 "%32"。

    算法设计思想

    1. 时间复杂度为 O(n2) 的算法思想

        从头到尾,扫描字符串中的每个字符,遇到空格,先将剩余的字符(未遍历到的字符串)整体向后移动2个位置,然后,在空格和其后的2个字符的替换为"%20"。

    2. 时间复杂度为 O(n) 的算法思想

        先遍历整个字符串,计算字符串中空格的总数,从而可以计算出替换后的字符串长度(根据替换规则,每次替换空格时,都会使字符串的长度增加2)。然后,使用两个指针或索引,从后往前遍历,即初始化指针或索引分别指向替换前和替换后字符串的末尾,循环递减,如遇到空格,则替换为 "%20",从而减少字符串移动的次数,降低时间复杂度。

    C++ 实现

    #include <iostream>
    
    // Replace blank " " with "%20"
    // Note - the 'length' parameter is the maximum length of the array
    void ReplaceBlanks(char str[], int length)
    {
        if (str == NULL || length <= 0)  // 易漏点
            return;
    
        // Count the number of blanks
        char *pChar = str;
        int strLen = 0;
        int blanksCount = 0;
        while (*pChar++ != '') {   // 易错点,容易漏掉指针递增操作,而导致运行时的死循环。
            ++strLen;
            if (*pChar == ' ')
                blanksCount++;
        }
        // Compute the replaced string length
        int replacedStrLen = strLen + 2 * blanksCount;
        if (replacedStrLen > length) {
            std::cout << "The char array is lack of space." << std::endl;
            return;
        }
        // Char pointer initialization
        char *pChar2 = str + replacedStrLen - 1;
        pChar = str + strLen - 1;
        while (pChar != pChar2) {
            // Replace blanks with "%20"
            if (*pChar == ' ') {
                pChar2 -= 2;
                *pChar2 = '%';
                *(pChar2 + 1) = '2';
                *(pChar2 + 2) = '0';
            } else {
                *pChar2 = *pChar;
            }
            --pChar;
            --pChar2;
        }
    }
    
    void unitest()
    {
        char s[100] = "We are happy.";
        std::cout << "Before replacing blanks, the string is " << s << std::endl;
        ReplaceBlanks(s, 100);
        std::cout << "After replacing blanks, the string is " << s << std::endl;
    }
    
    int main()
    {
        unitest();
    
        return 0;
    }

    Python 实现

    #!/usr/bin/python
    # -*- coding: utf8 -*-
    
    # Replace blank " " with "%20"
    # Note, the 'string' parameter is Python list type;
    #   and the 'length' parameter is the maximum length of the array.
    def replace_blanks(string, length):
        if string == None or length <= 0:  # 易漏点
            return
    
        # Count the number of blanks
        blanks_count = string.count(' ')
        string_length = len(string)
    
        # Compute the replaced string length
        replaced_length = string_length + 2 * blanks_count
        if replaced_length > length:
            return
        # Extend the char list length 'string_length' with '' characters
        string += ["" for i in range(replaced_length - string_length)]
    
        # Replace each blank with "%20"
        original_index = string_length - 1
        new_index = replaced_length - 1
        while new_index != original_index:
            if string[original_index] == ' ':
                new_index -= 2
                string[new_index:new_index+3] = '%20'
            else:
                string[new_index] = string[original_index]
            # Update indexes
            new_index -= 1
            original_index -= 1
    
    
    def unitest():
        test_string = "We are happy."
        string_lst = list(test_string)  # 易错点不能用'str'对象替代,因为 'str' object does not support item assignment 。
        print "Before replacing blanks, the string is %s" % ''.join(string_lst)
        replace_blanks(string_lst, 100)
        print "After replacing blanks, the string is %s" % ''.join(string_lst)
    
    if __name__ == '__main__':
        unitest()

     

    参考代码

    1. targetver.h

    #pragma once
    
    // The following macros define the minimum required platform.  The minimum required platform
    // is the earliest version of Windows, Internet Explorer etc. that has the necessary features to run 
    // your application.  The macros work by enabling all features available on platform versions up to and 
    // including the version specified.
    
    // Modify the following defines if you have to target a platform prior to the ones specified below.
    // Refer to MSDN for the latest info on corresponding values for different platforms.
    #ifndef _WIN32_WINNT            // Specifies that the minimum required platform is Windows Vista.
    #define _WIN32_WINNT 0x0600     // Change this to the appropriate value to target other versions of Windows.
    #endif

    2. stdafx.h

    // stdafx.h : include file for standard system include files,
    // or project specific include files that are used frequently, but
    // are changed infrequently
    //
    
    #pragma once
    
    #include "targetver.h"
    
    #include <stdio.h>
    #include <tchar.h>
    
    
    
    // TODO: reference additional headers your program requires here

    3. stdafx.cpp

    // stdafx.cpp : source file that includes just the standard includes
    // ReplaceBlank.pch will be the pre-compiled header
    // stdafx.obj will contain the pre-compiled type information
    
    #include "stdafx.h"
    
    // TODO: reference any additional headers you need in STDAFX.H
    // and not in this file

    4. ReplaceBlank.cpp

    // ReplaceBlank.cpp : Defines the entry point for the console application.
    //
    
    // 《剑指Offer——名企面试官精讲典型编程题》代码
    // 著作权所有者:何海涛
    
    #include "stdafx.h"
    #include <string>
    
    /*length 为字符数组string的总容量*/
    void ReplaceBlank(char string[], int length)
    {
        if(string == NULL && length <= 0)
            return;
    
        /*originalLength 为字符串string的实际长度*/
        int originalLength = 0;
        int numberOfBlank = 0;
        int i = 0;
        while(string[i] != '')
        {
            ++ originalLength;
    
            if(string[i] == ' ')
                ++ numberOfBlank;
    
            ++ i;
        }
    
        /*newLength 为把空格替换成'%20'之后的长度*/
        int newLength = originalLength + numberOfBlank * 2;
        if(newLength > length)
            return;
    
        int indexOfOriginal = originalLength;
        int indexOfNew = newLength;
        while(indexOfOriginal >= 0 && indexOfNew > indexOfOriginal)
        {
            if(string[indexOfOriginal] == ' ')
            {
                string[indexOfNew --] = '0';
                string[indexOfNew --] = '2';
                string[indexOfNew --] = '%';
            }
            else
            {
                string[indexOfNew --] = string[indexOfOriginal];
            }
    
            -- indexOfOriginal;
        }
    }
    
    void Test(char* testName, char string[], int length, char expected[])
    {
        if(testName != NULL)
            printf("%s begins: ", testName);
    
        ReplaceBlank(string, length);
    
        if(expected == NULL && string == NULL)
            printf("passed.
    ");
        else if(expected == NULL && string != NULL)
            printf("failed.
    ");
        else if(strcmp(string, expected) == 0)
            printf("passed.
    ");
        else
            printf("failed.
    ");
    }
    
    // 空格在句子中间
    void Test1()
    {
        const int length = 100;
    
        char string[length] = "hello world";
        Test("Test1", string, length, "hello%20world");
    }
    
    // 空格在句子开头
    void Test2()
    {
        const int length = 100;
    
        char string[length] = " helloworld";
        Test("Test2", string, length, "%20helloworld");
    }
    
    // 空格在句子末尾
    void Test3()
    {
        const int length = 100;
    
        char string[length] = "helloworld ";
        Test("Test3", string, length, "helloworld%20");
    }
    
    // 连续有两个空格
    void Test4()
    {
        const int length = 100;
    
        char string[length] = "hello  world";
        Test("Test4", string, length, "hello%20%20world");
    }
    
    // 传入NULL
    void Test5()
    {
        Test("Test5", NULL, 0, NULL);
    }
    
    // 传入内容为空的字符串
    void Test6()
    {
        const int length = 100;
    
        char string[length] = "";
        Test("Test6", string, length, "");
    }
    
    //传入内容为一个空格的字符串
    void Test7()
    {
        const int length = 100;
    
        char string[length] = " ";
        Test("Test7", string, length, "%20");
    }
    
    // 传入的字符串没有空格
    void Test8()
    {
        const int length = 100;
    
        char string[length] = "helloworld";
        Test("Test8", string, length, "helloworld");
    }
    
    // 传入的字符串全是空格
    void Test9()
    {
        const int length = 100;
    
        char string[length] = "   ";
        Test("Test9", string, length, "%20%20%20");
    }
    
    int _tmain(int argc, _TCHAR* argv[])
    {
        Test1();
        Test2();
        Test3();
        Test4();
        Test5();
        Test6();
        Test7();
        Test8();
        Test9();
    
        return 0;
    }

    5. 项目 04_ReplaceBlank 下载

    百度网盘: 04_ReplaceBlank.zip

    参考资料

    [1]  何海涛. 剑指 Offer:名企面试官精讲典型编程题 [M]. 北京:电子工业出版社,2012. 44-48.

  • 相关阅读:
    LeetCode 40. 组合总和 II(Combination Sum II)
    LeetCode 129. 求根到叶子节点数字之和(Sum Root to Leaf Numbers)
    LeetCode 60. 第k个排列(Permutation Sequence)
    LeetCode 47. 全排列 II(Permutations II)
    LeetCode 46. 全排列(Permutations)
    LeetCode 93. 复原IP地址(Restore IP Addresses)
    LeetCode 98. 验证二叉搜索树(Validate Binary Search Tree)
    LeetCode 59. 螺旋矩阵 II(Spiral Matrix II)
    一重指针和二重指针
    指针的意义
  • 原文地址:https://www.cnblogs.com/klchang/p/7501911.html
Copyright © 2011-2022 走看看