精华内容
下载资源
问答
  • 如何禁用完成字符串
    千次阅读
    2017-11-07 17:39:34

    字符串


    FName

    FName 通过一个轻型系统使用字符串。在此系统中,特定字符串即使会被重复使用,在数据表中也只存储一次。FNames 不区分大小写。它们为不可变,无法被操作。FNames 的存储系统和静态特性决定了通过键进行 FNames 的查找和访问速度较快。FName 子系统的另一个功能是使用散列表为 FName 转换提供快速字符串。

    FName不区分大小写,作为索引组合存储在唯一字符串和实例编号的表格中。

    创建FName
        FName TestHUDName = FName(TEXT("ThisIsTestFName"));
    FName转FString
        FString TestHUDString = TestHUDName.ToString();
    FName转FText
        FText TestHUDText = FText::FromName(TestHUDName);
    FString转FName
        TestHUDName = FName(*TestHUDString);
    FText到FName的转换不存在,可先转到FString,再转换到FName
        FText -> FString -> FName不可靠。因为FName不区分大小写,所以转换存在损耗

    执行这些转换时,需注意它们可能包含对创建中的 FName 类型无效的字符。 NameTypes.h 文件中的 INVALID_NAME_CHARACTERS 宏定义 FNames 中无效的字符; FName 中的数个函数(如 IsValidObjectName())将对 FNames 在特定使用情况下的有效性进行检查。

    FName之间的比对

    == 运算符用于对比两个FName,返回true或false
    它并不执行字符串的比对,而是对比索引中的数值,可极大地节约CPU的开销。

    FName::Compare还可同于对比两个FName,如果<Other将返回负数,==Other返回0,>Other则返回正数

    int32 CompareFloat = TestFName.Compare(OtherFName);
    使用FName

    在需要FName的地方直接构造即可

        FRotator rotPelvis = Mesh->MeshGetInstance(this)->GetBoneRotation(FName(TEXT("pelvis")));
    搜索名称表

    如需确定FName是否在名称表中(但不希望进行自动添加),可在FName构建函数中补充一个不同的搜索类型:

        if (FName(TEXT("pelvis"), FNAME_Find) != NAME_None)
        {
            //Do something
        }

    如果名称不在表中,FName的索引将被设定为NAME_None。!注意:将不对指针进行null检查,因为使用的是普通字符串


    FText

    FText 代表一个显示字符串。为用户显示的文本都需要由 FText 进行处理。FText 类拥有本地化的内置支持,可处理已本地化并存储在查找表中的文本内容,以及在运行时被本地化的文本,如数字、日期、时间和格式化文本。甚至可用 FText 处理无需进行本地化的文本。包括用户输入内容,如玩家名和 Slate 显示的文本。FText 不提供任何变异函数,因为对显示字符串进行修改是非常不安全的操作。

    Slate和FText

    整体而言,Slate弃用了FString的公开钩,转而支持FText。因为FText可在其接口后处理所有本地化问题,Slate未来支持诸如实时语言勾选之类的功能。使用FString将无法实现。使用FText还可增强文本渲染的性能。 使用FText时,字符串被假定为不可变,因此字符串的内存地址可用作快速缓存查找的键。与检查字符串更新或对其重新测量进行显示相比较,这种方法的开销较小。最后,在Slate中使用FText以为这本地化支持将与UI系统自然整合,形成本地化最佳方案的坚实框架。

    创建FText

    因为FText的本地化应用,每个FText必须以键和文本进行设置。使用LOCTEXTNSLOCTEXT宏可对FText进行正确设置。LOCTEXT将键和文本视为参数。所有参数必须为字符串文字。所有文字量将通过本地系统进行传递。
    必须首先将全局 LOCTEXT_NAMESPACE 宏设为字符串文字,以指定该本地化键的命名空间。

    使用 LOCTEXT 宏从字符串创建FText:

        /*Top of file*/
        #define LOCTEXT_NAMESPACE "Your Namespace"
        ...
        FText TestHUDText = LOCTEXT("Your Ket", "Your Text");
        ...
        #undef LOCTEXT_NAMESPACE
        /*Bottom of file*/

    除键和文本外,NSLOCTEXT还将命名空间作为参数。所有参数必须为字符串文字。所有文字量将通过本地化系统进行传递。

        FText TestHUDText = NSLOCTEXT("Your Namespace", "Your Key", "Your Text");

    也可以使用以下任意一个语法创建空白的FText:

        FText TestHUDText = FText::GetEmpty();
        FText TestHUDText = FText();
    FText转FString
        TestHUDString = TestHUDText.ToString();
        // FText -> FString 不可靠。它在一些语言的转换中存在潜在损耗
    FText转FName
        FTextFName的转换不存在,可先转换到FString,在转为FName
        // FText -> FString -> FName不可靠。因为FName不区分大小写,所在转换存在损耗

    FText字符串为不可变,因此必须将其复制,否则无法对返回的字符串进行修改

    FName转FText
        TestHUDText = FText::FromName(TestHUDName);
        // FName -> FText在一些情况下有效,但需注意FName内容不会从FText"自动本地化"中受益
    FString转FText
        TestHUDText = FText::FromString(TestHUDString);
        // FString -> FText在一些情况下有效,但需注意FString内容不会从FText"自动本地化"中受益
    从FName字符串到数字变量不存在转换
    数字变量转换为FText

    可使用 FText::AsNumber() 将浮点数和int转换为FText。此函数生成一个FText,代表当前文化中传递的数字。

        FText::AsNumber(CurrentHealth);

    额外的数字转换包括:
    FText::AsPercent() FText::AsCurrency() FText::AsDate() FText::AsTime()

    FText之间的比对

    可使用 FText::EqualTo()FText::EqualToCaseIgnored() 对两个FText字符串进行对比,接收true或false作为结果。使用 FText::ConmpareTo() 或者 FText::CompareToCaseIgnored() 对比字符串将返回一个整数值

    FText当前不对这些对比操作公开运算符,因为这些操作不是FString一类的简单序号比较。我们不使用常规的运算符表达操作的开销

    格式化FText

    可使用 FText::Format() 函数将不同的FText串联起来。如有需要,将其保存到FText变量

        FText::Format(LOCTEXT("HelloMessageFormat", "Hello {0}"), PlayerName)

    当前,格式化函数只将FText视为参数

    FText::Format支持两种不同类型的格式参数:排序和命名

    排序参数
    • 参数 = {0}、{1}、{2}、…等
    • 大括号标识格式参数的开头和结尾,数值说明已传递的参数
      FText::Format(
          LOCTEXT("HealthFormatStr", "{0} / {1}"), 
          FText::AsNumber(CurrentHealth), 
          FText::AsNumber(MaxHealth)
      )
    命名参数
    • 参数 = {Name}、{ID}、{Health}、…等
    • 大括号表示格式参数的开头和结尾,大括号之间的文本是在传入的 FFormatNamedArgs 集合中找到的参数名称
      FFormatNamedArguments Arguments;
      Arguments.Add(TEXT("CurrentHealth"), FText::AsNumber(CurrentHealth));
      EditorErrors.Error(
          FTExt::Format(
              LOCTEXT("ExampleFText", "You currently have {CurrentHealth} health left."),
              Arguments
          )
      );
    HUD中的FText
    Canvas

    如需使用 Canvas 在HUD中显示FText,必须新建一个 FCanvasTextItem

        FCanvasTextItem TextItem(FVector2D::ZeroVector, TestHUDText, BigFont, FLinearColor::Black);
    
        //设置文本变量即可更改FCanvasTextItem的文本
        FFormatNamedArguments Arguments;
        Arguments.Add(TEXT("CurrentHealth"), FText::AsNumber(CurrentHealth));
        TextItem.Text = FText::Format(
            LOCTEXT("ExampleFText", "You current have {CurrentHealth} health left."),
            Arguments
        );
    
        //调用 FCanvas->DrawItem() 函数即可将FText实际显示到屏幕上
        Canvas->DrawItem(TextItem, 10.0f, 10.0f);
        /*必须在HUD类的DrawHUD()函数中调用DrawItem()函数,或在以DrawHUD()开始的函数链中调用*/
    蓝图中的FText

    蓝图支持文本文字。文本数值的任意输入引脚将支持在节点中被指派一个数值,这些字符串将被收集用作本地化。

    FText::Format 在蓝图中也为可用。格式文本可为文字或连接到引脚。作为文本使用时,它将为格式化自动生成参数。因此,输入文字“There are {number} days until {day}.”后,一个 Number 引脚和一个 Day 引脚将被自动添加到节点。这些引脚可作为文字被填充或从变量被填充,输出文本将以钩住引脚的数值替代参数。

    在 Details 中可对引脚名进行变更、添加和移除


    FString

    与 FName 和 FText 不同,FString 是唯一允许操作的字符串类。字符串操作的可用方法有许多,如大小写转换、摘录子字符串和逆向。FStrings 可被搜集、修改、并与其他字符串进行对比。然而这些操作可能使 FString 的开销比不可变字符串类更大。

    创建FString
        FString TestHUDString = FString(TEXT("This is my test FString"));
    FString转FName
        TestHUDName = FName(*TestHUDString);
        //FString -> FName不可靠。因为FName不区分大小写,所以转换存在损耗
    FString转FText
        TestHUDText = FText::FromString(TestHUDString);
        //FString -> FText在一些情况下有效,但需注意FString内容不会从FText"自动本地化"中受益
    FName转FString
        TestHUDString = TestHUDName.ToString();
    FText转FString
        TestHUDString = TestHUDText.ToString();
        //FText -> FString不可靠,它在一些语言的转换中存在损耗
    数字和其他变量转FString
        //float -> FString
        FString::SanitizeFloat(FloatVariable);
    
        //int -> FString
        FString::FromInt(IntVariable);
    
        //bool -> FString
        InBool ? TEXT("true") : TEXT("false");
    
        //FVector -> FString
        VectorVariable.ToString();
    
        //FVector2D -> FString
        Vector2DVariable.ToString();
    
        //FRotator -> FString
        RotatorVariable.ToString();
    
        //FLinearColor -> FString
        LinearColorVariable.ToString();
    
        //UObject -> FString
        (InObj != NULL) ? InObj->GetName() : FString(TEXT("None"));

    对于其他数值转换,可使用带合适参数的 FString::Printf() 函数

    FString转其他变量
        //FString -> bool
        TestHUDString.ToBool();
    
        //FString -> int
        FCString::Atoi(*TestHUDString);
    
        //FString -> float
        FCString::Atof(*TestHUDString);
    FString之间的比对

    重载的==操作符可以用来比较两个FStrings,或者比较一个FString和一个TCHAR *的数组。还有FString :: Equals()方法,该方法需要FString进行测试,ESearchCase枚举是否应该忽略大小写作为参数。如果要比较忽略大小写,请使用ESearchCase :: IgnoreCase,如果不是,则使用ESearchCase :: CaseSensitive。

        TestHUDString.Equals(TEXT("Test"), ESearchCase::CaseSensitive);
    FString检索

    在FString中搜索时有两种搜索类型。第一种是 FString::Contains() ,找到子字符串后返回true,否则返回false。FString::Contains()可搜索FString或TCHAR*s子字符串。ESearchCase枚举可用于指定搜索是否忽略大小写。此外,ESearchDir枚举可用于指定搜索的方向。默认设置为忽略大小写,从开始执行搜索。

        TestHUDString.Contains(TEXT("Test"), ESearch::CaseSensitive, ESearchDir::FromEnd);

    第二种是 FString::Find() ,返回找到的第一个子字符串实例的索引。FString::Find()可对FString或TCHAR*s子字符串进行搜索。和FString::Contains()一样,可对大小写敏感和搜索方向进行指定,默认设置为忽略大小写并从字符串开头开始搜索。也可在索引中任选一个索引开始搜索。如果FString::Find()为找到子字符串,它将返回-1。

        TestHUDString.Find(TEXT("test"), ESearchCase::CaseSensitive, ESearchDir::FromEnd, 10);
    构建FString

    有两种方法可以从子字符串或其他变量类型中构造字符串。第一个连接只是将FStrings作为参数。在连接它们之前,需要将其他类型的变量转换为FStrings。其次,Printf可以接受像int和float这样的数字输入,还可以在添加到字符串时设置输入的格式。

    串联
    有两个运算符用于串联字符串:
    += 将提供的字符串附加到FString对象,StringResult += AddedString;
    + 新建一个FString对象并附加提供的字符串

    Printf
    FString::Printf 构建的FString可被存入FStrings,并与 UE_LOG 调试信息一同显示到屏幕上。格式参数同有和C++ printf函数相同的说明符

        FString AShooterHUD::GetTimeString(float TimeSeconds)
        {
            //only minutes and seconds are relevant
            const int32 TotalSeconds = FMath::Max(0, FMath::TruncToInt(TimeSeconds) % 3600);
            const int32 NumMinutes = TotalSeconds / 60;
            const int32 NumSeconds = TotalSeconfs % 60;
            const FString TimeDesc = FString::Printf(
                                        TEXT("%02d:%02d"), 
                                        NumMinutes, 
                                        NumSeconds
                                        )

    使用 %s 参数包含FString时,必须使用 * 运算符返回 %s 参数所需的 TCHAR *

    操作字符串

    可通过许多函数操作字符串。在 UnralString.h 文件中查阅。

    复制字符串分段的函数:Left、Right 和 Mid。可在找到的子字符串的位置将一个字符串分为两个字符串。 使用 Split 法即可完成此操作。拆分字符串的另一个方法是 ParseIntoArray,可将一个字符串拆分为字符串阵列,由指定的分隔符隔开。 使用 ToUpper 和 ToLower 即可完成大小写转换,将字符串转换为大写或小写。

    HUD中的FString

    Canvas
    如需要在HUD中显示FString,使用 Canvas 调用 FCancas::DrawText() 函数

        Canvas->DrawText(BigFont, TestHUDString, 110.0f, 110.0f);
        /*必须在HUD类的DrawHUD()函数中调用DrawItem()函数,或在以DrawHUD()开始的函数链中调用*/

    调试信息

    打印到视口

    FString可被打印到 视口 和 输出日志,以便进行调试
    使用 UEngine::AddOnScreenDebugMessage() 将调试信息打印到视口。

        /****
        * @param  Key            int     防止相同信息多次添加的唯一键。使用-1作为键,使调试信息短时出现
        * @param  TimeToDisplay  float   信息显示时长,按秒计算
        * @param  DisplayColor   FColor  文本显示的颜色
        * @param  DebugMessage   FString 显示的信息(FString)
        * ****/
        GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Blue, TEXT("Test debug message."));
    打印到输出日志

    UE_LOG 使用printf标记进行参数化

        /****
        * @param LogClass 日志类别。
        * 可使用现有的类别(在 `OutputDevices.h` 中用 `DECLARE_LOG_CATEGORY_EXTERN` 宏设置)
        * 也可以使用DEFINE_LOG_CATEGORY_STATIC定义自己的类别
        * @param Log 日志级别。在 `ELogVerbosity` 枚举中被定义
        * 有效值包含 `Fatal` `Error` `Warning` `Display` `Log` `Verbose` `VeryVerbose`
        * 下一个参数即为输出的文本,包括对参数的标记
        ****/
        UE_LOG(LogClass, Log, TEXT("This is a testing statement. %s"), *TestHUDString);
        //此范围使用一个 %s 参数,因此 * 运算符用于返回 %s 参数所需的 TCHAR*
    转换宏编码

    FString类构建在TCHARs的TArray之上。有多个宏可同于将应用字符串(TCHAR*)转换至ANSI或UNICODE字符集,反之亦然。宏定义的存储路径为 Engine\Source\Runtime\Core\Public\Containers\StringConv.h

    如果字符串相对较小,则在堆栈中作为转换器类的一部分进行分配; 否则堆被用来分配一个临时缓冲区。使用堆之前的大小是一个模板参数,所以你可以调整它到你的应用程序。这在循环内是安全的,因为类的范围从堆栈分配中弹出。

    常见的转换宏有:
    TCHAR_TO_ANSI 将引擎字符串(TCHAR*)转换为ANSI字符串
    ANSI_TO_TCHAR 将ANSO字符串转换为引擎字符串(TCHAR*)

    这些宏声明的对象具有非常短的生命周期。它们被用来作为参数来使用。您无法为转换的字符串的内容分配变量,因为对象将超出生命周期范围,并且字符串将被释放。


    传入的参数必须是适当的字符串,因为参数是指向一个指针的类型。如果你传递一个TCHAR而不是一个TCHAR *,它会编译,然后在运行时崩溃。
    用法:SomeApi(TCHAR_TO_ANSI(SomeUnicodeString));


    TCHAR

    TCHARs 用于存储不受正在使用的字符集约束的字符。平台不同,它们也可能存在不同。UE4 字符串在后台使用 TCHAR 数组将数据保存在 UTF-16 编码中。使用返回 TCHAR 的重载解引用运算符可以访问原始数据

    文本格式

    ASCII
    在32和126之间的字符(32和126包括在内)以及0、9、10和13。(P4型文本)(它在迁入的时候通过P4触发器才有效)

    ANSI
    ASCII及当前编码页面。(例如,Western European high ASCII)(在P4服务器上需要作为二进制来存储)

    UTF-8
    一个由可以使用特殊字符序列获取非ANSI字符的单独字节组成的字符串(P4型Unicode)

    UTF-16

    二进制

    优点
    没有定义内部格式,可以下载每个文件,无论是什么格式

    缺点
    不可以进行合并,需要将所有此类型的文件独占迁出
    没有定义内部格式,每个文件可以是不同的格式
    P4可以存储所有版本的完整内容,这样可能会没必要地使库大小膨胀得很大

    文本

    优点
    可合并,不需要独占迁出
    缺点
    非常有限,只允许ASCII字符

    UTF-8

    优点
    只会访问我们将会需要的所有字符
    使用更少的内存
    是一个ASCII的超级组合,一个纯ASCII字符是一个完全有效的UTF-8字符串
    在游戏检测到字符串时ASCII并且就这样将它输出时仍然可以正常工作
    如果没有一个启用Unicode的服务器,文件可以合并,并且不会要求独占迁出
    可以通过解析检测字符串是否是UTF-8(有或没有BOM)
    缺点
    对于亚洲语言而言有不同的内存分析
    在Perforce服务器上没有启用P4类型的Unicode
    字符串操作符更复杂
    MSDev在亚洲区域无法正常处理除ASCII之外的字符编码,这就是为什么Unreal在迁入的过程中将文本审核为ASCII

    UTF-16

    优点
    只会访问我们将会需要的所有字符
    字符串操作可以进行分割/合并,不需要解析这个字符串
    与游戏中使用的格式相同,不需要转换、解析或内存操作
    可合并,不需要独占迁出
    C# 会在内部使用 UTF-16
    缺点
    如果这个格式没有 BOM,那么很难检测到它
    当游戏检测到字符串是 ASCII 而且就这样将其输出的时候不能工作(现在是在迁入的时候通过 UTF-16 验证器进行检测
    MSDev 在亚洲区域无法正常处理除 ASCII 之外的字符编码

    UE4内部字符串表示

    虚幻引擎4中的所有字符串都以 UTF-16 的格式作为 FStrings 或 TCHAR 字符串存储在内存中。大多数代码假设两个字节是一个 codepoint(码点),所以仅支持Basic Multilingual Plane (BMP),可以将 Unreal 的内部编码更精确地描述为 UCS-2。字符串存储按照适于当前平台的字节序进行存储

    当把包 到/从 磁盘或网络上进行序列化时,具有所有 TCHAR 字符 < 0xff 的字符串都存储为一连串 8 位字节,其它的字符串存储为 2 位的 UTF-16 字符串。序列化代码可以根据需要处理任何字节序转换

    由UE4载入的文本文件

    当Unreal加载外部文本文件(比如在运行时读取一个.INI文件)时,这些操作基本上都是通过UnMisc.cpp中的 appLoadFileToString() 函数来完成。主要的工作发生在 appBufferToString() 函数中

    这个函数识别UTF-16文件中的Unicode字节顺序标记(BOM),如果存在的话,将以UTF-16的形式加载文件

    BOM 不存在时所发生的现象取决于平台

    如果在非Windows平台转换失败,它将仅读取每个字节,并把它填充为16位来构成一组TCHAR

    没有代码可以检测或解码使用appLoadFileToString()函数加载的UTF-8格式编码的贴图文件

    Unreal保存的文本文件

    大多数引擎产生的文本文件都是使用 appSaveStringToFile() 函数来进行保存

    通过一个字节可以展现所有TCHAR字符的字符串将被存储为一连串的8位字节;除了 bAlwaysSaveAsAnsi 标志传入的值为true外,其他的字符串都将会存储为UTF-16,在这种情况下,它将首先会被转换为默认的 Window 编码。目前,这个操作仅在着色器文件上执行,用于解决着色器编译器上的 UTF-16 文件的问题

    Unreal推荐使用的文件编码

    INT和INI文件

    任何字节排序的 UTF-16 格式。虽然亚洲语言(例如CP932)的默认MBCS编码可以在Windows上运行,但这些文件需要在PS3和Xbox360上加载,并且转换代码只能在Windows上运行

    源代码

    一般,不推荐 C++ 源码文件中存在的字符串文字,推荐把这些数据放到 INT 文件中

    C++源代码

    UTF-8或默认的Windows编码。Xbox360 的编译器 MSVC 和 gcc 应该都很容易处理 UTF-8 编码的源文件。Latin-1 编码的文件的字符具有高位集,比如应该避免在源码文件中出现版权、商标或者度数的符号,因为在具有不同编码的系统上,编码将会中断。某些这样的实例在第三方软件中是不可避免的(比如,版权标志),所以,我们仅用了 MSVC 的警告 4819,否则当我们在 Asian Windows 上进行编译时将会出现这个警告

    在Perforce中存储UTF-16文本文件

    • 请不要使用文本格式
      • 如果迁入了一个UTF-x文件并把它保存为文本文件,那么在同步后将会发生崩溃
    • 如果使用二进制格式,那么请把文件标记为独占迁出
      • 人们可以迁如ASCII、UTF-8、UTF-16格式的文件,它们是可以在引擎中正常工作的
      • 但是,二进制文件不能被融合,所以如果没有把文件标记为独占迁出,那么修改将会重叠到一起
    • 如果使用了UTF-16格式,请确保其他人没有迁入不是UTF-16的文件
      • Unreal有个Perforce触发器,它不允许迁入非UTF-16格式的文件作为UTF-16文件
        • //depot/UnrealEngine3/Development/Tools/P4Utils/CheckUTF16/
    • Unicode类型是UTF-8,当然这里没有什么用途

    转换机制

    我们有许多宏来把字符串转换为各种编码以及从各种编码转换回字符串。这些宏使用在本地范围内声明的类实例并且在栈上分配空间,所以不要保留指向它们的指针是很重要的! 它们的作用仅仅是将字符串传递给调用函数

    • TCHAR_TO_ANSI(str)
    • TCHAR_TO_OEM(str)
    • ANSI_TO_TCHAR(str)
    • TCHAR_TO_UTF8(str)
    • UTF8_TO_TCHAR(str)

    这些使用UnStringConv.h中的以下辅助类:

    • typedef TStringConversion FANSIToTCHAR;
    • typedef TStringConversion FTCHARToANSI;
    • typedef TStringConversion FTCHARToOEM;
    • typedef TStringConversion FTCHARToUTF8;
    • typedef TStringConversion FUTF8ToTCAHR;

    当使用TCHARTOANSI时,不要假设字节的数量和TCHAR字符串的长度一样也是很重要的。多字节的字符集的每个TCHAR字符可以对应多个字节。如果需要知道最终字符串的字节长度,可以使用辅助类而不是使用宏。比如:

        FString String;
        ...
        FTCHARToANSI Convert(*String);
        Ar->Serialize((ANSICHAR*)Convert, Convert.Length());
        //FTCHARToANSI::Length()函数返回编码字符串的字节长度,包括null文字

    Unicodevs的ToUpper()和ToLower() Non-Trivial

    UE4目前只会处理ANSI

    针对East Asian编码的C++源码的注意事项

    UTF-8和默认的Windows编码都可能导致C++编译器出现问题

    默认Windows编码

    如果源代码中有EastAsian双字节编码,比如CP932(日文)、CP936(简体中文) 或 CP950(繁体中文),那么当在运行单字节字符代码页(比如CP437 United States)的 Windows 上编译的 C++ 源码时要格外小心

    这些 East Asian 字符编码系统为第一字节使用 0x81-0xFE ,为第二个字节使用 0x40-0xFE。在第二个字节中的 0x5C 的值在 ASCII/latin-1 中将会被作为反斜线符号解释,并且它对 C++ 来说有特殊的意义。(如果在一行的末位使用它,将会决定一个字符串中的文字换码顺序及行连续性)。 当在单字节代码页的 Windows 上编译源码时,编译器不关心 East Asian 的双字节编码,这将可能会导致编译错误或者更糟糕的情况,在 EXE 中产生 bug

    单行注释:
    如果在East Asian编码的注释尾部有 0x5c ,这可能会造成代码行的丢失,而导致难以发现的bug或错误

        //East Asian编码以0x5c结尾(0x5c会被解释为反斜线,从而连接下一行代码)0x5c
        import_function();  //这行代码会被上一行的注释连接而丢失

    在一个字符串文字中:
    使用一个可识别的 0x5c 换码顺序,这可能会导致断裂的字符串或者其它错误

        printf("EastAsianCharacterThatContains0x5c'\'AndIfContains0x5cInTheEndOfString0x5c'\'");
        function();
        printf("Compiler recognizes left double quotation mark in this line as the end of string literal that continued from first line, and expected this message is C++ code.(编译器将会把左侧的双引号作为从第一行连续的字符串文字的尾部,并且编辑器将会把这个消息作为C++代码。)");

    在上面的例子中,字符串的尾部有 0x5c 反斜杠,并且下一个字符是双引号,所以换码顺序\”被转换为字符数据中的双引号,并且在下一个双引号或文件结尾之前,编译器将继续把它们当做字符串数据,从而导致了错误

    无BOM的UTF-8(某些文本编辑器将 BOM 作为识别标志)

    如果源码中有存储为UTF-8的East Asian字符,那么在 East Asian 代码页面 CP949(韩语)、CP932(日语)、CP936(简体中文)或 CP950(繁体中文)的 Windows 上编译 C++ 源码时一定要格外小心

    UTF-8 字符编码为 East Asian 字符使用 3 个字节: 为第一个字节使用 0xE0-0xEF 、第二个字节使用 0x80-0xBF 、第三个字节使用 0x80-0xBF。如果没有 BOM,East Asian 的 Windows 的默认编码将把 3 个 UTF-8 编码字节和接下来的字节作为 2 个字节的 East Asian 编码字符,第一个和第二个字节成对组成了第一个 East Asian 字符,第三个字节和接下来的字节成对组成第二个 East Asian 字符。 如果遵循 UTF-8 编码的三个字节在字符串字符或注释中有特殊的意义时,可能会出现一些问题

    比如,在一行的注释中:
    如果注释文本包含了奇数个 East Asian 字符,并且下一个字符作为注释的结束标志时,丢失的代码将会导致很难发现的 bug 或错误

        /*OddNumberOfEastAsianCharacterComment*/
        important_function();
        /*normal comment*/

    在 East Asian 编码页面的 Windows 上,编译器会将 UTF-8 的最后一个字节解码的 East Asian 字符注释和星号‘*’作为一个单独的 East Asian 字符,并且它接下来的字符将仍然作为注释的一部分对待。在上面的例子中,编译器删除了 important_function(),因为它似乎是注释的一部分。 这种行为是非常危险的,而且很难找到丢失的代码

    在字符串字符内部:
    当在一个字符串文字中有奇数个 UTF-8 编码的 East Asian 字符并且接下来的字符有特殊意义时,这将会导致断开的字符串、错误或警告

        printf("OddNumberOfEastAsiaCharacterString");
        printf("OddNumberOfEastAsiaCharacterString%d",0);
        printf("OddNumberOfEastAsiaCharacterString\n");

    在 East Asian 字符编码的 Windows 上,编译器会将 UTF-8 最后一字节的解码的 East Asian 字符串和一个字符作为一个单独的 East Asian 字符。如果您幸运,编译器将会出现 “C4819” 警告(如果没有禁用)或者一个错误来提示您该问题。如果您不走运,那么字符串将会被破坏

    总结

    可以为CV++源码使用UTF-8或默认的WIndows编码,但是知道这些可能出现问题。再次说明,不推荐在C++源码中加入字符串字符,如果必须在C++源码中使用East Asian字符编码,请一定要使用East Asian作为默认字符编码,另一个很好的方法是,使用具有 BOM 的 UTF-8(某些文本编辑器将 BOM 作为 Unicode 识别标志)

    更多相关内容
  • 今天我们来看一看MooTools给我们提供的额外的一些处理字符函数。这只是MooTools字符串处理中的一部分,并不包含一些神秘的函数(比如toCamelCase())和使用正则表达式处理字符串的函数。
  • 4.java字符串和输入输出

    万次阅读 2018-11-09 01:50:36
    目录 1.String类 2.StringBuilder类 3.StringBuffer类 4.Java:String、StringBuffer ...从概念上讲,java字符串就是Unicode字符序列。​​​​ String类提供处理Unicode代码点(即字符)的方法,以及用于处理...

    目录

    1.String类

    2.StringBuilder类

    3.StringBuffer类

    4.Java:String、StringBuffer 和 StringBuilder 的区别

    5.输入输出类

    6.java格式化输出


    1.String类

    从概念上讲,java字符串就是Unicode字符序列。​​​​

    String类提供处理Unicode代码点(即字符)的方法,以及用于处理Unicode代码单元(即char值)的方法。

    String类代表字符串。 Java程序中的所有字符串文字(例如"abc" )都被实现为此类的实例。

    字符串不变; 它们的值在创建后不能被更改。 字符串缓冲区支持可变字符串。 因为String对象是不可变的,它们可以被共享。

    构造方法

     
    Constructor and Description 
    String()

    初始化新创建的 String对象,使其表示空字符序列。

    String(byte[] bytes)

    通过使用平台的默认字符集解码指定的字节数组来构造新的 String

    String(byte[] bytes, Charset charset)

    构造一个新的String由指定用指定的字节的数组解码charset

    String(byte[] ascii, int hibyte)已弃用

    此方法无法将字节正确转换为字符。 从JDK 1.1开始,首选的方法是通过String构造函数获取Charset ,字符集名称,或者使用平台的默认字符集。

    String(byte[] bytes, int offset, int length)

    通过使用平台的默认字符集解码指定的字节子阵列来构造新的 String

    String(byte[] bytes, int offset, int length, Charset charset)

    构造一个新的String通过使用指定的指定字节子阵列解码charset

    String(byte[] ascii, int hibyte, int offset, int count)已弃用

    此方法无法将字节正确转换为字符。 从JDK 1.1开始,首选的方式是通过String构造函数获取Charset ,字符集名称,或使用平台的默认字符集。

    String(byte[] bytes, int offset, int length, String charsetName)

    构造一个新的 String通过使用指定的字符集解码指定的字节子阵列。

    String(byte[] bytes, String charsetName)

    构造一个新的String由指定用指定的字节的数组解码charset

    String(char[] value)

    分配一个新的 String ,以便它表示当前包含在字符数组参数中的字符序列。

    String(char[] value, int offset, int count)

    分配一个新的 String ,其中包含字符数组参数的子阵列中的字符。

    String(int[] codePoints, int offset, int count)

    分配一个新的 String ,其中包含 Unicode code point数组参数的子阵列中的 字符

    String(String original)

    初始化新创建的String对象,使其表示与参数相同的字符序列; 换句话说,新创建的字符串是参数字符串的副本。

    String(StringBuffer buffer)

    分配一个新的字符串,其中包含当前包含在字符串缓冲区参数中的字符序列。

    String(StringBuilder builder)

    分配一个新的字符串,其中包含当前包含在字符串构建器参数中的字符序列。

    常用方法:

    Modifier and TypeMethod and Description
    charcharAt(int index)

    返回 char指定索引处的值。

    intcodePointAt(int index)

    返回指定索引处的字符(Unicode代码点)。

    intcodePointBefore(int index)

    返回指定索引之前的字符(Unicode代码点)。

    intcodePointCount(int beginIndex, int endIndex)

    返回此 String指定文本范围内的Unicode代码点数。

    intcompareTo(String anotherString)

    按字典顺序比较两个字符串。

    intcompareToIgnoreCase(String str)

    按字典顺序比较两个字符串,忽略病例差异。

    Stringconcat(String str)

    将指定的字符串连接到该字符串的末尾。

    booleancontains(CharSequence s)

    当且仅当此字符串包含指定的char值序列时才返回true。

    booleancontentEquals(CharSequence cs)

    将此字符串与指定的CharSequence进行 CharSequence

    booleancontentEquals(StringBuffer sb)

    将此字符串与指定的StringBuffer进行 StringBuffer

    static StringcopyValueOf(char[] data)

    相当于 valueOf(char[])

    static StringcopyValueOf(char[] data, int offset, int count)

    相当于 valueOf(char[], int, int)

    booleanendsWith(String suffix)

    测试此字符串是否以指定的后缀结尾。

    booleanequals(Object anObject)

    将此字符串与指定对象进行比较。

    booleanequalsIgnoreCase(String anotherString)

    将此 String与其他 String比较,忽略案例注意事项。

    static Stringformat(Locale l, String format, Object... args)

    使用指定的区域设置,格式字符串和参数返回格式化的字符串。

    static Stringformat(String format, Object... args)

    使用指定的格式字符串和参数返回格式化的字符串。

    byte[]getBytes()

    使用平台的默认字符集将此 String编码为字节序列,将结果存储到新的字节数组中。

    byte[]getBytes(Charset charset)

    使用给定的charset将该String编码为字节序列,将结果存储到新的字节数组中。

    voidgetBytes(int srcBegin, int srcEnd, byte[] dst, int dstBegin)已弃用

    此方法无法将字符正确转换为字节。 从JDK 1.1开始,首选的方法是通过getBytes()方法,该方法使用平台的默认字符集。

    byte[]getBytes(String charsetName)

    使用命名的字符集将此 String编码为字节序列,将结果存储到新的字节数组中。

    voidgetChars(int srcBegin, int srcEnd, char[] dst, int dstBegin)

    将此字符串中的字符复制到目标字符数组中。

    inthashCode()

    返回此字符串的哈希码。

    intindexOf(int ch)

    返回指定字符第一次出现的字符串内的索引。

    intindexOf(int ch, int fromIndex)

    返回指定字符第一次出现的字符串内的索引,以指定的索引开始搜索。

    intindexOf(String str)

    返回指定子字符串第一次出现的字符串内的索引。

    intindexOf(String str, int fromIndex)

    返回指定子串的第一次出现的字符串中的索引,从指定的索引开始。

    Stringintern()

    返回字符串对象的规范表示。

    booleanisEmpty()

    返回 true如果,且仅当 length()0

    static Stringjoin(CharSequence delimiter, CharSequence... elements)

    返回一个新的字符串,由 CharSequence elements的副本组成,并附有指定的delimiter的 delimiter

    static Stringjoin(CharSequence delimiter, Iterable<? extends CharSequence> elements)

    返回一个新 String的副本组成 CharSequence elements与指定的副本一起加入 delimiter

    intlastIndexOf(int ch)

    返回指定字符的最后一次出现的字符串中的索引。

    intlastIndexOf(int ch, int fromIndex)

    返回指定字符的最后一次出现的字符串中的索引,从指定的索引开始向后搜索。

    intlastIndexOf(String str)

    返回指定子字符串最后一次出现的字符串中的索引。

    intlastIndexOf(String str, int fromIndex)

    返回指定子字符串的最后一次出现的字符串中的索引,从指定索引开始向后搜索。

    intlength()

    返回此字符串的长度。

    booleanmatches(String regex)

    告诉这个字符串是否匹配给定的 regular expression

    intoffsetByCodePoints(int index, int codePointOffset)

    返回此 String内的指数,与 index codePointOffset代码点。

    booleanregionMatches(boolean ignoreCase, int toffset, String other, int ooffset, int len)

    测试两个字符串区域是否相等。

    booleanregionMatches(int toffset, String other, int ooffset, int len)

    测试两个字符串区域是否相等。

    Stringreplace(char oldChar, char newChar)

    返回从替换所有出现的导致一个字符串 oldChar在此字符串 newChar

    Stringreplace(CharSequence target, CharSequence replacement)

    将与字面目标序列匹配的字符串的每个子字符串替换为指定的字面替换序列。

    StringreplaceAll(String regex, String replacement)

    用给定的替换替换与给定的 regular expression匹配的此字符串的每个子字符串。

    StringreplaceFirst(String regex, String replacement)

    用给定的替换替换与给定的 regular expression匹配的此字符串的第一个子字符串。

    String[]split(String regex)

    将此字符串分割为给定的 regular expression的匹配。

    String[]split(String regex, int limit)

    将这个字符串拆分为给定的 regular expression的匹配。

    booleanstartsWith(String prefix)

    测试此字符串是否以指定的前缀开头。

    booleanstartsWith(String prefix, int toffset)

    测试在指定索引处开始的此字符串的子字符串是否以指定的前缀开头。

    CharSequencesubSequence(int beginIndex, int endIndex)

    返回一个字符序列,该序列是该序列的子序列。

    Stringsubstring(int beginIndex)

    返回一个字符串,该字符串是此字符串的子字符串。

    Stringsubstring(int beginIndex, int endIndex)

    返回一个字符串,该字符串是此字符串的子字符串。

    char[]toCharArray()

    将此字符串转换为新的字符数组。

    StringtoLowerCase()

    将所有在此字符 String使用默认语言环境的规则,以小写。

    StringtoLowerCase(Locale locale)

    将所有在此字符 String ,以降低使用给定的规则情况下 Locale

    StringtoString()

    此对象(已经是字符串!)本身已被返回。

    StringtoUpperCase()

    将所有在此字符 String使用默认语言环境的规则大写。

    StringtoUpperCase(Locale locale)

    将所有在此字符 String使用给定的规则,大写 Locale

    Stringtrim()

    返回一个字符串,其值为此字符串,并删除任何前导和尾随空格。

    static StringvalueOf(boolean b)

    返回 boolean参数的字符串 boolean形式。

    static StringvalueOf(char c)

    返回 char参数的字符串 char形式。

    static StringvalueOf(char[] data)

    返回 char数组参数的字符串 char形式。

    static StringvalueOf(char[] data, int offset, int count)

    返回 char数组参数的特定子阵列的字符串 char形式。

    static StringvalueOf(double d)

    返回 double参数的字符串 double形式。

    static StringvalueOf(float f)

    返回 float参数的字符串 float形式。

    static StringvalueOf(int i)

    返回 int参数的字符串 int形式。

    static StringvalueOf(long l)

    返回 long参数的字符串 long形式。

    static StringvalueOf(Object obj)

    返回 Object参数的字符串 Object形式。

    2.StringBuilder类

    一个可变的字符序列。 此类提供与StringBuffer的API,但不保证同步。 此类设计用作简易替换为StringBuffer在正在使用由单个线程字符串缓冲区的地方(如通常是这种情况)。 在可能的情况下,建议使用这个类别优先于StringBuffer ,因为它在大多数实现中将更快。

    StringBuilder的主要StringBuilderappendinsert方法,它们是重载的,以便接受任何类型的数据。 每个都有效地将给定的数据转换为字符串,然后将该字符串的字符附加或插入字符串构建器。 append方法始终在构建器的末尾添加这些字符; insert方法将insert添加到指定点。

    构造方法

    Constructor and Description
    StringBuilder()

    构造一个没有字符的字符串构建器,初始容量为16个字符。

    StringBuilder(CharSequence seq)

    构造一个包含与指定的相同字符的字符串构建器 CharSequence

    StringBuilder(int capacity)

    构造一个没有字符的字符串构建器,由 capacity参数指定的初始容量。

    StringBuilder(String str)

    构造一个初始化为指定字符串内容的字符串构建器。

    常用方法

    Modifier and TypeMethod and Description
    StringBuilderappend(boolean b)

    boolean参数的字符串表示附加到序列中。

    StringBuilderappend(char c)

    char参数的字符串表示附加到此序列。

    StringBuilderappend(char[] str)

    char数组参数的字符串表示追加到此序列。

    StringBuilderappend(char[] str, int offset, int len)

    char数组参数的子阵列的字符串表示附加到此序列。

    StringBuilderappend(CharSequence s)

    将指定的字符序列追加到此 Appendable 。

    StringBuilderappend(CharSequence s, int start, int end)

    追加指定的序列 CharSequence的序列。

    StringBuilderappend(double d)

    double参数的字符串表示法附加到此序列。

    StringBuilderappend(float f)

    float参数的字符串表示附加到此序列。

    StringBuilderappend(int i)

    int参数的字符串表示法附加到此序列。

    StringBuilderappend(long lng)

    long参数的字符串表示法附加到此序列。

    StringBuilderappend(Object obj)

    追加 Object参数的字符串 Object形式。

    StringBuilderappend(String str)

    将指定的字符串附加到此字符序列。

    StringBuilderappend(StringBuffer sb)

    将指定 StringBuffer这个序列。

    StringBuilderappendCodePoint(int codePoint)

    codePoint参数的字符串表示附加到此序列。

    intcapacity()

    返回当前容量。

    charcharAt(int index)

    返回 char在指定索引在这个序列值。

    intcodePointAt(int index)

    返回指定索引处的字符(Unicode代码点)。

    intcodePointBefore(int index)

    返回指定索引之前的字符(Unicode代码点)。

    intcodePointCount(int beginIndex, int endIndex)

    返回此序列指定文本范围内的Unicode代码点数。

    StringBuilderdelete(int start, int end)

    删除此序列的子字符串中的字符。

    StringBuilderdeleteCharAt(int index)

    删除 char在这个序列中的指定位置。

    voidensureCapacity(int minimumCapacity)

    确保容量至少等于规定的最小值。

    voidgetChars(int srcBegin, int srcEnd, char[] dst, int dstBegin)

    字符从该序列复制到目标字符数组 dst

    intindexOf(String str)

    返回指定子字符串第一次出现的字符串内的索引。

    intindexOf(String str, int fromIndex)

    返回指定子串的第一次出现的字符串中的索引,从指定的索引开始。

    StringBuilderinsert(int offset, boolean b)

    boolean参数的字符串表示插入到此序列中。

    StringBuilderinsert(int offset, char c)

    在此序列中插入 char参数的字符串表示形式。

    StringBuilderinsert(int offset, char[] str)

    在此序列中插入 char数组参数的字符串表示形式。

    StringBuilderinsert(int index, char[] str, int offset, int len)

    在此序列中插入 str数组参数的子阵列的字符串表示形式。

    StringBuilderinsert(int dstOffset, CharSequence s)

    将指定的 CharSequence这个序列。

    StringBuilderinsert(int dstOffset, CharSequence s, int start, int end)

    将指定的CharSequence的子 CharSequence插入到此序列中。

    StringBuilderinsert(int offset, double d)

    在此序列中插入 double参数的字符串表示形式。

    StringBuilderinsert(int offset, float f)

    在此序列中插入 float参数的字符串表示形式。

    StringBuilderinsert(int offset, int i)

    将第二个 int参数的字符串表示插入到此序列中。

    StringBuilderinsert(int offset, long l)

    在此序列中插入 long参数的字符串表示形式。

    StringBuilderinsert(int offset, Object obj)

    Object参数的字符串表示插入到此字符序列中。

    StringBuilderinsert(int offset, String str)

    将字符串插入到此字符序列中。

    intlastIndexOf(String str)

    返回指定子字符串最右边出现的字符串内的索引。

    intlastIndexOf(String str, int fromIndex)

    返回指定子字符串最后一次出现的字符串中的索引。

    intlength()

    返回长度(字符数)。

    intoffsetByCodePoints(int index, int codePointOffset)

    返回此序列中与 indexcodePointOffset代码点偏移的索引。

    StringBuilderreplace(int start, int end, String str)

    用指定的String中的字符替换此序列的子字符串中的 String

    StringBuilderreverse()

    导致该字符序列被序列的相反代替。

    voidsetCharAt(int index, char ch)

    指定索引处的字符设置为 ch

    voidsetLength(int newLength)

    设置字符序列的长度。

    CharSequencesubSequence(int start, int end)

    返回一个新的字符序列,该序列是该序列的子序列。

    Stringsubstring(int start)

    返回一个新的 String ,其中包含此字符序列中当前包含的字符的子序列。

    Stringsubstring(int start, int end)

    返回一个新的 String ,其中包含此序列中当前包含的字符的子序列。

    StringtoString()

    返回表示此顺序中的数据的字符串。

    voidtrimToSize()

    尝试减少用于字符序列的存储。

    3.StringBuffer类

    线程安全,可变的字符序列。 字符串缓冲区就像一个String ,但可以修改。 在任何时间点,它包含一些特定的字符序列,但可以通过某些方法调用来更改序列的长度和内容。

    字符串缓冲区可以安全地被多个线程使用。 这些方法在必要时进行同步,以便任何特定实例上的所有操作都按照与所涉及的各个线程所执行的方法调用顺序一致的顺序发生。

    StringBuffer的主要StringBufferappendinsert方法,它们被重载以便接受任何类型的数据。 每个都有效地将给定的数据转换为字符串,然后将该字符串的字符附加或插入到字符串缓冲区。 append方法总是在缓冲区的末尾添加这些字符; insert方法将insert添加到指定点。

    构造方法

    Constructor and Description
    StringBuffer()

    构造一个没有字符的字符串缓冲区,初始容量为16个字符。

    StringBuffer(CharSequence seq)

    构造一个包含与指定的相同字符的字符串缓冲区 CharSequence

    StringBuffer(int capacity)

    构造一个没有字符的字符串缓冲区和指定的初始容量。

    StringBuffer(String str)

    构造一个初始化为指定字符串内容的字符串缓冲区。

    主要方法:

    Modifier and TypeMethod and Description
    StringBufferappend(boolean b)

    boolean参数的字符串表示附加到序列中。

    StringBufferappend(char c)

    char参数的字符串表示附加到此序列。

    StringBufferappend(char[] str)

    char数组参数的字符串表示附加到此序列。

    StringBufferappend(char[] str, int offset, int len)

    char数组参数的子阵列的字符串表示附加到此序列。

    StringBufferappend(CharSequence s)

    追加指定的 CharSequence到这个序列。

    StringBufferappend(CharSequence s, int start, int end)

    追加指定的序列 CharSequence到这个序列。

    StringBufferappend(double d)

    double参数的字符串表示附加到此序列。

    StringBufferappend(float f)

    float参数的字符串表示附加到此序列。

    StringBufferappend(int i)

    int参数的字符串表示附加到此序列。

    StringBufferappend(long lng)

    long参数的字符串表示附加到此序列。

    StringBufferappend(Object obj)

    追加 Object参数的字符串表示。

    StringBufferappend(String str)

    将指定的字符串附加到此字符序列。

    StringBufferappend(StringBuffer sb)

    将指定 StringBuffer这个序列。

    StringBufferappendCodePoint(int codePoint)

    codePoint参数的字符串表示法附加到此序列。

    intcapacity()

    返回当前容量。

    charcharAt(int index)

    返回 char在指定索引在这个序列值。

    intcodePointAt(int index)

    返回指定索引处的字符(Unicode代码点)。

    intcodePointBefore(int index)

    返回指定索引之前的字符(Unicode代码点)。

    intcodePointCount(int beginIndex, int endIndex)

    返回此序列指定文本范围内的Unicode代码点数。

    StringBufferdelete(int start, int end)

    删除此序列的子字符串中的字符。

    StringBufferdeleteCharAt(int index)

    删除 char在这个序列中的指定位置。

    voidensureCapacity(int minimumCapacity)

    确保容量至少等于规定的最小值。

    voidgetChars(int srcBegin, int srcEnd, char[] dst, int dstBegin)

    字符从该序列复制到目标字符数组 dst

    intindexOf(String str)

    返回指定子字符串第一次出现的字符串内的索引。

    intindexOf(String str, int fromIndex)

    返回指定子串的第一次出现的字符串中的索引,从指定的索引开始。

    StringBufferinsert(int offset, boolean b)

    在此序列中插入 boolean参数的字符串表示形式。

    StringBufferinsert(int offset, char c)

    在此序列中插入 char参数的字符串表示形式。

    StringBufferinsert(int offset, char[] str)

    在此序列中插入 char数组参数的字符串表示形式。

    StringBufferinsert(int index, char[] str, int offset, int len)

    在此序列中插入 str数组参数的子阵列的字符串表示形式。

    StringBufferinsert(int dstOffset, CharSequence s)

    将指定的 CharSequence这个序列。

    StringBufferinsert(int dstOffset, CharSequence s, int start, int end)

    将指定的子序列 CharSequence这个序列。

    StringBufferinsert(int offset, double d)

    在此序列中插入 double参数的字符串表示形式。

    StringBufferinsert(int offset, float f)

    在此序列中插入 float参数的字符串表示形式。

    StringBufferinsert(int offset, int i)

    将第二个 int参数的字符串表示插入到此序列中。

    StringBufferinsert(int offset, long l)

    在此序列中插入 long参数的字符串表示形式。

    StringBufferinsert(int offset, Object obj)

    Object参数的字符串表示插入到此字符序列中。

    StringBufferinsert(int offset, String str)

    将字符串插入到此字符序列中。

    intlastIndexOf(String str)

    返回指定子字符串最右边出现的字符串内的索引。

    intlastIndexOf(String str, int fromIndex)

    返回指定子字符串最后一次出现的字符串中的索引。

    intlength()

    返回长度(字符数)。

    intoffsetByCodePoints(int index, int codePointOffset)

    返回此序列中与 indexcodePointOffset代码点偏移的索引。

    StringBufferreplace(int start, int end, String str)

    用指定的String中的字符替换此序列的子字符串中的 String

    StringBufferreverse()

    导致该字符序列被序列的相反代替。

    voidsetCharAt(int index, char ch)

    指定索引处的字符设置为 ch

    voidsetLength(int newLength)

    设置字符序列的长度。

    CharSequencesubSequence(int start, int end)

    返回一个新的字符序列,该序列是该序列的子序列。

    Stringsubstring(int start)

    返回一个新的 String ,其中包含此字符序列中当前包含的字符的子序列。

    Stringsubstring(int start, int end)

    返回一个新的 String ,其中包含此序列中当前包含的字符的子序列。

    StringtoString()

    返回表示此顺序中的数据的字符串。

    voidtrimToSize()

    尝试减少用于字符序列的存储。

     

    4.Java:String、StringBuffer 和 StringBuilder 的区别

    String:字符串常量,字符串长度不可变。Java中String 是immutable(不可变)的。用于存放字符的数组被声明为final的,因此只能赋值一次,不可再更改。

    StringBuffer:字符串变量(Synchronized,即线程安全)。如果要频繁对字符串内容进行修改,出于效率考虑最好使用 。StringBuffer如果想转成 String 类型,可以调用 StringBuffer 的 toString() 方法。Java.lang.StringBuffer 线程安全的可变字符序列。在任意时间点上它都包含某种特定的字符序列,但通过某些方法调用可以改变该序列的长度和内容。可将字符串缓冲区安全地用于多个线程。

    StringBuilder:字符串变量(非线程安全)。在内部 StringBuilder 对象被当作是一个包含字符序列的变长数组。

    基本原则:

    如果要操作少量的数据用 String ;

    单线程操作大量数据用StringBuilder ;

    多线程操作大量数据,用StringBuffer。

    5.输入输出类

    5.1 java.lang.System

    System类包含几个有用的类字段和方法。 它不能被实例化。

    System类提供的System包括标准输入,标准输出和错误输出流; 访问外部定义的属性和环境变量; 一种加载文件和库的方法; 以及用于快速复制阵列的一部分的实用方法。

    构造方法:

    Modifier and TypeField and Description
    static PrintStreamerr

    “标准”错误输出流。

    static InputStreamin

    “标准”输入流。

    static PrintStreamout

    “标准”输出流。

    主要方法

    Modifier and TypeMethod and Description
    static voidarraycopy(Object src, int srcPos, Object dest, int destPos, int length)

    将指定源数组中的数组从指定位置复制到目标数组的指定位置。

    static StringclearProperty(String key)

    删除指定键指定的系统属性。

    static Consoleconsole()

    返回与当前Java虚拟机关联的唯一的Console对象(如果有)。

    static longcurrentTimeMillis()

    返回当前时间(以毫秒为单位)。

    static voidexit(int status)

    终止当前运行的Java虚拟机。

    static voidgc()

    运行垃圾回收器。

    static Map<String,String>getenv()

    返回当前系统环境的不可修改的字符串映射视图。

    static Stringgetenv(String name)

    获取指定环境变量的值。

    static PropertiesgetProperties()

    确定当前的系统属性。

    static StringgetProperty(String key)

    获取指定键指示的系统属性。

    static StringgetProperty(String key, String def)

    获取指定键指示的系统属性。

    static SecurityManagergetSecurityManager()

    获取系统安全界面。

    static intidentityHashCode(Object x)

    返回与默认方法hashCode()返回的给定对象相同的哈希码,无论给定对象的类是否覆盖了hashCode()。

    static ChannelinheritedChannel()

    返回从创建此Java虚拟机的实体继承的通道。

    static StringlineSeparator()

    返回与系统相关的行分隔符字符串。

    static voidload(String filename)

    加载由filename参数指定的本机库。

    static voidloadLibrary(String libname)

    加载 libname参数指定的本机库。

    static StringmapLibraryName(String libname)

    将库名称映射到表示本地库的平台特定字符串。

    static longnanoTime()

    以纳秒为单位返回正在运行的Java虚拟机的高分辨率时间源的当前值。

    static voidrunFinalization()

    运行任何对象等待定稿的最终化方法。

    static voidrunFinalizersOnExit(boolean value)已弃用

    这种方法本质上是不安全的。 它可能导致在活动对象上调用finalizer,而其他线程同时操作这些对象,导致不稳定的行为或死锁。

    static voidsetErr(PrintStream err)

    重新分配“标准”错误输出流。

    static voidsetIn(InputStream in)

    重新分配“标准”输入流。

    static voidsetOut(PrintStream out)

    重新分配“标准”输出流。

    static voidsetProperties(Properties props)

    将系统属性设置为 Properties参数。

    static StringsetProperty(String key, String value)

    设置由指定键指示的系统属性。

    static voidsetSecurityManager(SecurityManager s)

    设置系统安全性。

         5.2 java.util.Scanner

    一个简单的文本扫描器,可以使用正则表达式解析原始类型和字符串。

    A Scanner分隔符模式将输入打破到令牌,默认情况下匹配空格。 然后可以使用各种next方法将得到的令牌转换成不同类型的值。​​​​​​​

    构造方法:

    Constructor and Description
    Scanner(File source)

    构造一个新的 Scanner ,产生从指定文件扫描的值。

    Scanner(File source, String charsetName)

    构造一个新的 Scanner ,产生从指定文件扫描的值。

    Scanner(InputStream source)

    构造一个新的 Scanner ,产生从指定输入流扫描的值。

    Scanner(InputStream source, String charsetName)

    构造一个新的 Scanner ,产生从指定输入流扫描的值。

    Scanner(Path source)

    构造一个新的 Scanner ,产生从指定文件扫描的值。

    Scanner(Path source, String charsetName)

    构造一个新的 Scanner ,产生从指定文件扫描的值。

    Scanner(Readable source)

    构造一个新的 Scanner ,产生从指定源扫描的值。

    Scanner(ReadableByteChannel source)

    构造一个新的 Scanner ,产生从指定通道扫描的值。

    Scanner(ReadableByteChannel source, String charsetName)

    构造一个新的 Scanner ,产生从指定通道扫描的值。

    Scanner(String source)

    构造一个新的 Scanner ,产生从指定字符串扫描的值。

    常用方法:​​​​​​​

    Modifier and TypeMethod and Description
    voidclose()

    关闭此扫描仪。

    Patterndelimiter()

    返回 Pattern这个 Scanner正在使用来匹配分隔符。

    StringfindInLine(Pattern pattern)

    尝试找到忽略分隔符的指定模式的下一个出现。

    StringfindInLine(String pattern)

    尝试查找从指定字符串构造的模式的下一个出现,忽略分隔符。

    StringfindWithinHorizon(Pattern pattern, int horizon)

    尝试找到指定模式的下一个出现。

    StringfindWithinHorizon(String pattern, int horizon)

    尝试查找从指定字符串构造的模式的下一个出现,忽略分隔符。

    booleanhasNext()

    如果此扫描仪在其输入中有另一个令牌,则返回true。

    booleanhasNext(Pattern pattern)

    如果下一个完整的令牌匹配指定的模式,则返回true。

    booleanhasNext(String pattern)

    如果下一个令牌匹配从指定字符串构造的模式,则返回true。

    booleanhasNextBigDecimal()

    如果在此扫描器输入信息的下一个标记可以解释为,则返回true BigDecimal使用 nextBigDecimal()方法。

    booleanhasNextBigInteger()

    如果在此扫描器输入信息的下一个标记可以解释为,则返回true BigInteger在使用默认基数 nextBigInteger()方法。

    booleanhasNextBigInteger(int radix)

    如果在此扫描器输入信息的下一个标记可以解释为,则返回true BigInteger在使用指定基数 nextBigInteger()方法。

    booleanhasNextBoolean()

    如果此扫描器输入中的下一个标记可以使用从字符串“true | false”创建的不区分大小写的模式解释为布尔值,则返回true。

    booleanhasNextByte()

    如果此扫描仪输入中的下一个标记可以使用 nextByte()方法将其 解释为默认基数中的字节值,则返回true。

    booleanhasNextByte(int radix)

    如果扫描仪输入中的下一个标记可以使用 nextByte()方法解释为指定基数中的字节值,则返回true。

    booleanhasNextDouble()

    如果扫描仪的输入中的下一个标记可以使用 nextDouble()方法将其解释为双重值,则返回true。

    booleanhasNextFloat()

    如果扫描仪输入中的下一个标记可以使用 nextFloat()方法将其解释为浮点值,则返回true。

    booleanhasNextInt()

    如果此扫描仪输入中的下一个标记可以使用 nextInt()方法解释为默认基数中的int值,则返回true。

    booleanhasNextInt(int radix)

    如果此扫描仪输入中的下一个标记可以使用 nextInt()方法解释为指定基数中的int值,则返回true。

    booleanhasNextLine()

    如果扫描仪的输入中有另一行,则返回true。

    booleanhasNextLong()

    如果此扫描仪输入中的下一个标记可以使用 nextLong()方法将其 解释为默认基数中的长整型值,则返回true。

    booleanhasNextLong(int radix)

    如果扫描仪的输入中的下一个标记可以使用 nextLong()方法解释为指定基数中的长整型值,则返回true。

    booleanhasNextShort()

    如果此扫描仪输入中的下一个标记可以使用 nextShort()方法将其 解释为默认基数中的一个短值,则返回true。

    booleanhasNextShort(int radix)

    如果扫描仪的输入中的下一个标记可以使用 nextShort()方法解释为指定基数中的一个短值,则返回true。

    IOExceptionioException()

    返回 IOException最后通过此抛出 Scanner的基本 Readable

    Localelocale()

    返回此扫描仪的区域设置。

    MatchResultmatch()

    返回此扫描仪执行的最后扫描操作的匹配结果。

    Stringnext()

    查找并返回此扫描仪的下一个完整令牌。

    Stringnext(Pattern pattern)

    如果匹配指定的模式,则返回下一个令牌。

    Stringnext(String pattern)

    如果匹配从指定字符串构造的模式,则返回下一个令牌。

    BigDecimalnextBigDecimal()

    将输入的下一个标记扫描为BigDecimal

    BigIntegernextBigInteger()

    将输入的下一个标记扫描为BigInteger

    BigIntegernextBigInteger(int radix)

    将输入的下一个标记扫描为BigInteger

    booleannextBoolean()

    将输入的下一个标记扫描为布尔值,并返回该值。

    bytenextByte()

    将输入的下一个标记扫描为 byte 。

    bytenextByte(int radix)

    将输入的下一个标记扫描为 byte 。

    doublenextDouble()

    将输入的下一个标记扫描为 double 。

    floatnextFloat()

    将输入的下一个标记扫描为 float 。

    intnextInt()

    将输入的下一个标记扫描为 int 。

    intnextInt(int radix)

    将输入的下一个标记扫描为 int 。

    StringnextLine()

    将此扫描仪推进到当前行并返回跳过的输入。

    longnextLong()

    将输入的下一个标记扫描为 long 。

    longnextLong(int radix)

    将输入的下一个标记扫描为 long 。

    shortnextShort()

    将输入的下一个标记扫描为 short 。

    shortnextShort(int radix)

    将输入的下一个标记扫描为 short 。

    intradix()

    返回此扫描仪的默认基数。

    voidremove()

    Iterator的此实现不支持删除 Iterator

    Scannerreset()

    重设此扫描仪。

    Scannerskip(Pattern pattern)

    跳过与指定模式匹配的输入,忽略分隔符。

    Scannerskip(String pattern)

    跳过与指定字符串构成的模式匹配的输入。

    StringtoString()

    返回此 Scanner的字符串表示 Scanner

    ScanneruseDelimiter(Pattern pattern)

    将此扫描仪的分隔模式设置为指定的模式。

    ScanneruseDelimiter(String pattern)

    将此扫描器的分隔模式设置为从指定的构造的模式 String

    ScanneruseLocale(Locale locale)

    将此扫描仪的区域设置设置为指定的区域设置。

    ScanneruseRadix(int radix)

    将此扫描仪的默认基数设置为指定的基数。

         5.3 java.io.Console

    虚拟机是否具有控制台取决于底层平台以及虚拟机的调用方式。 如果虚拟机从交互式命令行启动,而不重定向标准输入和输出流,则其控制台将存在,并且通常将连接到启动虚拟机的键盘和显示器。 如果虚拟机是自动启动的,例如由后台作业调度程序启动,则通常不具有控制台。

    如果这个虚拟机有一个控制台,那么它由一个这个类的唯一实例表示,可以通过调用System.console()方法获得。 如果没有控制台设备可用,则该方法的调用将返回null 。

    读取和写入操作是同步的,以保证关键操作的原子完成; 因此调用方法readLine()readPassword()format()printf()以及读,格式和写在由返回的对象的操作reader()writer()在多线程方案可能阻塞。

    reader()writer()返回的对象调用close()将不会关闭这些对象的基础流。

    创建Console对象

    Console con = System.console();

    ​​​​​​​具体方法

    Modifier and TypeMethod and Description
    voidflush()

    刷新控制台并强制任何缓冲输出立即写入。

    Consoleformat(String fmt, Object... args)

    使用指定的格式字符串和参数将格式化的字符串写入此控制台的输出流。

    Consoleprintf(String format, Object... args)

    使用指定的格式字符串和参数将格式化的字符串写入此控制台的输出流的便利方法。

    Readerreader()

    检索与此控制台关联的唯一Reader对象。

    StringreadLine()

    从控制台读取一行文本。

    StringreadLine(String fmt, Object... args)

    提供一个格式化的提示,然后从控制台读取一行文本。

    char[]readPassword()

    从禁用回音的控制台读取密码或密码

    char[]readPassword(String fmt, Object... args)

    提供一个格式化的提示,然后从禁用回显的控制台读取密码或密码。

    PrintWriterwriter()

    检索与此控制台关联的唯一PrintWriter对象。

    6.java格式化输出

    System.out.format()

    System.out.printf()

    java.util.Formatter​​​​​​​

    构造方法

    Constructor and Description
    Formatter()

    构造一个新的格式化程序。

    Formatter(Appendable a)

    使用指定的目的地构造一个新的格式化程序。

    Formatter(Appendable a, Locale l)

    构造一个具有指定目的地和区域设置的新格式化程序。

    Formatter(File file)

    使用指定的文件构造一个新的格式化程序。

    Formatter(File file, String csn)

    使用指定的文件和字符集构造一个新的格式化程序。

    Formatter(File file, String csn, Locale l)

    使用指定的文件,字符集和区域设置构造一个新的格式化程序。

    Formatter(Locale l)

    构造具有指定区域设置的新格式化程序。

    Formatter(OutputStream os)

    使用指定的输出流构造一个新的格式化程序。

    Formatter(OutputStream os, String csn)

    使用指定的输出流和字符集构造一个新的格式化程序。

    Formatter(OutputStream os, String csn, Locale l)

    使用指定的输出流,字符集和区域设置构造一个新的格式化程序。

    Formatter(PrintStream ps)

    使用指定的打印流构造新的格式化程序。

    Formatter(String fileName)

    构造具有指定文件名的新格式化程序。

    Formatter(String fileName, String csn)

    构造具有指定文件名和字符集的新格式化程序。

    Formatter(String fileName, String csn, Locale l)

    构造具有指定文件名,字符集和区域设置的新格式化程序。

    ​​​​​​​方法

    Modifier and TypeMethod and Description
    voidclose()

    关闭此格式化程序。

    voidflush()

    刷新格式化程序。

    Formatterformat(Locale l, String format, Object... args)

    使用指定的区域设置,格式字符串和参数将格式化的字符串写入此对象的目标。

    Formatterformat(String format, Object... args)

    使用指定的格式字符串和参数将格式化的字符串写入此对象的目标。

    IOExceptionioException()

    返回此IOException最后抛出的IOException

    Localelocale()

    返回通过构建此格式化程序设置的区域设置。

    Appendableout()

    返回输出的目的地。

    StringtoString()

    返回在输出的 toString()上调用 toString()的结果。

        static Formatter formatter = new Formatter(System.out);
    	 
        public static void printTitle() {
            formatter.format("%-15s %-15s %-10s\n", "huhx", "linux", "liuli");
            formatter.format("%-15s %-15s %-10s\n", "zhangkun", "yanzi", "zhangcong");
            formatter.format("%-15s %-15s %-10s\n", "zhangkun", "yanzhou", "zhangcong");
        }

    输出结果:

    huhx            linux           liuli     
    zhangkun        yanzi           zhangcong 
    zhangkun        yanzhou         zhangcong 

    “ 格式说明符 ”的语法规则:

    è¿éåå¾çæè¿°

    数字

    转换符类型举例
    d十进制整数250
    f定点浮点数12.3
    s字符串hello
    c字符a
    b布尔型true
    h散列码87c258e

    标志

    标记目的举例
    +打印正数和负数的符合12345.6
    (将负数括在括号内-12345.7
    添加分组分隔符12,345.70
    0数字前面用 0 补位123.45
    <格式化前面说明的数值 
    -左对齐 
    #(对于f格式)包含小数点3,333.
    #(对于x或0格式)前面加0x或者0 0xf56a

    日期

    转换符类型举例
    c完整的日期和时间星期二 三月 28 11:00:52 CST 2017
    FISO 8601 日期2017/3/28
    D美国格式的日期(月/日/年)03/28/2017
    T24 小时时间11:00:52
    r12 小时时间11:00:52 AM
    R24 小时时间没有秒11:00
    Y4 位数字的年(前面补 0)2017
    y年的后两位数字(前面补 0)17
    C年的前两位数字(前面补 0)20
    B月的完整拼写March
    b 或者 h月的缩写Mar
    m两位数字的月(前面补 0)3
    d两位数字的日(前面补 0)28
    e两位数字的月(前面不补 0)3
    A星期几的完整拼写Monday
    a星期几的缩写Mon
    j三位数中的年的日(前面补 0),在 0001 到 366 之间87
    H两位数字的小时(前面补 0),在 0 到 23 之间11
    k两位数字的小时(前面不补 0),在 0 到 23 之间11
    M两位数字的分钟(前面补 0)26
    S两位数字的秒(前面补 0)17
    L三位数字的毫秒413
    N九位数字的毫微秒413000000
    P上午或下午的大写标志AM
    p上午或下午的小写标志am
    z从 GMT 起,RFC822 数位位移800
    Z时区CST
    s从格林威治时间 1970-01-01 00:00:00 起的秒数1490671516
    Q从格林威治时间 1970-01-01 00:00:00 起的毫秒数1.49067E+12

    例如:

    ​
                System.out.printf("%tc", new Date());
    	        System.out.println();
    	        System.out.printf("%tF", new Date());
    	        System.out.println();
    	        System.out.printf("%tT", new Date());
    	        System.out.println();
    	        System.out.printf("%tQ", new Date());
    
    ​

    输出结果:

    星期五 十一月 09 01:48:42 GMT+08:00 2018
    2018-11-09
    01:48:43
    1541699323006

     

    展开全文
  • LeetCode 字符串(简单题)

    千次阅读 2020-03-15 01:37:39
    答案摘抄自: https://leetcode-cn.com/tag/string/ 13. 罗马数字转整数 罗马数字包含以下七种字符: I, V, X, L,C,D 和 M。 字符 数值 I 1 V 5 X 10 L 50 C 100 D ...

    答案摘抄自:
    https://leetcode-cn.com/tag/string/

    13. 罗马数字转整数

    罗马数字包含以下七种字符: I, V, X, L,C,D 和 M。

    字符 数值
    I 1
    V 5
    X 10
    L 50
    C 100
    D 500
    M 1000
    例如, 罗马数字 2 写做 II ,即为两个并列的 1。12 写做 XII ,即为 X + II 。 27 写做 XXVII, 即为 XX + V + II 。

    通常情况下,罗马数字中小的数字在大的数字的右边。但也存在特例,例如 4 不写做 IIII,而是 IV。数字 1 在数字 5 的左边,所表示的数等于大数 5 减小数 1 得到的数值 4 。同样地,数字 9 表示为 IX。这个特殊的规则只适用于以下六种情况:

    I 可以放在 V (5) 和 X (10) 的左边,来表示 4 和 9。
    X 可以放在 L (50) 和 C (100) 的左边,来表示 40 和 90。
    C 可以放在 D (500) 和 M (1000) 的左边,来表示 400 和 900。
    给定一个罗马数字,将其转换成整数。输入确保在 1 到 3999 的范围内。

    示例 1:
    输入: “III”
    输出: 3
    示例 2:
    输入: “IV”
    输出: 4
    示例 3:
    输入: “IX”
    输出: 9
    示例 4:
    输入: “LVIII”
    输出: 58
    解释: L = 50, V= 5, III = 3.
    示例 5:

    输入: “MCMXCIV”
    输出: 1994
    解释: M = 1000, CM = 900, XC = 90, IV = 4.

    方法:
    按照题目的描述,可以总结如下规则:

    罗马数字由 I,V,X,L,C,D,M 构成;
    当小值在大值的左边,则减小值,如 IV=5-1=4;
    当小值在大值的右边,则加小值,如 VI=5+1=6;
    由上可知,右值永远为正,因此最后一位必然为正。
    一言蔽之,把一个小值放在大值的左边,就是做减法,否则为加法。

    在代码实现上,可以往后看多一位,对比当前位与后一位的大小关系,从而确定当前位是加还是减法。当没有下一位时,做加法即可。

    也可保留当前位的值,当遍历到下一位的时,对比保留值与遍历位的大小关系,再确定保留值为加还是减。最后一位做加法即可。

    import java.util.*;
    
    class Solution {
        public int romanToInt(String s) {
            int sum = 0;
            int preNum = getValue(s.charAt(0));
            for(int i = 1;i < s.length(); i ++) {
                int num = getValue(s.charAt(i));
                if(preNum < num) {
                    sum -= preNum;
                } else {
                    sum += preNum;
                }
                preNum = num;
            }
            sum += preNum;
            return sum;
        }
        
        private int getValue(char ch) {
            switch(ch) {
                case 'I': return 1;
                case 'V': return 5;
                case 'X': return 10;
                case 'L': return 50;
                case 'C': return 100;
                case 'D': return 500;
                case 'M': return 1000;
                default: return 0;
            }
        }
    }
    

    14. 最长公共前缀

    编写一个函数来查找字符串数组中的最长公共前缀。

    如果不存在公共前缀,返回空字符串 “”。

    示例 1:
    输入: [“flower”,“flow”,“flight”]
    输出: “fl”
    示例 2:
    输入: [“dog”,“racecar”,“car”]
    输出: “”
    解释: 输入不存在公共前缀。

    class Solution {
        public String longestCommonPrefix(String[] strs) {
            if (strs == null || strs.length == 0) return "";
            for (int i = 0; i < strs[0].length() ; i++){
                char c = strs[0].charAt(i);
                for (int j = 1; j < strs.length; j ++) {
                    if (i == strs[j].length() || strs[j].charAt(i) != c)
                        return strs[0].substring(0, i);             
                }
            }
            return strs[0];
        }
    }
    /*
    if(strs.length == 0) {
            return "";
        }
        for(int i=0; i<strs[0].length(); i++) {
            char c = (char) strs[0].charAt(i);
            for(int j=1; j<strs.length; j++) {
                if( c!=strs[j].charAt(i) || i==strs[j].length() ) {
                    return strs[0].substring(0, i);
                }
            }
        }
    
        return strs[0];
        */
    

    20. 有效的括号

    给定一个只包括 ‘(’,’)’,’{’,’}’,’[’,’]’ 的字符串,判断字符串是否有效。

    有效字符串需满足:

    左括号必须用相同类型的右括号闭合。
    左括号必须以正确的顺序闭合。
    注意空字符串可被认为是有效字符串。

    示例 1:
    输入: “()”
    输出: true
    示例 2:
    输入: “()[]{}”
    输出: true
    示例 3:
    输入: “(]”
    输出: false
    示例 4:
    输入: “([)]”
    输出: false
    示例 5:
    输入: “{[]}”
    输出: true

    class Solution {
    
      // Hash table that takes care of the mappings.
      private HashMap<Character, Character> mappings;
    
      // Initialize hash map with mappings. This simply makes the code easier to read.
      public Solution() {
        this.mappings = new HashMap<Character, Character>();
        this.mappings.put(')', '(');
        this.mappings.put('}', '{');
        this.mappings.put(']', '[');
      }
    
      public boolean isValid(String s) {
    
        // Initialize a stack to be used in the algorithm.
        Stack<Character> stack = new Stack<Character>();
    
        for (int i = 0; i < s.length(); i++) {
          char c = s.charAt(i);
    
          // If the current character is a closing bracket.
          if (this.mappings.containsKey(c)) {
    
            // Get the top element of the stack. If the stack is empty, set a dummy value of '#'
            char topElement = stack.empty() ? '#' : stack.pop();
    
            // If the mapping for this bracket doesn't match the stack's top element, return false.
            if (topElement != this.mappings.get(c)) {
              return false;
            }
          } else {
            // If it was an opening bracket, push to the stack.
            stack.push(c);
          }
        }
    
        // If the stack still contains elements, then it is an invalid expression.
        return stack.isEmpty();
      }
    }
    

    28. 实现 strStr()

    实现 strStr() 函数。

    给定一个 haystack 字符串和一个 needle 字符串,在 haystack 字符串中找出 needle 字符串出现的第一个位置 (从0开始)。如果不存在,则返回 -1。
    示例 1:
    输入: haystack = “hello”, needle = “ll”
    输出: 2
    示例 2:
    输入: haystack = “aaaaa”, needle = “bba”
    输出: -1

    说明:
    当 needle 是空字符串时,我们应当返回什么值呢?这是一个在面试中很好的问题。
    对于本题而言,当 needle 是空字符串时我们应当返回 0 。这与C语言的 strstr() 以及 Java的 indexOf() 定义相符。

    38. 外观数列

    「外观数列」是一个整数序列,从数字 1 开始,序列中的每一项都是对前一项的描述。前五项如下:

    1. 1
      
    2. 11
      
    3. 21
      
    4. 1211
      
    5. 111221
      

    1 被读作 “one 1” (“一个一”) , 即 11。
    11 被读作 “two 1s” (“两个一”), 即 21。
    21 被读作 “one 2”, “one 1” (“一个二” , “一个一”) , 即 1211。

    给定一个正整数 n(1 ≤ n ≤ 30),输出外观数列的第 n 项。

    注意:整数序列中的每一项将表示为一个字符串。

    示例 1:
    输入: 1
    输出: “1”
    解释:这是一个基本样例。
    示例 2:
    输入: 4
    输出: “1211”
    解释:当 n = 3 时,序列是 “21”,其中我们有 “2” 和 “1” 两组,“2” 可以读作 “12”,也就是出现频次 = 1 而 值 = 2;类似 “1” 可以读作 “11”。所以答案是 “12” 和 “11” 组合在一起,也就是 “1211”。

    58. 最后一个单词的长度

    给定一个仅包含大小写字母和空格 ’ ’ 的字符串 s,返回其最后一个单词的长度。如果字符串从左向右滚动显示,那么最后一个单词就是最后出现的单词。
    如果不存在最后一个单词,请返回 0 。
    说明:一个单词是指仅由字母组成、不包含任何空格字符的 最大子字符串。

    示例:
    输入: “Hello World”
    输出: 5

    class Solution {
        public int lengthOfLastWord(String s) {
            /*
            int end = s.length() - 1;
            while(end >= 0 && s.charAt(end) == ' ') end--;
            //if(end < 0) return 0;
            int start = end;
            while(start >= 0 && s.charAt(start) != ' ') start--;
            return end - start;     
            */
            s=s.trim();
            return s.length()-1-s.lastIndexOf(" ");
        }
    }
    

    67. 二进制求和

    给定两个二进制字符串,返回他们的和(用二进制表示)。
    输入为非空字符串且只包含数字 1 和 0。
    示例 1:
    输入: a = “11”, b = “1”
    输出: “100”
    示例 2:
    输入: a = “1010”, b = “1011”
    输出: “10101”

    class Solution {
        public String addBinary(String a, String b) {
            StringBuilder sb=new StringBuilder();
            int m=a.length();
            int n=b.length();
            //两个String形式二进制数相加,大的在前,小的在后
            if(m<n) return addBinary(b,a);
    
            int carry=0;
            int j=n-1;
            for(int i=m-1;i>=0;i--){
                if(a.charAt(i)=='1') carry++;
                if(j>=0 && b.charAt(j--)=='1') carry++;
                //如果carry值为1,sb加入元素1
                if(carry%2==1)  {
                    sb.append('1');
                }else{
                    sb.append('0');
                }
                //0/2=0;1/2=0;2/2=1(1为进位值,下一步要将此带入运算)
                carry/=2;
            }
            if(carry==1) sb.append('1');
            sb.reverse();
            return sb.toString();
        }
    }
    

    125. 验证回文串

    给定一个字符串,验证它是否是回文串,只考虑字母和数字字符,可以忽略字母的大小写。

    说明:本题中,我们将空字符串定义为有效的回文串。

    示例 1:
    输入: “A man, a plan, a canal: Panama”
    输出: true
    示例 2:
    输入: “race a car”
    输出: false

    class Solution {
        public boolean isPalindrome(String s) {
            int left=0;int right=s.length()-1;
            while(left<right){
                while(left<right && !Character.isLetterOrDigit(s.charAt(left))) left++;
                while(left<right && !Character.isLetterOrDigit(s.charAt(right))) right--;
                if(Character.toLowerCase(s.charAt(left))==Character.toLowerCase(s.charAt(right))){
                    left++;
                    right--;
                }else{
                    return false;
                }
            }
            return true;
        }
    }
    

    344. 反转字符串

    编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组 char[] 的形式给出。

    不要给另外的数组分配额外的空间,你必须原地修改输入数组、使用 O(1) 的额外空间解决这一问题。

    你可以假设数组中的所有字符都是 ASCII 码表中的可打印字符。

    示例 1:
    输入:[“h”,“e”,“l”,“l”,“o”]
    输出:[“o”,“l”,“l”,“e”,“h”]
    示例 2:
    输入:[“H”,“a”,“n”,“n”,“a”,“h”]
    输出:[“h”,“a”,“n”,“n”,“a”,“H”]

    class Solution {
        public void reverseString(char[] s) {
            int left=0;
            int right=s.length-1;
            while(left<right){
                char tmp=s[left];
                s[left++]=s[right];
                s[right--]=tmp;
            }
        }
    }
    

    345. 反转字符串中的元音字母

    编写一个函数,以字符串作为输入,反转该字符串中的元音字母。

    示例 1:
    输入: “hello”
    输出: “holle”
    示例 2:
    输入: “leetcode”
    输出: “leotcede”
    说明:
    元音字母不包含字母"y"。

    class Solution {
        public String reverseVowels(String s) {
            char[] array=s.toCharArray();
            int left=0;
            int right=s.length()-1;
            while(left<right){
                while(left<right && judge(array[left])) left++;
                while(left<right && judge(array[right])) right--;
                char tmp=array[left];
                array[left++]=array[right];
                array[right--]=tmp;
            }   
            String str=new String(array);
            return str;
        }
        public boolean judge(char c){
            if(c!='a' && c!='e' && c!='i' && c!='o'&& c!='u' && c!='A' && c!='E' && c!='I' && c!='O' & c!='U'){
                return true;
            }else{
                return false;
            }
        }
    }
    

    383. 赎金信

    给定一个赎金信 (ransom) 字符串和一个杂志(magazine)字符串,判断第一个字符串ransom能不能由第二个字符串magazines里面的字符构成。如果可以构成,返回 true ;否则返回 false。

    (题目说明:为了不暴露赎金信字迹,要从杂志上搜索各个需要的字母,组成单词来表达意思。)

    注意:

    你可以假设两个字符串均只含有小写字母。

    canConstruct(“a”, “b”) -> false
    canConstruct(“aa”, “ab”) -> false
    canConstruct(“aa”, “aab”) -> true

    class Solution {
        public boolean canConstruct(String ransomNote, String magazine) {
            int[ ] buckets=new int[26];
            for(int i=0;i<magazine.length();i++){
                buckets[magazine.charAt(i)-'a']++;
            }
            for(int j=0;j<ransomNote.length();j++){
                if(--buckets[ransomNote.charAt(j)-'a']<0){
                    return false;
                }
            }
            return true;
        }
    }
    

    387. 字符串中的第一个唯一字符

    给定一个字符串,找到它的第一个不重复的字符,并返回它的索引。如果不存在,则返回 -1。

    案例:
    s = “leetcode”
    返回 0.
    s = “loveleetcode”,
    返回 2.

    方法: 线性时间复杂度解法
    这道题最优的解法就是线性复杂度了,为了保证每个元素是唯一的,至少得把每个字符都遍历一遍。

    算法的思路就是遍历一遍字符串,然后把字符串中每个字符出现的次数保存在一个散列表中。这个过程的时间复杂度为 O(N),其中 N 为字符串的长度。

    接下来需要再遍历一次字符串,这一次利用散列表来检查遍历的每个字符是不是唯一的。如果当前字符唯一,直接返回当前下标就可以了。第二次遍历的时间复杂度也是 O(N)。

    class Solution {
        public int firstUniqChar(String s) {
            HashMap<Character,Integer> map=new HashMap<>();
            for(int i=0;i<s.length();i++){
                char c=s.charAt(i);
                map.put(c,map.getOrDefault(c,0)+1);
            }
    
            for(int i=0;i<s.length();i++){
                if(map.get(s.charAt(i))==1){
                    return i;
                }
            }
            return -1;
        }
    }
    

    415. 字符串相加

    给定两个字符串形式的非负整数 num1 和num2 ,计算它们的和。

    注意:
    num1 和num2 的长度都小于 5100.
    num1 和num2 都只包含数字 0-9.
    num1 和num2 都不包含任何前导零。
    你不能使用任何內建 BigInteger 库, 也不能直接将输入的字符串转换为整数形式。

    class Solution {
        public String addStrings(String num1, String num2) {
            StringBuilder sb=new StringBuilder();
            //进位处理
            int carry=0;
            for(int i=num1.length()-1,j=num2.length()-1;i>=0 || j>=0;i--,j--){
                int x= i>=0 ? num1.charAt(i)-'0' : 0;
                int y= j>=0 ? num2.charAt(j)-'0' : 0;
                int sum=x+y+carry;
                sb.append(sum%10);
                carry=sum/10;
            }
            if(carry == 1){
                sb.append("1");
            }
            return sb.reverse().toString();
        }
    }
    

    434. 字符串中的单词数

    统计字符串中的单词个数,这里的单词指的是连续的不是空格的字符。

    请注意,你可以假定字符串里不包括任何不可打印的字符。

    示例:
    输入: “Hello, my name is John”
    输出: 5

    class Solution {
        public int countSegments(String s) {
            /*
            int count=0;
            String[] array=s.split(" ");
            for(String arr:array){
                if(!"".equals(arr))
                count++;
            }
            return count;
            */
            int count=0,i=0,j=0;
            while(i<s.length()){
                while(i<s.length() && s.charAt(i)==' '){
                    i++;
                }
                j=i;
                if(j<s.length()){
                    while(j<s.length() && s.charAt(j)!=' '){
                        j++;
                    }
                count++;
                i=j;
                }
            }
            return count;
        }
    }
    

    443. 压缩字符串

    给定一组字符,使用原地算法将其压缩。
    压缩后的长度必须始终小于或等于原数组长度。
    数组的每个元素应该是长度为1 的字符(不是 int 整数类型)。
    在完成原地修改输入数组后,返回数组的新长度。

    进阶:
    你能否仅使用O(1) 空间解决问题?

    示例 1:
    输入:
    [“a”,“a”,“b”,“b”,“c”,“c”,“c”]
    输出:
    返回6,输入数组的前6个字符应该是:[“a”,“2”,“b”,“2”,“c”,“3”]
    说明:
    "aa"被"a2"替代。"bb"被"b2"替代。"ccc"被"c3"替代。
    示例 2:
    输入:
    [“a”]
    输出:
    返回1,输入数组的前1个字符应该是:[“a”]
    说明:
    没有任何字符串被替代。
    示例 3:
    输入:
    [“a”,“b”,“b”,“b”,“b”,“b”,“b”,“b”,“b”,“b”,“b”,“b”,“b”]
    输出:
    返回4,输入数组的前4个字符应该是:[“a”,“b”,“1”,“2”]。
    说明:
    由于字符"a"不重复,所以不会被压缩。"bbbbbbbbbbbb"被“b12”替代。
    注意每个数字在数组中都有它自己的位置。

    class Solution {
        public int compress(char[] chars) {
            StringBuilder sb=new StringBuilder();
            for(int i=0;i<chars.length;i++){
                int count=1;
                while(i<chars.length-1 && chars[i]==chars[i+1]){
                    count++;
                    i++;
                }
                if(count==1){
                    sb.append(chars[i]);
                }else{
                    sb.append(chars[i]).append(count);
                }
            }
            for(int i=0;i<sb.length();i++){
                chars[i]=sb.charAt(i);
            }
            return sb.length();
        }
    }
    

    459. 重复的子字符串

    给定一个非空的字符串,判断它是否可以由它的一个子串重复多次构成。给定的字符串只含有小写英文字母,并且长度不超过10000。

    示例 1:
    输入: “abab”
    输出: True
    解释: 可由子字符串 “ab” 重复两次构成。
    示例 2:
    输入: “aba”
    输出: False
    示例 3:
    输入: “abcabcabcabc”
    输出: True
    解释: 可由子字符串 “abc” 重复四次构成。 (或者子字符串 “abcabc” 重复两次构成。)

    class Solution {
        public boolean repeatedSubstringPattern(String s) {
            String str=s+s;
            return str.substring(1,str.length()-1).contains(s);
        }
    }
    

    520. 检测大写字母

    给定一个单词,你需要判断单词的大写使用是否正确。
    我们定义,在以下情况时,单词的大写用法是正确的:
    全部字母都是大写,比如"USA"。
    单词中所有字母都不是大写,比如"leetcode"。
    如果单词不只含有一个字母,只有首字母大写, 比如 “Google”。
    否则,我们定义这个单词没有正确使用大写字母。

    示例 1:
    输入: “USA”
    输出: True
    示例 2:
    输入: “FlaG”
    输出: False
    注意: 输入是由大写和小写拉丁字母组成的非空单词。

    class Solution {
        public boolean detectCapitalUse(String word) {
            int count=0;
            for(int i=0;i<word.length();i++){
                if(isUpperCase(word.charAt(i))){
                    count++;
                }
            }
            if(count==0 || count==word.length()){
                return true;
            }else if(isUpperCase(word.charAt(0)) && count==1){
                return true;
            }else{
                return false;
            }
        }
        public boolean isUpperCase(char c){
            if(c>='A' && c<='Z'){
                return true;
            }
            return false;
        }
    }
    

    521. 最长特殊序列 Ⅰ

    给定两个字符串,你需要从这两个字符串中找出最长的特殊序列。最长特殊序列定义如下:该序列为某字符串独有的最长子序列(即不能是其他字符串的子序列)。
    子序列可以通过删去字符串中的某些字符实现,但不能改变剩余字符的相对顺序。空序列为所有字符串的子序列,任何字符串为其自身的子序列。
    输入为两个字符串,输出最长特殊序列的长度。如果不存在,则返回 -1。

    示例 :
    输入: “aba”, “cdc”
    输出: 3
    解析: 最长特殊序列可为 “aba” (或 “cdc”)
    说明:
    两个字符串长度均小于100。
    字符串中的字符仅含有 ‘a’~‘z’。

    class Solution {
        public int findLUSlength(String a, String b) {
            if(a.equals(b)){
                return -1;
            }
            return Math.max(a.length(),b.length());
        }
    }
    

    541. 反转字符串 II

    给定一个字符串和一个整数 k,你需要对从字符串开头算起的每个 2k 个字符的前k个字符进行反转。如果剩余少于 k 个字符,则将剩余的所有全部反转。如果有小于 2k 但大于或等于 k 个字符,则反转前 k 个字符,并将剩余的字符保持原样。

    示例:
    输入: s = “abcdefg”, k = 2
    输出: “bacdfeg”
    要求:
    该字符串只包含小写的英文字母。
    给定字符串的长度和 k 在[1, 10000]范围内。

    class Solution {
        public String reverseStr(String s, int k) {
            char[] a = s.toCharArray();
            for (int start = 0; start < a.length; start += 2 * k) {
                int i = start, j = Math.min(start + k - 1, a.length - 1);
                while (i < j) {
                    char tmp = a[i];
                    a[i++] = a[j];
                    a[j--] = tmp;
                }
            }
            return new String(a);
        }
    }
    

    551. 学生出勤记录 I

    给定一个字符串来代表一个学生的出勤记录,这个记录仅包含以下三个字符:

    ‘A’ : Absent,缺勤
    ‘L’ : Late,迟到
    ‘P’ : Present,到场
    如果一个学生的出勤记录中不超过一个’A’(缺勤)并且不超过两个连续的’L’(迟到),那么这个学生会被奖赏。

    你需要根据这个学生的出勤记录判断他是否会被奖赏。

    示例 1:
    输入: “PPALLP”
    输出: True
    示例 2:
    输入: “PPALLL”
    输出: False

    class Solution {
        public boolean checkRecord(String s) {
            int count=0;
            for(int i=0;i<s.length() && count<2;i++){
                if(s.charAt(i)=='A'){
                    count++;
                }
            }
            return count<2 && s.indexOf("LLL")<0;
        }
    }
    

    557. 反转字符串中的单词 III

    给定一个字符串,你需要反转字符串中每个单词的字符顺序,同时仍保留空格和单词的初始顺序。

    示例 1:
    输入: “Let’s take LeetCode contest”
    输出: “s’teL ekat edoCteeL tsetnoc”
    注意:在字符串中,每个单词由单个空格分隔,并且字符串中不会有任何额外的空格。

    class Solution {
        public String reverseWords(String s) {
            StringBuilder sb=new StringBuilder();
            Stack<Character> stack=new Stack<>();
            for(char c:s.toCharArray()){
                if(c!=' '){
                    stack.push(c);
                }else{
                    while(!stack.empty()){
                        sb.append(stack.pop());
                    }
                    sb.append(' ');
                }
            }
            while(!stack.empty()){
                sb.append(stack.pop());
            }
            return sb.toString();
        }
    }
    /*
    方法 3:使用 StringBuilder 和 reverse 方法 [Accepted]
    算法
    
    这一方法中,我们不使用 split 方法,我们创建临时字符串 wordword 保存单词,我们在遍历过程中将字符逐一连接在 wordword 后面,直到我们遇到 ' '(空格) 字符。当我们遇到 ' ' 字符时,我们将 wordword 反转后连接在结果字符串 resultresult 后面。在遍历完成以后,我们返回结果字符串 resultresult 。
    
    Java
    public class Solution {
        public String reverseWords(String input) {
            final StringBuilder result = new StringBuilder();
            final StringBuilder word = new StringBuilder();
            for (int i = 0; i < input.length(); i++) {
                if (input.charAt(i) != ' ') {
                    word.append(input.charAt(i));
                } else {
                    result.append(word.reverse());
                    result.append(" ");
                    word.setLength(0);
                }
            }
            result.append(word.reverse());
            return result.toString();
        }
    }
    */
    

    606. 根据二叉树创建字符串

    你需要采用前序遍历的方式,将一个二叉树转换成一个由括号和整数组成的字符串。

    空节点则用一对空括号 “()” 表示。而且你需要省略所有不影响字符串与原始二叉树之间的一对一映射关系的空括号对。

    示例 1:
    输入: 二叉树: [1,2,3,4]
    1
    /
    2 3
    /
    4

    输出: “1(2(4))(3)”
    解释: 原本将是“1(2(4)())(3())”,
    在你省略所有不必要的空括号对之后,
    它将是“1(2(4))(3)”。
    示例 2:
    输入: 二叉树: [1,2,3,null,4]
    1
    /
    2 3
    \
    4

    输出: “1(2()(4))(3)”
    解释: 和第一个示例相似,
    除了我们不能省略第一个对括号来中断输入和输出之间的一对一映射关系。

    /**
     * Definition for a binary tree node.
     * public class TreeNode {
     *     int val;
     *     TreeNode left;
     *     TreeNode right;
     *     TreeNode(int x) { val = x; }
     * }
     */
    class Solution {
        public String tree2str(TreeNode t) {
            if (t == null)
                return "";
            Stack < TreeNode > stack = new Stack < > ();
            stack.push(t);
            Set < TreeNode > visited = new HashSet < > ();
            StringBuilder s = new StringBuilder();
            while (!stack.isEmpty()) {
                t = stack.peek();
                if (visited.contains(t)) {
                    stack.pop();
                    s.append(")");
                } else {
                    visited.add(t);
                    s.append("(" + t.val);
                    if (t.left == null && t.right != null)
                        s.append("()");
                    if (t.right != null)
                        stack.push(t.right);
                    if (t.left != null)
                        stack.push(t.left);
                }
            }
            return s.substring(1, s.length() - 1);
        }
    }
    /*
    方法一:递归
    我们可以使用递归的方法得到二叉树的前序遍历。在递归时,根据题目描述,我们需要加上额外的括号,会有以下 4 种情况:
    
    如果当前节点有两个孩子,那我们在递归时,需要在两个孩子的结果外都加上一层括号;
    
    如果当前节点没有孩子,那我们不需要在节点后面加上任何括号;
    
    
    
    如果当前节点只有左孩子,那我们在递归时,只需要在左孩子的结果外加上一层括号,而不需要给右孩子加上任何括号;
    
    
    如果当前节点只有右孩子,那我们在递归时,需要先加上一层空的括号 () 表示左孩子为空,再对右孩子进行递归,并在结果外加上一层括号。
    
    
    考虑完上面的 4 种情况,我们就可以得到最终的字符串。
    
    public class Solution {
        public String tree2str(TreeNode t) {
            if(t==null)
                return "";
            if(t.left==null && t.right==null)
                return t.val+"";
            if(t.right==null)
                return t.val+"("+tree2str(t.left)+")";
            return t.val+"("+tree2str(t.left)+")("+tree2str(t.right)+")";   
        }
    }
    复杂度分析
    
    时间复杂度:O(N)O(N),其中 NN 是二叉树中的节点数目。
    
    空间复杂度:O(N)O(N),在最坏情况下,会递归 NN 层,需要 O(N)O(N) 的栈空间。
    
    方法二:迭代
    我们也可以用迭代的方法解决这个问题。
    
    我们用一个栈来存储树中的一些节点,其中栈顶的元素为当前遍历到的节点,从栈底到栈顶的元素在树上即为从根到当前节点的唯一路径。和迭代得到前序遍历的方法略有不同,由于这里需要输出额外的括号,因此我们还需要用一个集合存储所有遍历过的节点,具体的原因在接下来会说明。
    
    首先我们把根节点入栈。对于当前栈顶的元素,如果它没有遍历过,那么就把它加入到集合中,并开始对以它为根的子树进行前序遍历。我们先在答案末尾添加一个 (,表示一个节点的开始,然后判断该节点的子节点个数。和方法一相同,这里会出现四种情况:如果它没有子节点,我们什么都不做;如果它有两个子节点,那么我们先将右孩子入栈,再将左孩子入栈,这样就保证了前序遍历的顺序;如果它只有左孩子,那么我们将左孩子入栈;如果它只有右孩子,那么我们在答案末尾添加一个 () 表示空的左孩子,再将右孩子入栈。注意这四种情况中,我们都不会将当前节点出栈,原因是我们一开始添加了 ( 表示节点的开始,在以当前节点为根的子树中所有节点遍历完成之后,我们才会在答案末尾添加 ) 表示节点的结束。因此我们需要用上面提到的集合来存储遍历过的节点,如果当前栈顶的元素遍历过,那么我们就知道需要在答案末尾添加 ),并将这个节点出栈。
    
    在迭代完成之后,我们得到的答案字符串的前后会有一对括号,我们把它去除后就可以得到最终的答案。
    
    
    1 / 13
    
    Java
    public class Solution {
        public String tree2str(TreeNode t) {
            if (t == null)
                return "";
            Stack < TreeNode > stack = new Stack < > ();
            stack.push(t);
            Set < TreeNode > visited = new HashSet < > ();
            StringBuilder s = new StringBuilder();
            while (!stack.isEmpty()) {
                t = stack.peek();
                if (visited.contains(t)) {
                    stack.pop();
                    s.append(")");
                } else {
                    visited.add(t);
                    s.append("(" + t.val);
                    if (t.left == null && t.right != null)
                        s.append("()");
                    if (t.right != null)
                        stack.push(t.right);
                    if (t.left != null)
                        stack.push(t.left);
                }
            }
            return s.substring(1, s.length() - 1);
        }
    }
    复杂度分析
    
    时间复杂度:O(N),其中 N 是二叉树中的节点数目。
    
    空间复杂度:O(N),在最坏情况下,栈中会存放 N 个节点。
    
    */
    

    657. 机器人能否返回原点

    在二维平面上,有一个机器人从原点 (0, 0) 开始。给出它的移动顺序,判断这个机器人在完成移动后是否在 (0, 0) 处结束。
    移动顺序由字符串表示。字符 move[i] 表示其第 i 次移动。机器人的有效动作有 R(右),L(左),U(上)和 D(下)。如果机器人在完成所有动作后返回原点,则返回 true。否则,返回 false。

    注意:机器人“面朝”的方向无关紧要。 “R” 将始终使机器人向右移动一次,“L” 将始终向左移动等。此外,假设每次移动机器人的移动幅度相同。

    示例 1:
    输入: “UD”
    输出: true
    解释:机器人向上移动一次,然后向下移动一次。所有动作都具有相同的幅度,因此它最终回到它开始的原点。因此,我们返回 true。
    示例 2:
    输入: “LL”
    输出: false
    解释:机器人向左移动两次。它最终位于原点的左侧,距原点有两次 “移动” 的距离。我们返回 false,因为它在移动结束时没有返回原点。

    class Solution {
        public boolean judgeCircle(String moves) {
            int x=0,y=0;
            for(char move:moves.toCharArray()){
                if(move=='U') y--;
                else if(move=='D') y++;
                else if(move=='L') x--;
                else if(move=='R') x++;
            }
            return x==0 && y==0;
        }
    }
    

    680. 验证回文字符串 Ⅱ

    给定一个非空字符串 s,最多删除一个字符。判断是否能成为回文字符串。

    示例 1:
    输入: “aba”
    输出: True
    示例 2:
    输入: “abca”
    输出: True
    解释: 你可以删除c字符。

    class Solution {
        public boolean validPalindrome(String s) {
            for(int i=0,j=s.length()-1;i<j;i++,j--){
                if(s.charAt(i)!=s.charAt(j)){
                    return judge(s,i+1,j) || judge(s,i,j-1);
                }
            }
            return true;
        }
        public boolean judge(String s,int i,int j){
            while(i<j){
                if(s.charAt(i++)!=s.charAt(j--)){
                    return false;
                }
            }
            return true;
        }
    }
    

    686. 重复叠加字符串匹配

    给定两个字符串 A 和 B, 寻找重复叠加字符串A的最小次数,使得字符串B成为叠加后的字符串A的子串,如果不存在则返回 -1。

    举个例子,A = “abcd”,B = “cdabcdab”。

    答案为 3, 因为 A 重复叠加三遍后为 “abcdabcdabcd”,此时 B 是其子串;A 重复叠加两遍后为"abcdabcd",B 并不是其子串。

    注意:

    A 与 B 字符串的长度在1和10000区间范围内。

    696. 计数二进制子串

    给定一个字符串 s,计算具有相同数量0和1的非空(连续)子字符串的数量,并且这些子字符串中的所有0和所有1都是组合在一起的。

    重复出现的子串要计算它们出现的次数。

    示例 1 :
    输入: “00110011”
    输出: 6
    解释: 有6个子串具有相同数量的连续1和0:“0011”,“01”,“1100”,“10”,“0011” 和 “01”。
    请注意,一些重复出现的子串要计算它们出现的次数。
    另外,“00110011”不是有效的子串,因为所有的0(和1)没有组合在一起。
    示例 2 :
    输入: “10101”
    输出: 4
    解释: 有4个子串:“10”,“01”,“10”,“01”,它们具有相同数量的连续1和0。

    709. 转换成小写字母

    实现函数 ToLowerCase(),该函数接收一个字符串参数 str,并将该字符串中的大写字母转换成小写字母,之后返回新的字符串。
    示例 1:
    输入: “Hello”
    输出: “hello”
    示例 2:
    输入: “here”
    输出: “here”
    示例 3:
    输入: “LOVELY”
    输出: “lovely”

    class Solution {
        public String toLowerCase(String str) {
            /*
            if(str==null){
                return null;
            }
            return str.toLowerCase();
            */
            if(str==null){
                return null;
            }
            char[] array=str.toCharArray();
            int length=array.length;
            for(int i=0;i<length;i++){
                if(array[i]>='A'&&array[i]<='Z'){
                    array[i]+=32;
                }
            }
            //return String.valueOf(array);
            String s=new String(array);
            return s;
        }
    }
    

    788. 旋转数字

    我们称一个数 X 为好数, 如果它的每位数字逐个地被旋转 180 度后,我们仍可以得到一个有效的,且和 X 不同的数。要求每位数字都要被旋转。

    如果一个数的每位数字被旋转以后仍然还是一个数字, 则这个数是有效的。0, 1, 和 8 被旋转后仍然是它们自己;2 和 5 可以互相旋转成对方;6 和 9 同理,除了这些以外其他的数字旋转以后都不再是有效的数字。

    现在我们有一个正整数 N, 计算从 1 到 N 中有多少个数 X 是好数?

    示例:
    输入: 10
    输出: 4
    解释:
    在[1, 10]中有四个好数: 2, 5, 6, 9。
    注意 1 和 10 不是好数, 因为他们在旋转之后不变。

    class Solution {
        public int rotatedDigits(int N) {
             // Count how many n in [1, N] are good.
            int ans = 0;
            for (int n = 1; n <= N; ++n)
                if (good(n, false)) ans++;
            return ans;
        }
    
    
        // Return true if n is good.
        // The flag is true iff we have an occurrence of 2, 5, 6, 9.
        public boolean good(int n, boolean flag) {
            if (n == 0) return flag;
    
            int d = n % 10;
            if (d == 3 || d == 4 || d == 7) return false;
            if (d == 0 || d == 1 || d == 8) return good(n / 10, flag);
            return good(n / 10, true);
        }
    }
    

    804. 唯一摩尔斯密码词

    国际摩尔斯密码定义一种标准编码方式,将每个字母对应于一个由一系列点和短线组成的字符串, 比如: “a” 对应 “.-”, “b” 对应 “-…”, “c” 对应 “-.-.”, 等等。

    为了方便,所有26个英文字母对应摩尔斯密码表如下:

    [".-","-…","-.-.","-…",".","…-.","–.","…","…",".—","-.-",".-…","–","-.","—",".–.","–.-",".-.","…","-","…-","…-",".–","-…-","-.–","–…"]
    给定一个单词列表,每个单词可以写成每个字母对应摩尔斯密码的组合。例如,“cab” 可以写成 “-.-…–…”,(即 “-.-.” + “-…” + ".-"字符串的结合)。我们将这样一个连接过程称作单词翻译。

    返回我们可以获得所有词不同单词翻译的数量。

    例如:
    输入: words = [“gin”, “zen”, “gig”, “msg”]
    输出: 2
    解释:
    各单词翻译如下:
    “gin” -> “–…-.”
    “zen” -> “–…-.”
    “gig” -> “–…--.”
    “msg” -> “–…--.”

    共有 2 种不同翻译, “–…-.” 和 “–…--.”.

    class Solution {
        public int uniqueMorseRepresentations(String[] words) {
            String[] MORSE = new String[]{".-","-...","-.-.","-..",".","..-.","--.",
                             "....","..",".---","-.-",".-..","--","-.",
                             "---",".--.","--.-",".-.","...","-","..-",
                             "...-",".--","-..-","-.--","--.."};
    
            Set<String> seen = new HashSet();
            for (String word: words) {
                StringBuilder code = new StringBuilder();
                for (char c: word.toCharArray())
                    code.append(MORSE[c - 'a']);
                seen.add(code.toString());
            }
    
            return seen.size();
        }
    }
    

    819. 最常见的单词

    给定一个段落 (paragraph) 和一个禁用单词列表 (banned)。返回出现次数最多,同时不在禁用列表中的单词。题目保证至少有一个词不在禁用列表中,而且答案唯一。

    禁用列表中的单词用小写字母表示,不含标点符号。段落中的单词不区分大小写。答案都是小写字母。

    示例:
    输入:
    paragraph = “Bob hit a ball, the hit BALL flew far after it was hit.”
    banned = [“hit”]
    输出: “ball”
    解释:
    “hit” 出现了3次,但它是一个禁用的单词。
    “ball” 出现了2次 (同时没有其他单词出现2次),所以它是段落里出现次数最多的,且不在禁用列表中的单词。
    注意,所有这些单词在段落里不区分大小写,标点符号需要忽略(即使是紧挨着单词也忽略, 比如 “ball,”),
    "hit"不是最终的答案,虽然它出现次数更多,但它在禁用单词列表中。

    方法:简单计数:
    我们统计出每个单词出现的次数,忽略所有的标点符号和大小写,答案即为出现次数最多且不在禁用列表中的那个单词。

    统计单词的方法有两种。在第一种方法中,我们首先对整个段落按照空格进行分词(split),然后对于分出的每个单词,我们移除标点符号并忽略大小写。在第二种方法中,我们逐字符扫描整个段落,如果遇到一个非字母的符号,那就把之前遇到的字母作为一个单词。

    对于每一个单词,我们会放入哈希映射(Java 中的 HashMap 或者 Python 中的 Counter)中进行计数。在每次放入单词之后,如果这个单词不在禁用列表中,我们就可以更新一次答案。

    class Solution {
        public String mostCommonWord(String paragraph, String[] banned) {
            paragraph += ".";
    
            Set<String> banset = new HashSet();
            for (String word: banned) banset.add(word);
            Map<String, Integer> count = new HashMap();
    
            String ans = "";
            int ansfreq = 0;
    
            StringBuilder word = new StringBuilder();
            for (char c: paragraph.toCharArray()) {
                if (Character.isLetter(c)) {
                    word.append(Character.toLowerCase(c));
                } else if (word.length() > 0) {
                    String finalword = word.toString();
                    if (!banset.contains(finalword)) {
                        count.put(finalword, count.getOrDefault(finalword, 0) + 1);
                        if (count.get(finalword) > ansfreq) {
                            ans = finalword;
                            ansfreq = count.get(finalword);
                        }
                    }
                    word = new StringBuilder();
                }
            }
    
            return ans;
        }
    }
    

    824. 山羊拉丁文

    给定一个由空格分割单词的句子 S。每个单词只包含大写或小写字母。

    我们要将句子转换为 “Goat Latin”(一种类似于 猪拉丁文 - Pig Latin 的虚构语言)。

    山羊拉丁文的规则如下:

    如果单词以元音开头(a, e, i, o, u),在单词后添加"ma"。
    例如,单词"apple"变为"applema"。

    如果单词以辅音字母开头(即非元音字母),移除第一个字符并将它放到末尾,之后再添加"ma"。
    例如,单词"goat"变为"oatgma"。

    根据单词在句子中的索引,在单词最后添加与索引相同数量的字母’a’,索引从1开始。
    例如,在第一个单词后添加"a",在第二个单词后添加"aa",以此类推。
    返回将 S 转换为山羊拉丁文后的句子。

    示例 1:
    输入: “I speak Goat Latin”
    输出: “Imaa peaksmaaa oatGmaaaa atinLmaaaaa”
    示例 2:
    输入: “The quick brown fox jumped over the lazy dog”
    输出: “heTmaa uickqmaaa rownbmaaaa oxfmaaaaa umpedjmaaaaaa overmaaaaaaa hetmaaaaaaaa azylmaaaaaaaaa ogdmaaaaaaaaaa”

    方法:
    对于句子中的每个 word,如果是元音字母,就不变;如果是辅音字母,就旋转这个单词(在 Python 中是 word[1:] + word[:1],在 Java 中是 word.substring(1) + word.substring(0, 1)。

    然后,我们加入 “ma” 和期望数量的 “a” 以及一个空格。

    class Solution {
        public String toGoatLatin(String S) {
            Set<Character> vowel = new HashSet();
            for (char c: new char[]{'a', 'e', 'i', 'o', 'u', 'A', 'E', 'I', 'O', 'U'})
                vowel.add(c);
    
            int t = 1;
            StringBuilder sb = new StringBuilder();
            for (String word: S.split(" ")) {
                char first = word.charAt(0);
                if (vowel.contains(first)) {
                    sb.append(word);
                } else {
                    sb.append(word.substring(1));
                    sb.append(word.substring(0, 1));
                }
                sb.append("ma");
                for (int i = 0; i < t; i++)
                    sb.append("a");
                t++;
                sb.append(" ");
            }
    
            sb.deleteCharAt(sb.length() - 1);
            return sb.toString();
        }
    }
    

    859. 亲密字符串

    给定两个由小写字母构成的字符串 A 和 B ,只要我们可以通过交换 A 中的两个字母得到与 B 相等的结果,就返回 true ;否则返回 false 。

    示例 1:
    输入: A = “ab”, B = “ba”
    输出: true
    示例 2:
    输入: A = “ab”, B = “ab”
    输出: false
    示例 3:
    输入: A = “aa”, B = “aa”
    输出: true
    示例 4:
    输入: A = “aaaaaaabc”, B = “aaaaaaacb”
    输出: true
    示例 5:
    输入: A = “”, B = “aa”
    输出: false

    方法:情况列举
    思路:
    如果 A[i] == B[i],我们就说 i 是匹配的,否则称 i 是不匹配的。亲密字符串几乎是完全匹配的,因为一次交换只会影响到两个索引。
    如果交换 A[i] 和 A[j] 可以证明 A 和 B 是亲密字符串,那么就有 A[i] == B[j] 以及 A[j] == B[i]。 这意味着在 A[i], A[j], B[i], B[j] 这四个自由变量中,只存在两种情况:A[i] == A[j] 或 A[i] != A[j]

    算法:
    让我们来看看这些情况。
    在 A[i] == A[j] == B[i] == B[j] 的情况下,字符串 A 与 B 相等。因此,如果 A == B,我们应当检查每个索引 i 以寻找具有相同值的两个匹配。

    在 A[i] == B[j], A[j] == B[i], (A[i] != A[j]) 的情况下,其余索引是相匹配的。所以如果 A 和 B 只有两个不匹配的索引(记作 i 和 j),我们应该检查并确保等式 A[i] == B[j] 和 A[j] == B[i] 成立。

    class Solution {
        public boolean buddyStrings(String A, String B) {
            if (A.length() != B.length()) return false;
            if (A.equals(B)) {
                int[] count = new int[26];
                for (int i = 0; i < A.length(); ++i)
                    count[A.charAt(i) - 'a']++;
    
                for (int c: count)
                    if (c > 1) return true;
                return false;
            } else {
                int first = -1, second = -1;
                for (int i = 0; i < A.length(); ++i) {
                    if (A.charAt(i) != B.charAt(i)) {
                        if (first == -1)
                            first = i;
                        else if (second == -1)
                            second = i;
                        else
                            return false;
                    }
                }
    
                return (second != -1 && A.charAt(first) == B.charAt(second) &&
                        A.charAt(second) == B.charAt(first));
            }
        }
    }
    

    893. 特殊等价字符串组

    你将得到一个字符串数组 A。

    如果经过任意次数的移动,S == T,那么两个字符串 S 和 T 是特殊等价的。

    一次移动包括选择两个索引 i 和 j,且 i % 2 == j % 2,交换 S[j] 和 S [i]。

    现在规定,A 中的特殊等价字符串组是 A 的非空子集 S,这样不在 S 中的任何字符串与 S 中的任何字符串都不是特殊等价的。

    返回 A 中特殊等价字符串组的数量。

    示例 1:
    输入:[“a”,“b”,“c”,“a”,“c”,“c”]
    输出:3
    解释:3 组 [“a”,“a”],[“b”],[“c”,“c”,“c”]
    示例 2:
    输入:[“aa”,“bb”,“ab”,“ba”]
    输出:4
    解释:4 组 [“aa”],[“bb”],[“ab”],[“ba”]
    示例 3:
    输入:[“abc”,“acb”,“bac”,“bca”,“cab”,“cba”]
    输出:3
    解释:3 组 [“abc”,“cba”],[“acb”,“bca”],[“bac”,“cab”]
    示例 4:
    输入:[“abcd”,“cdab”,“adcb”,“cbad”]
    输出:1
    解释:1 组 [“abcd”,“cdab”,“adcb”,“cbad”]

    917. 仅仅反转字母

    给定一个字符串 S,返回 “反转后的” 字符串,其中不是字母的字符都保留在原地,而所有字母的位置发生反转。

    示例 1:
    输入:“ab-cd”
    输出:“dc-ba”
    示例 2:
    输入:“a-bC-dEf-ghIj”
    输出:“j-Ih-gfE-dCba”
    示例 3:
    输入:“Test1ng-Leet=code-Q!”
    输出:“Qedo1ct-eeLg=ntse-T!”

    class Solution {
        public String reverseOnlyLetters(String S) {
            char[] array=S.toCharArray();
            Stack<Character> letters = new Stack();
            for (char c: array)
                if (Character.isLetter(c))
                    letters.push(c);
    
            StringBuilder ans = new StringBuilder();
            for (char c: array) {
                if (Character.isLetter(c))
                    ans.append(letters.pop());
                else
                    ans.append(c);
            }
    
            return ans.toString();
            //StringBuilder叫字符串缓存区对象,使用时可以不断添加字符、字符串等已有内容。
            //需要使用时调用toString()获得对象里的所有字符串
        }
    }
    

    925. 长按键入

    你的朋友正在使用键盘输入他的名字 name。偶尔,在键入字符 c 时,按键可能会被长按,而字符可能被输入 1 次或多次。

    你将会检查键盘输入的字符 typed。如果它对应的可能是你的朋友的名字(其中一些字符可能被长按),那么就返回 True。

    示例 1:
    输入:name = “alex”, typed = “aaleex”
    输出:true
    解释:‘alex’ 中的 ‘a’ 和 ‘e’ 被长按。
    示例 2:
    输入:name = “saeed”, typed = “ssaaedd”
    输出:false
    解释:‘e’ 一定需要被键入两次,但在 typed 的输出中不是这样。
    示例 3:
    输入:name = “leelee”, typed = “lleeelee”
    输出:true
    示例 4:
    输入:name = “laiden”, typed = “laiden”
    输出:true
    解释:长按名字中的字符并不是必要的。

    class Solution {
        public boolean isLongPressedName(String name, String typed) {
            char[] array1=name.toCharArray();
            char[] array2=typed.toCharArray();
            char p=0;
            char q=0;
            while(p<array1.length && q<array2.length){
                if(array1[p]==array2[q]){
                    p++;
                    q++;
                }else{
                    q++;
                }
            }
            return p==array1.length;
        }
    }
    

    929. 独特的电子邮件地址

    每封电子邮件都由一个本地名称和一个域名组成,以 @ 符号分隔。

    例如,在 alice@leetcode.com中, alice 是本地名称,而 leetcode.com 是域名。

    除了小写字母,这些电子邮件还可能包含 ‘.’ 或 ‘+’。

    如果在电子邮件地址的本地名称部分中的某些字符之间添加句点(’.’),则发往那里的邮件将会转发到本地名称中没有点的同一地址。例如,"alice.z@leetcode.com” 和 “alicez@leetcode.com” 会转发到同一电子邮件地址。 (请注意,此规则不适用于域名。)

    如果在本地名称中添加加号(’+’),则会忽略第一个加号后面的所有内容。这允许过滤某些电子邮件,例如 m.y+name@email.com 将转发到 my@email.com。 (同样,此规则不适用于域名。)

    可以同时使用这两个规则。

    给定电子邮件列表 emails,我们会向列表中的每个地址发送一封电子邮件。实际收到邮件的不同地址有多少?

    示例:
    输入:[“test.email+alex@leetcode.com”,“test.e.mail+bob.cathy@leetcode.com”,“testemail+david@lee.tcode.com”]
    输出:2
    解释:实际收到邮件的是 “testemail@leetcode.com” 和 “testemail@lee.tcode.com”。

    提示:
    1 <= emails[i].length <= 100
    1 <= emails.length <= 100
    每封 emails[i] 都包含有且仅有一个 ‘@’ 字符。

    class Solution {
        public int numUniqueEmails(String[] emails) {/*
            对于每个电子邮件地址,我们求出它的规范化表示(即根据 '.' 和 '+' 的规则进行处理后得到的,本地名称中仅包含小写字母的电子邮件地址)。我们对每一个地址依次进行如下的操作:
    
    将电子邮件地址根据 '@' 分成本地名称和域名两部分,其中域名部分包含 '@',且不需要进行额外的处理;
    
    如果本地名称中有 '+',那么移除 '+' 以及它后面出现的所有字符;
    
    移除本地名称中的所有 '.';
    
    处理完成的本地名称和域名进行连接,得到电子邮件地址的规范化表示。
    
    在得到了所有电子邮件地址的规范化表示后,我们将它们放入集合(set)中,就可以获知不同地址的数目。
    */
        Set<String> seen = new HashSet();
            for (String email: emails) {
                int i = email.indexOf('@');
                String local = email.substring(0, i);
                String rest = email.substring(i);
                if (local.contains("+")) {
                    local = local.substring(0, local.indexOf('+'));
                }
                local = local.replace(".", "");
                seen.add(local + rest);
            }
    
            return seen.size(); 
        }
    }
    

    937. 重新排列日志文件

    你有一个日志数组 logs。每条日志都是以空格分隔的字串。

    对于每条日志,其第一个字为字母数字标识符。然后,要么:

    标识符后面的每个字将仅由小写字母组成,或;
    标识符后面的每个字将仅由数字组成。
    我们将这两种日志分别称为字母日志和数字日志。保证每个日志在其标识符后面至少有一个字。

    将日志重新排序,使得所有字母日志都排在数字日志之前。字母日志按内容字母顺序排序,忽略标识符;在内容相同时,按标识符排序。数字日志应该按原来的顺序排列。

    返回日志的最终顺序。
    示例 :
    输入:[“a1 9 2 3 1”,“g1 act car”,“zo4 4 7”,“ab1 off key dog”,“a8 act zoo”]
    输出:[“g1 act car”,“a8 act zoo”,“ab1 off key dog”,“a1 9 2 3 1”,“zo4 4 7”]

    1071. 字符串的最大公因子

    对于字符串 S 和 T,只有在 S = T + … + T(T 与自身连接 1 次或多次)时,我们才认定 “T 能除尽 S”。

    返回最长字符串 X,要求满足 X 能除尽 str1 且 X 能除尽 str2。

    示例 1:
    输入:str1 = “ABCABC”, str2 = “ABC”
    输出:“ABC”
    示例 2:
    输入:str1 = “ABABAB”, str2 = “ABAB”
    输出:“AB”
    示例 3:
    输入:str1 = “LEET”, str2 = “CODE”
    输出:""

    class Solution {
        public String gcdOfStrings(String str1, String str2) {
            // 假设str1是N个x,str2是M个x,那么str1+str2肯定是等于str2+str1的。
            if (!(str1 + str2).equals(str2 + str1)) {
                return "";
            }
            // 辗转相除法求gcd。
            return str1.substring(0, gcd(str1.length(), str2.length()));
        }
    
        private int gcd(int a, int b) {
            return b == 0? a: gcd(b, a % b);
        }
    }
    

    1108. IP 地址无效化

    给你一个有效的 IPv4 地址 address,返回这个 IP 地址的无效化版本。

    所谓无效化 IP 地址,其实就是用 “[.]” 代替了每个 “.”。

    示例 1:
    输入:address = “1.1.1.1”
    输出:“1[.]1[.]1[.]1”
    示例 2:
    输入:address = “255.100.50.0”
    输出:“255[.]100[.]50[.]0”

    class Solution {
        public String defangIPaddr(String address) {
            StringBuilder sb=new StringBuilder();
            for(int i=0;i<address.length();i++){
                if(address.charAt(i)=='.'){
                    sb.append("[.]");
                }else{
                    sb.append(address.charAt(i));
                }
            }
            return sb.toString();
        }
    }
    

    1170. 比较字符串最小字母出现频次

    我们来定义一个函数 f(s),其中传入参数 s 是一个非空字符串;该函数的功能是统计 s 中(按字典序比较)最小字母的出现频次。

    例如,若 s = “dcce”,那么 f(s) = 2,因为最小的字母是 “c”,它出现了 2 次。

    现在,给你两个字符串数组待查表 queries 和词汇表 words,请你返回一个整数数组 answer 作为答案,其中每个 answer[i] 是满足 f(queries[i]) < f(W) 的词的数目,W 是词汇表 words 中的词。

    示例 1:
    输入:queries = [“cbd”], words = [“zaaaz”]
    输出:[1]
    解释:查询 f(“cbd”) = 1,而 f(“zaaaz”) = 3 所以 f(“cbd”) < f(“zaaaz”)。
    示例 2:
    输入:queries = [“bbb”,“cc”], words = [“a”,“aa”,“aaa”,“aaaa”]
    输出:[1,2]
    解释:第一个查询 f(“bbb”) < f(“aaaa”),第二个查询 f(“aaa”) 和 f(“aaaa”) 都 > f(“cc”)。

    提示:
    1 <= queries.length <= 2000
    1 <= words.length <= 2000
    1 <= queries[i].length, words[i].length <= 10
    queries[i][j], words[i][j] 都是小写英文字母

    class Solution {
        public int[] numSmallerByFrequency(String[] queries, String[] words) {
            int[] result = new int[queries.length];
            for (int i = 0; i < queries.length; i++) {
                int countMinQuery = countMinCode(queries[i]);
                for (String word : words) {
                    if (countMinQuery < countMinCode(word)) {
                        result[i] ++;
                    }
                }
            }
            return result;
        }
         /**
         * 统计最小出现频次
         * @param s
         * @return
         */
        public static int countMinCode(String s) {
            char min = s.charAt(0);
            int  count = 0;
            for (int i = 0; i < s.length(); i++) {
                if (s.charAt(i) < min) {
                    min = s.charAt(i);
                    count = 0;
                }
                if (s.charAt(i) == min) {
                    count++;
                }
            }
            return count;
        }
    }
    

    1189. “气球” 的最大数量

    给你一个字符串 text,你需要使用 text 中的字母来拼凑尽可能多的单词 “balloon”(气球)。

    字符串 text 中的每个字母最多只能被使用一次。请你返回最多可以拼凑出多少个单词 “balloon”。

    示例 1:
    输入:text = “nlaebolko”
    输出:1
    示例 2:
    输入:text = “loonbalxballpoon”
    输出:2
    示例 3:
    输入:text = “leetcode”
    输出:0

    class Solution {
        public int maxNumberOfBalloons(String text) {
            int[] array=new int[5];
            for(char c:text.toCharArray()){
                switch(c){
                    case 'b': array[0]++;
                    break;
                    case 'a': array[1]++;
                    break;
                    case 'l': array[2]++;
                    break;
                    case 'o': array[3]++;
                    break;
                    case 'n': array[4]++;
                    break;
                }
            }
            array[2]/=2;
            array[3]/=2;
            Arrays.sort(array);
            return array[0];
        }
    }
    

    1221. 分割平衡字符串

    在一个「平衡字符串」中,‘L’ 和 ‘R’ 字符的数量是相同的。

    给出一个平衡字符串 s,请你将它分割成尽可能多的平衡字符串。

    返回可以通过分割得到的平衡字符串的最大数量。

    示例 1:
    输入:s = “RLRRLLRLRL”
    输出:4
    解释:s 可以分割为 “RL”, “RRLL”, “RL”, “RL”, 每个子字符串中都包含相同数量的 ‘L’ 和 ‘R’。
    示例 2:
    输入:s = “RLLLLRRRLR”
    输出:3
    解释:s 可以分割为 “RL”, “LLLRRR”, “LR”, 每个子字符串中都包含相同数量的 ‘L’ 和 ‘R’。
    示例 3:
    输入:s = “LLLLRRRR”
    输出:1
    解释:s 只能保持原样 “LLLLRRRR”.

    class Solution {
        public int balancedStringSplit(String s) {
            int countR=0;
            int count=0;
            for(int i=0;i<s.length();i++){
                if(s.charAt(i)=='R'){
                    countR++;
                }else{
                    countR--;
                }
                if(countR==0){
                    count++;
                }
            }
            return count;
        }
    }
    

    1309. 解码字母到整数映射

    给你一个字符串 s,它由数字(‘0’ - ‘9’)和 ‘#’ 组成。我们希望按下述规则将 s 映射为一些小写英文字符:

    字符(‘a’ - ‘i’)分别用(‘1’ - ‘9’)表示。
    字符(‘j’ - ‘z’)分别用(‘10#’ - ‘26#’)表示。
    返回映射之后形成的新字符串。

    题目数据保证映射始终唯一。

    示例 1:
    输入:s = “10#11#12”
    输出:“jkab”
    解释:“j” -> “10#” , “k” -> “11#” , “a” -> “1” , “b” -> “2”.
    示例 2:
    输入:s = “1326#”
    输出:“acz”
    示例 3:
    输入:s = “25#”
    输出:“y”
    示例 4:
    输入:s = “12345678910#11#12#13#14#15#16#17#18#19#20#21#22#23#24#25#26#”
    输出:“abcdefghijklmnopqrstuvwxyz”

    1332. 删除回文子序列

    给你一个字符串 s,它仅由字母 ‘a’ 和 ‘b’ 组成。每一次删除操作都可以从 s 中删除一个回文 子序列。

    返回删除给定字符串中所有字符(字符串为空)的最小删除次数。

    「子序列」定义:如果一个字符串可以通过删除原字符串某些字符而不改变原字符顺序得到,那么这个字符串就是原字符串的一个子序列。

    「回文」定义:如果一个字符串向后和向前读是一致的,那么这个字符串就是一个回文。

    示例 1:
    输入:s = “ababa”
    输出:1
    解释:字符串本身就是回文序列,只需要删除一次。
    示例 2:
    输入:s = “abb”
    输出:2
    解释:“abb” -> “bb” -> “”.
    先删除回文子序列 “a”,然后再删除 “bb”。
    示例 3:
    输入:s = “baabb”
    输出:2
    解释:“baabb” -> “b” -> “”.
    先删除回文子序列 “baab”,然后再删除 “b”。
    示例 4:
    输入:s = “”
    输出:0

    class Solution {
        public int removePalindromeSub(String s) {
            if(s.length()==0){
                return 0;
            }
            boolean equals=new StringBuilder(s).reverse().toString().equals(s);
            if(equals){
                return 1;
            }else{
                return 2;
            }
        }
    }
    

    1370. 上升下降字符串

    给你一个字符串 s ,请你根据下面的算法重新构造字符串:

    从 s 中选出 最小 的字符,将它 接在 结果字符串的后面。
    从 s 剩余字符中选出 最小 的字符,且该字符比上一个添加的字符大,将它 接在 结果字符串后面。
    重复步骤 2 ,直到你没法从 s 中选择字符。
    从 s 中选出 最大 的字符,将它 接在 结果字符串的后面。
    从 s 剩余字符中选出 最大 的字符,且该字符比上一个添加的字符小,将它 接在 结果字符串后面。
    重复步骤 5 ,直到你没法从 s 中选择字符。
    重复步骤 1 到 6 ,直到 s 中所有字符都已经被选过。
    在任何一步中,如果最小或者最大字符不止一个 ,你可以选择其中任意一个,并将其添加到结果字符串。

    请你返回将 s 中字符重新排序后的 结果字符串 。

    示例 1:
    输入:s = “aaaabbbbcccc”
    输出:“abccbaabccba”
    解释:第一轮的步骤 1,2,3 后,结果字符串为 result = “abc”
    第一轮的步骤 4,5,6 后,结果字符串为 result = “abccba”
    第一轮结束,现在 s = “aabbcc” ,我们再次回到步骤 1
    第二轮的步骤 1,2,3 后,结果字符串为 result = “abccbaabc”
    第二轮的步骤 4,5,6 后,结果字符串为 result = “abccbaabccba”
    示例 2:
    输入:s = “rat”
    输出:“art”
    解释:单词 “rat” 在上述算法重排序以后变成 “art”
    示例 3:
    输入:s = “leetcode”
    输出:“cdelotee”
    示例 4:
    输入:s = “ggggggg”
    输出:“ggggggg”
    示例 5:
    输入:s = “spo”
    输出:“ops”

    1374. 生成每种字符都是奇数个的字符串

    给你一个整数 n,请你返回一个含 n 个字符的字符串,其中每种字符在该字符串中都恰好出现 奇数次 。

    返回的字符串必须只含小写英文字母。如果存在多个满足题目要求的字符串,则返回其中任意一个即可。

    示例 1:
    输入:n = 4
    输出:“pppz”
    解释:“pppz” 是一个满足题目要求的字符串,因为 ‘p’ 出现 3 次,且 ‘z’ 出现 1 次。当然,还有很多其他字符串也满足题目要求,比如:“ohhh” 和 “love”。
    示例 2:
    输入:n = 2
    输出:“xy”
    解释:“xy” 是一个满足题目要求的字符串,因为 ‘x’ 和 ‘y’ 各出现 1 次。当然,还有很多其他字符串也满足题目要求,比如:“ag” 和 “ur”。
    示例 3:
    输入:n = 7
    输出:“holasss”

    class Solution {
        public String generateTheString(int n) {
            if (n == 0) {
                return "";
            }
            StringBuilder stringBuilder = new StringBuilder(n);
            if (n % 2 == 0) {
                int m = n - 1;
                for (int i = 0; i < m; i++) {
                    stringBuilder.append('a');
                }
                stringBuilder.append('b');
            } else {
                for (int i = 0; i < n; i++) {
                    stringBuilder.append('a');
                }
            }
            return stringBuilder.toString();
        }
    }
    

    1408. 数组中的字符串匹配

    给你一个字符串数组 words ,数组中的每个字符串都可以看作是一个单词。请你按 任意 顺序返回 words 中是其他单词的子字符串的所有单词。

    如果你可以删除 words[j] 最左侧和/或最右侧的若干字符得到 word[i] ,那么字符串 words[i] 就是 words[j] 的一个子字符串。

    示例 1:
    输入:words = [“mass”,“as”,“hero”,“superhero”]
    输出:[“as”,“hero”]
    解释:“as” 是 “mass” 的子字符串,“hero” 是 “superhero” 的子字符串。
    [“hero”,“as”] 也是有效的答案。

    示例 2:
    输入:words = [“leetcode”,“et”,“code”]
    输出:[“et”,“code”]
    解释:“et” 和 “code” 都是 “leetcode” 的子字符串。

    示例 3:
    输入:words = [“blue”,“green”,“bu”]
    输出:[]

    class Solution {
        public List<String> stringMatching(String[] words) {
             //排序,短的在前面 
            Arrays.sort(words, new Comparator<String>() {
                @Override
                public int compare(String o1, String o2) {
                    return o1.length()-o2.length();
                }
            });
            List<String> res = new ArrayList<>();
            for(int i=0; i<words.length; i++)
                for(int j=i+1; j<words.length; j++){
                    if(words[j].length() == words[i].length())
                        continue;
                    if(words[j].contains(words[i])){
                        res.add(words[i]);
                        break;
                    }                
                }
            return res;   
        }
    }
    

    1417. 重新格式化字符串

    给你一个混合了数字和字母的字符串 s,其中的字母均为小写英文字母。

    请你将该字符串重新格式化,使得任意两个相邻字符的类型都不同。也就是说,字母后面应该跟着数字,而数字后面应该跟着字母。

    请你返回 重新格式化后 的字符串;如果无法按要求重新格式化,则返回一个 空字符串 。

    示例 1:
    输入:s = “a0b1c2”
    输出:“0a1b2c”
    解释:“0a1b2c” 中任意两个相邻字符的类型都不同。 “a0b1c2”, “0a1b2c”, “0c2a1b” 也是满足题目要求的答案。

    示例 2:
    输入:s = “leetcode”
    输出:""
    解释:“leetcode” 中只有字母,所以无法满足重新格式化的条件。

    示例 3:
    输入:s = “1229857369”
    输出:""
    解释:“1229857369” 中只有数字,所以无法满足重新格式化的条件。

    示例 4:
    输入:s = “covid2019”
    输出:“c2o0v1i9d”

    示例 5:
    输入:s = “ab123”
    输出:“1a2b3”

    class Solution {
        public String reformat(String s) {
            int num1=0,num2=0;
            char[] chars = s.toCharArray();
            for(char c:chars){
                if(c >= '0'&&c <= '9'){num1++;}
                else{num2++;}
            }//看数字字符比较多还是字母字符比较多
            if( num1-num2<-1 || num1-num2>1){return "";}
            if(num1>num2){
                num1 = 0;num2 = 1;
            }else{
                num1 = 1;num2 = 0;
            }
            for(char c:s.toCharArray()){
                if(c >= '0'&&c <= '9'){chars[num1] = c; num1 += 2;}
                else{chars[num2] = c; num2 += 2;}
            }
            return new String(chars);
        }
    }
    /*1.定义两个变量,对数字字符和字母字符计数,如果数量相差2及以上,直接溜溜球(你呵护不了我,我也呵护不了你,直接music“可惜不是你”)
    2.为了节省空间计数的两个变量拿来复用,哪个数大,哪个从零开始,每次加2,自己走自己的,互不干涉
    反正数字字符和字母字符最终都要放进去
    3.通过num1和num2双指针,将字符放入到字符数组中,返回字符串
    
    链接:https://leetcode-cn.com/problems/reformat-the-string/solution/java-shuang-100zuo-fa-jian-dan-yi-dong-nei-fu-jie-/
    来源:力扣(LeetCode)
    著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。*/
    

    1422. 分割字符串的最大得分

    给你一个由若干 0 和 1 组成的字符串 s ,请你计算并返回将该字符串分割成两个 非空 子字符串(即 左 子字符串和 右 子字符串)所能获得的最大得分。

    「分割字符串的得分」为 左 子字符串中 0 的数量加上 右 子字符串中 1 的数量。

    示例 1:
    输入:s = “011101”
    输出:5
    解释:
    将字符串 s 划分为两个非空子字符串的可行方案有:
    左子字符串 = “0” 且 右子字符串 = “11101”,得分 = 1 + 4 = 5
    左子字符串 = “01” 且 右子字符串 = “1101”,得分 = 1 + 3 = 4
    左子字符串 = “011” 且 右子字符串 = “101”,得分 = 1 + 2 = 3
    左子字符串 = “0111” 且 右子字符串 = “01”,得分 = 1 + 1 = 2
    左子字符串 = “01110” 且 右子字符串 = “1”,得分 = 2 + 1 = 3

    示例 2:
    输入:s = “00111”
    输出:5
    解释:当 左子字符串 = “00” 且 右子字符串 = “111” 时,我们得到最大得分 = 2 + 3 = 5

    示例 3:
    输入:s = “1111”
    输出:3

    class Solution {
        public int maxScore(String s) {
            int res = 0, cnt1 = 0, cnt0 = 0;        //cnt1统计右边1的个数,同理cnt0左边0的个数
            for(int i = 0; i < s.length(); i++){
                cnt1 += s.charAt(i)-'0';            //先统计1的个数
            }                                       //由于左右区域的数至少为1,所以i不能等于len-1
            for(int i = 0; i < s.length()-1; i++){  //点i分为左右两个区域        
                if(s.charAt(i) == '0') cnt0++;      //遇到01就统计,动态更新左右区域01个数
                else cnt1--;
                res = Math.max(res, cnt0+cnt1);
            }
            return res;
        }
    }
    

    1436. 旅行终点站

    给你一份旅游线路图,该线路图中的旅行线路用数组 paths 表示,其中 paths[i] = [cityAi, cityBi] 表示该线路将会从 cityAi 直接前往 cityBi 。请你找出这次旅行的终点站,即没有任何可以通往其他城市的线路的城市。

    题目数据保证线路图会形成一条不存在循环的线路,因此只会有一个旅行终点站。

    示例 1:
    输入:paths = [[“London”,“New York”],[“New York”,“Lima”],[“Lima”,“Sao Paulo”]]
    输出:“Sao Paulo”
    解释:从 “London” 出发,最后抵达终点站 “Sao Paulo” 。本次旅行的路线是 “London” -> “New York” -> “Lima” -> “Sao Paulo” 。

    示例 2:
    输入:paths = [[“B”,“C”],[“D”,“B”],[“C”,“A”]]
    输出:“A”
    解释:所有可能的线路是:
    “D” -> “B” -> “C” -> “A”.
    “B” -> “C” -> “A”.
    “C” -> “A”.
    “A”.
    显然,旅行终点站是 “A” 。

    示例 3:
    输入:paths = [[“A”,“Z”]]
    输出:“Z”

    class Solution {
        public String destCity(List<List<String>> paths) {
            Map<String,Boolean> map = new HashMap<>();
    
            for (List<String> path : paths) {
                if (map.containsKey(path.get(0))) map.remove(path.get(0));
                else map.put(path.get(0),false);
                if (map.containsKey(path.get(1))) map.remove(path.get(1));
                else map.put(path.get(1),true);
            }
    
            for (Map.Entry<String, Boolean> entry : map.entrySet()) {
                if (entry.getValue()) return entry.getKey();
            }
            return null;
        }
    }
    //哈希表key代表只出现一次的城市,value代表城市出现的位置。
    
    展开全文
  • 针对字符串的题目

    解题思路

    1. 先将句子中所有的字符串取出放入字符串数组中。
    2. 再对数组中的字符串进行操作后重新连接

    遍历句子取字符串的思路:将遇到的字符放进临时字符串中,遇得空格或者标点符号,就将临时字符串放进字符串数组中,并且将临时字符串清空。

    模板代码

    一、字符串前后有空格

    s +=" ";//在字符串最后位置加上空格,这样最后一个字符串就不会遗漏
    string temp = "";//创建临时字符串
    vector<string> res;//存放字符串数组
    int main()
    {
    	for (char ch : s)//遍历字符串
    	{
    		if (ch == ' ')//遇见空格或者这里也可以根据题目要求,将空格改标点符号
    		{
    			//遇见空格,代表字符串s中的一个单词已经全部存储在临时字符串中
    			if (!temp.empty())//临时字符串非空
    			{
    				//将临时字符串存储在字符串数组中
    				res.push_back(temp);
    				temp.clear();//将临时字符串清空,方便存入字符串s中下一个单词
    			}			
    		}
    		else//临时字符串是空,代表已经遍历到字符串最后一个位置了。
    		{
    			temp += ch;
    		}
    	}
    }
    

    二、字符串前后没有空格

    s += " ";
    	string temp = "";
    	vector<string> res;
    	for (char ch : s)
    	{
    		if (ch == ' ')
    		{
    			res.push_back(temp);
    			temp.clear();
    		}
    		else
    		{
    			temp += ch;
    		}
    	}
    

    有关字符串的题目

    最后一个单词的长度
    反转字符串中的单词
    反转单词顺序
    截断句子
    字符串中不同整数的数目
    最常见的单词
    山羊拉丁文
    检查单词是否为句子中其他单词的前缀
    重新排列单词间的空格
    将句子排序

    解题方法:

    最后一个单词的长度
    题目描述:给你一个字符串 s,由若干单词组成,单词前后用一些空格字符隔开。返回字符串中 最后一个 单词的长度。
    从题目描述中我们可以看出,该题目可以直接套用模板1,返回字符串数组尾的元素长度。

    class Solution {
    public:
        int lengthOfLastWord(string s) {
            s+=' ';
            string temp;
            vector<string> res;
            for(char ch:s)
            {
                if(ch==' ')
                {
                    if(!temp.empty())
                    {
                        res.push_back(temp);
                        temp.clear();
                    }
                   
                }
                else
                {
                    temp+=ch;
                }
            }
            if(res.empty())return 0;
            return res.back().size();
    
        }
    };
    

    反转字符串中的单词
    题目描述:给定一个字符串 s ,你需要反转字符串中每个单词的字符顺序,同时仍保留空格和单词的初始顺序。
    我们根据题目要求可以判断出,我们只需要将字符串中所有单词的字母顺序颠倒即可。

    class Solution {
    public:
        string reverseWords(string s) {
            s+=' ';
            string temp="";
            vector<string>res;
            for(char ch:s)
            {
                if(ch==' ')
                {
                    res.push_back(temp);
                    temp.clear();
                }
                else
                {
                    temp+=ch;
                }
            }
            s.clear();//将原字符串清空
            for(auto&str:res)
            {
                reverse(str.begin(),str.end());
                s+=str+' ';//将单词用' '空格隔开
            }
            //执行在这里,意味着将所有单词全部反转,但是最后一个单词多了一个空格
            s.pop_back();//将最后一个空格删除
            return s;
        }
    

    反转单词顺序
    题目描述:输入一个英文句子,翻转句子中单词的顺序,但单词内字符的顺序不变。为简单起见,标点符号和普通字母一样处理。例如输入字符串"I am a student. “,则输出"student. a am I”。

    class Solution {
    public:
        string reverseWords(string s) {
            if(s.empty())return "";
            s+=" ";
            string temp="";
            vector<string>res;
            for(char ch:s)
            {
                if(ch==' ')
                {
                    if(!temp.empty())
                    {
                        res.push_back(temp);
                        temp.clear();
                    }
                }
                else
                {
                    temp+=ch;
                }
            }
            s.clear();
            reverse(res.begin(),res.end());
            for(auto&str:res)
            {
                s+=str+' ';
            }
            s.pop_back();
            return s;
    
        }
    };
    

    截断句子
    题目描述:句子 是一个单词列表,列表中的单词之间用单个空格隔开,且不存在前导或尾随空格。每个单词仅由大小写英文字母组成(不含标点符号)给你一个句子 s​​​​​​ 和一个整数 k​​​​​​ ,请你将 s​​ 截断 ​,​​​使截断后的句子仅含 前 k​​​​​​ 个单词。返回 截断 s​​​​​​ 后得到的句子。
    输入:s = “Hello how are you Contestant”, k = 4
    输出:“Hello how are you”
    解释:
    s 中的单词为 [“Hello”, “how” “are”, “you”, “Contestant”]
    前 4 个单词为 [“Hello”, “how”, “are”, “you”]
    因此,应当返回 “Hello how are you”
    示例中没有前置或者后置空格,所以用模板二。

    class Solution {
    public:
        string truncateSentence(string s, int k) {
            s+=" ";
            string temp="";
            vector<string>res;
            for(char ch:s)
            {
                if(ch==' ')
                {
                    res.push_back(temp);
                    temp.clear();
                }
                else
                {
                    temp+=ch;
                }
            }
            s.clear();
            for(int i=0;i<k;++i)
            {
                s+=res[i]+' ';
            }
            s.pop_back();
            return s;
    
        }
    };
    

    字符串中不同整数的数目
    题目描述:给你一个字符串 word ,该字符串由数字和小写英文字母组成。
    请你用空格替换每个不是数字的字符。例如,“a123bc34d8ef34” 将会变成 " 123 34 8 34" 。注意,剩下的这些整数为(相邻彼此至少有一个空格隔开):“123”、“34”、“8” 和 “34” 。
    返回对 word 完成替换后形成的 不同 整数的数目。
    只有当两个整数的 不含前导零 的十进制表示不同, 才认为这两个整数也不同。
    示例 1:

    输入:word = “a123bc34d8ef34”
    输出:3
    解释:不同的整数有 “123”、“34” 和 “8” 。注意,“34” 只计数一次。

    输入:word = “a1b01c001”
    输出:1
    解释:“1”、“01” 和 “001” 视为同一个整数的十进制表示,因为在比较十进制值时会忽略前导零的存在。

    class Solution {
    public:
        int numDifferentIntegers(string word) {
            set<string>s;//用set可进行去重
            string temp="";
            word+='a';//在字符串末尾加上一个字母,保证在遍历的时候如果有整数就不会遗漏
            for(char ch:word)
            {
                if(isalpha(ch))//如果是字母
                {
                    if(!temp.empty())//临时字符串为空
                    {
                        s.insert(temp);
                        temp.clear();
                    }
                }
                else
                {
                    if(temp=="0")temp.clear();//整数前面有0:如012就是12,将0清除
                    temp+=ch;
                }
            }
            return s.size();
        }
    };
    

    最常见的单词
    **题目描述:**给定一个段落 (paragraph) 和一个禁用单词列表 (banned)。返回出现次数最多,同时不在禁用列表中的单词。
    题目保证至少有一个词不在禁用列表中,而且答案唯一。
    禁用列表中的单词用小写字母表示,不含标点符号。段落中的单词不区分大小写。答案都是小写字母。
    示例:
    输入:
    paragraph = “Bob hit a ball, the hit BALL flew far after it was hit.”
    banned = [“hit”]
    输出: “ball”
    解释:
    “hit” 出现了3次,但它是一个禁用的单词。
    “ball” 出现了2次 (同时没有其他单词出现2次),所以它是段落里出现次数最多的,且不在禁用列表中的单词。
    注意,所有这些单词在段落里不区分大小写,标点符号需要忽略(即使是紧挨着单词也忽略, 比如 “ball,”),
    "hit"不是最终的答案,虽然它出现次数更多,但它在禁用单词列表中。

    class Solution {
    public:
        string mostCommonWord(string paragraph, vector<string>& banned) {
            paragraph+=" ";
            string temp="";
            map<string,int>m;//哈希表记录单词出现频次
            set<string>ban(banned.begin(),banned.end());//把禁用列表放到集合中方便查找
            for(char ch:paragraph)
            {
                if(!isalpha(ch))//将字符串中所有的单词分割出来
                {
                    if(!temp.empty())
                    {
                        m[temp]++;
                        temp.clear();
                    }
                }
                else
                {
                    temp+=tolower(ch);//将所有字母转换为小写字母
                }
            }
            vector<string>words;
            for(auto p:m)
            {
                words.push_back(p.first);
            }
             sort(words.begin(), words.end(), [&](string &s, string &p) { return m[s] > m[p]; }); 
    
            if(banned.empty())//如果没有禁用单词,直接返回排序后列表的首元素
            {
                return words[0];
            }
            for(auto w:words)//遍历列表,除了禁用单词外,第一个单词就是常见单词
            {
                if(ban.find(w)==ban.end())
                {
                    return w;
                }
            }
            return "";
    
        }
    };
    

    山羊拉丁文
    给定一个由空格分割单词的句子 S。每个单词只包含大写或小写字母。
    我们要将句子转换为 “Goat Latin”(一种类似于 猪拉丁文 - Pig Latin 的虚构语言)。
    山羊拉丁文的规则如下:
    如果单词以元音开头(a, e, i, o, u),在单词后添加"ma"。
    例如,单词"apple"变为"applema"。
    如果单词以辅音字母开头(即非元音字母),移除第一个字符并将它放到末尾,之后再添加"ma"。
    例如,单词"goat"变为"oatgma"。
    根据单词在句子中的索引,在单词最后添加与索引相同数量的字母’a’,索引从1开始。
    例如,在第一个单词后添加"a",在第二个单词后添加"aa",以此类推。
    返回将 S 转换为山羊拉丁文后的句子。
    示例 1:
    输入: “I speak Goat Latin”
    输出: “Imaa peaksmaaa oatGmaaaa atinLmaaaaa”

    class Solution {
    public:
        string toGoatLatin(string sentence) {
            sentence+=" ";
            vector<string>res; 
            string temp="";
            string vowels="aeiouAEIOU";
            for(char ch:sentence)
            {
                if(ch==' ')
                {
                    res.push_back(temp);
                    temp.clear();
                }
                else
                {
                    temp+=ch;
                }
            }
            sentence.clear();
            for(int i=0;i<res.size();++i)
            {
                //字符串中单词的首元素为元音字母
                if(vowels.find(res[i][0])!=-1)
                {
                    sentence+=res[i];
                }
                else
                {
                    //如果不是,那么就将单词的首元素字母增加在原单词中,然后将首字母删除
                    string t=res[i]+res[i][0];
                    t.erase(t.begin());
                    sentence+=t;
                }
                sentence+="ma";
                sentence.insert(sentence.size(),i+1,'a');
                sentence+=' ';
            }
            sentence.pop_back();
            return sentence;
    
        }
    };
    

    检查单词是否为句子中其他单词的前缀
    给你一个字符串 sentence 作为句子并指定检索词为 searchWord ,其中句子由若干用 单个空格 分隔的单词组成。请你检查检索词 searchWord 是否为句子 sentence 中任意单词的前缀。
    如果 searchWord 是某一个单词的前缀,则返回句子 sentence 中该单词所对应的下标(下标从 1 开始)。如果 searchWord 是多个单词的前缀,则返回匹配的第一个单词的下标(最小下标)。如果 searchWord 不是任何单词的前缀,则返回 -1 。
    字符串 s 的 前缀 是 s 的任何前导连续子字符串。
    示例 1:
    输入:sentence = “i love eating burger”, searchWord = “burg”
    输出:4
    解释:“burg” 是 “burger” 的前缀,而 “burger” 是句子中第 4 个单词。

    class Solution {
    public:
        int isPrefixOfWord(string sentence, string searchWord) {
            sentence+=" ";
            string temp="";
            vector<string>res;
            for(char ch:sentence)
            {
                if(ch==' ')
                {
                    res.push_back(temp);
                    temp.clear();
                }
                else
                {
                    temp+=ch;
                }
            }
            for(int i=0;i<res.size();++i)
            {
                if(res[i].find(searchWord)==0) return i+1;
            }
            return -1;
    
        }
    };
    

    重新排列单词间的空格
    给你一个字符串 text ,该字符串由若干被空格包围的单词组成。每个单词由一个或者多个小写英文字母组成,并且两个单词之间至少存在一个空格。题目测试用例保证 text 至少包含一个单词 。
    请你重新排列空格,使每对相邻单词之间的空格数目都 相等 ,并尽可能 最大化 该数目。如果不能重新平均分配所有空格,请 将多余的空格放置在字符串末尾 ,这也意味着返回的字符串应当与原 text 字符串的长度相等。
    返回 重新排列空格后的字符串 。
    用模板一

    class Solution {
    public:
        string reorderSpaces(string text) {
            text+=" ";
            string temp="";
            vector<string>res;
            int cnt=-1;//因为代码最开始给字符串增加了一个空格
            for(char ch:text)
            {
                if(ch==' ')
                {
                    cnt++;
                    if(!temp.empty())
                    {
                        res.push_back(temp);
                        temp.clear();
                    }
                }
                else
                {
                    temp+=ch;
                }
            }
            text.clear();
            int n=res.size();
            if(n==1)
            {
                text+=res[0];
                text.insert(text.size(),cnt,' ');
                return text;
            }
            int bank=cnt/(n-1);
            int remain=cnt-bank*(n-1);
            for(int i=0;i<n-1;++i)
            {
                text+=res[i];
                text.insert(text.size(),bank,' ');
    
            }
            text+=res.back();
            if(remain>0)text.insert(text.size(),remain,' ');
            return text;
    
        }
    };
    

    将句子排序

    class Solution {
    public:
        string sortSentence(string s) {
            s += " ";
        string temp = "";
        vector<string> res;
        for (char ch : s)
        {
            if (ch == ' ')
            {
                res.push_back(temp);
                temp.clear();
            }
            else
                temp += ch;
        }
        s.clear();
        sort(res.begin(),res.end(),[&](string&a,string&b){return a.back()<b.back();});
        for(auto&str:res)
        {
            str.pop_back();//将单词中的数字清除
            s+=str+' ';
        }
        s.pop_back();
        return s;
    
    
    
        }
    };
    
    展开全文
  • windows系统的很多组策略配置,都可以通过修改注册表完成。 为了自动化快速做组策略配置,需要通过命令行方式修改注册表来达到这一目的。... 其中通过命令行方式修改多字符串值类型的注册表有点难,本文以此为例。
  • 前台js数组json字符串,后台json字符串转为json数组,最后转换成集合的具体实现
  • String类: String类即字符串类型,并不...声明字符串:声明一个字符串就是创建一个字符串对象。 //可以声明单个也可以同时声明多个字符串对象,声明不赋值,这个对象就是空, 也就是 String a= null; String a
  • 拖了这么长时间,终于把Xdelta3的字符串匹配解析做好了,这个部分是我们整个系列解析中最重要的部分,想要把它解释清楚说明白还真不是一件容易的事,着实费了我不少功夫。 闲话少叙,直入主题。 介绍 Xdelta3中使用...
  • C语言中的字符串处理函数

    千次阅读 2019-04-02 17:15:38
    1、strcpy():复制字符串 2、strncpy():复制n个字符串 3、strcat():连接字符串 4、strncat():连接n个字符串 5、strcmp():字符串比大小 6、strlen():字符串长度 7、strset():字符串重置 9、memset():...
  • Qt TCP协议 传输简单字符串实例

    千次阅读 2016-08-22 10:06:49
    Qt TCP协议 传输简单字符串实例是本文要介绍的内容。TCP即Transmission Control Protocol,传输控制协议。与UDP不同,它是面向连接和数据流的可靠传输协议。也就是说,它能使一台计算机上的数据无差错的发往网络上的...
  • 字符串 FName FName 通过一个轻型系统使用字符串。在此系统中,特定字符串即使会被重复使用,在数据表中也只存储一次。FNames 不区分大小写。它们为不可变,无法被操作。FNames 的存储系统和静态特性决定了通过键...
  • 关键点在这里JSON.stringify(mock,null,4).toString()有格式化的作用,v-model以后取到的是字符串,所有得转成数组结构。 &amp;amp;lt;div id=&amp;quot;app&amp;quot;&amp;amp;gt; &amp;amp...
  • 字符串与文件I/O

    2017-03-03 14:41:57
    LabVIEW在功能模板上的字符串子模板中提供了一整套的字符串处理函数,能够完成各种字符串处理功能。常用的字符串对象包括字符串输入控件和字符串显示控件,它们位于控件→新式→字符串与路径→字符串输入控件,字符...
  • SQL Server 2008默认是不允许远程连接的,sa帐户默认禁用的,如果想要在本地用SSMS连接远程服务器上的SQL Server 2008,需要做两个部分的配置:使用用sa账户登录SQL Server Management Studio(简写SSMS) 如果...
  • Problem E: 编写函数:递归的字符串回文 (Append Code) Time Limit: 1 SecMemory Limit: 16 MB Submit: 838Solved: 235 [Submit][Status][Web Board] Description 输入一个字符串s,判断是否为回文。回文是指...
  • TIA Portal博途常见的15大问题汇总

    千次阅读 2021-02-05 07:36:18
    1.我的系统能不能装... 答:授权没有完成 15.TIA Portal 提示出错需要关闭 答:可能造成这个问题的原因太多,而出现这问题的大部分原因是操作系统的问题,没有什么针对性的解决方案,此错误最好的办法就是重装系统。
  • Problem E: 编写函数:递归求逆序 (Append Code) Time Limit: 1 Sec Memory Limit: 16 MB Submit: 5583 Solved: 3247 ...将输入的一个字符串s逆序输出。 编写函数recursive()完成程序: 原型:int recursive(); ...
  • C# System.Speech语音播报朗读字符串

    千次阅读 2019-03-31 10:54:44
    播音员在不同的电脑上可能会预装不同的播音员,如果播音员字符串错误,会出现如下异常: System.ArgumentException:“不能设置语音。未安装匹配的语音,或语音被禁用。” 这时候就可以检索PC上安装的语音包来...
  • 基于CubeMX HAL库的STM32串口发送、接收配置

    千次阅读 多人点赞 2019-10-20 08:18:51
    1.1.3、生成代码,打开工程,在主函数的循环前面添加测试语句,输出字符串: 1.1.4、编译下载,打开串口调试助手,复位: 1.2、使用自定义printf函数 1.2.1、编写函数用于发送字符串 1.2.2、在主函数中...
  • 本章将学到许多操作数据的方法,它们大多与下面这两种内置的Python数据类型有关。 字符串 Unicode字符组成的序列,用于存储文本数据。...Python3中的字符串是Unicode字符串而不是字节数组(一个字符一...
  • 数据库连接字符串

    千次阅读 2010-03-15 09:06:00
    注意 :在字符串中的引号"需要根据你使用的语言转义一些.举例如下 c#, c++ /" VB6, VBScript  "" xml (web.config etc) " 或者用单引号’。 "HDR=Yes;" 这个参数说明第一行是列名,而不是数据....
  • 在我们的HelloWord例子当中,我们并没有传入任何参数给我们的java层print方法,native方法也并没有返回任何数据而是void,本地方法只是简单的打印一个字符串,然后就返回了。实际开发中我们都需要传入参数,返回参数...
  • 第四章 字符串和格式化输入/输出

    千次阅读 2010-10-12 19:09:00
    1、字符串简介C语言没有字符串类型,而是把它存储在char数组中,字符串以空字符'/0'结束,非打印字符,其ASCII码值为0.
  • #限制QTextEdit的字符数的最大输入量,包括中文字符数或自由字符的最大输入量(纯中文输入、自由字符输入) ##UI界面效果图 ##textEdit.h #ifndef TEXTEDIT_H #define TEXTEDIT_H #include &amp;amp;amp;lt...
  • 索引数组(索引值为数字,以0开始)和关联数组(以字符串作为索引值) 数组的赋值方式有哪两种? 数组的声明方式主要有两种。 1.通过array()函数声明数组; 可以通过key=>value的方式分别定义索引和值,也可以...
  • 背景:以启用 / 禁用网卡举例。 系统平台:win2003。 情况描述:机器上装有两块网卡,8136和8139,网卡A使用静态IP,连接内部办公网,网卡B使用DHCP,连接互联网。切换两个网络时,需要先禁用一个网卡,启用另一个...
  • shell截取字符串

    千次阅读 2012-03-20 13:39:09
    以上命令定义了一个名为 "myvar" 的环境变量,并包含字符串 "This is my environment variable!"。以上有几点注意事项:第一,在等号 "=" 的两边没有空格,任何空格将导致错误。第二个件要注意的事是:虽然在定义...
  • 导致这一情况发生多半是由于USB设备被禁用了,那么该如何解除呢?下面学习啦小编就以笔记本电脑为例子,跟大家分享具体的处理方法吧,希望对大家有所帮助~笔记本电脑U盘等USB设备被禁用的处理方法1.使用组合快捷键win...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 96,209
精华内容 38,483
关键字:

如何禁用完成字符串