力扣字符串练习题(N字形变换、字符串转换整数(atoi))

111 阅读3分钟

N字形变换

来源:力扣(LeetCode) 链接:leetcode.cn/problems/zi…

将一个给定字符串 s 根据给定的行数 numRows ,以从上往下、从左到右进行 Z 字形排列。

比如输入字符串为 "PAYPALISHIRING" 行数为 3 时,排列如下:

P   A   H   N

A P L S I I G

Y   I   R

之后,你的输出需要从左往右逐行读取,产生出一个新的字符串,比如:"PAHNAPLSIIGYIR"。

请你实现这个将字符串进行指定行数变换的函数:

string convert(string s, int numRows);

示例 1:

输入:s = "PAYPALISHIRING", numRows = 3

输出:"PAHNAPLSIIGYIR"

示例 2:

输入:s = "PAYPALISHIRING", numRows = 4

输出:"PINALSIGYAHRPI"

解释:

P     I    N

A   L S  I G

Y A   H R

P     I

示例 3:

输入:s = "A", numRows = 1

输出:"A"

提示:

  • 1 <= s.length <= 1000 = s 由英文字母(小写和大写)、',' 和 '.' 组成 = 1 <= numRows <= 1000

代码

class Solution {
    public String convert(String s, int numRows) {
        if (numRows == 1 || numRows >= s.length()) {
            return s;
        }
        
        StringBuilder[] rows = new StringBuilder[numRows];
        for (int i = 0; i < numRows; i++) {
            rows[i] = new StringBuilder();
        }
        
        int currRow = 0;
        boolean goingDown = false;
        
        for (char c : s.toCharArray()) {
            rows[currRow].append(c);
            
            if (currRow == 0 || currRow == numRows - 1) {
                goingDown = !goingDown;
            }
            
            currRow += goingDown ? 1 : -1;
        }
        
        StringBuilder result = new StringBuilder();
        for (StringBuilder row : rows) {
            result.append(row);
        }
        
        return result.toString();
    }
}

思路分析

  1. 首先处理特殊情况,如果行数为1或大于等于字符串长度,则直接返回原字符串。
  2. 创建一个StringBuilder数组rows,数组的长度为行数,每个元素都是一个StringBuilder对象,用于存储每行的字符。
  3. 定义当前行号currRow和一个标志变量goingDown,用于表示当前字符是向下移动还是向上移动。
  4. 遍历字符串的每个字符,将字符添加到对应的行中的StringBuilder对象中。
  5. 根据当前行号和行数进行判断,如果当前行号为第一行或最后一行,则改变goingDown的值。
  6. 根据goingDown的值更新当前行号,向下移动时行号加1,向上移动时行号减1。
  7. 遍历完成后,将每行的StringBuilder对象按顺序合并为一个新的StringBuilder对象result
  8. result转换为字符串并返回。

字符串转换整数(atoi)

来源:力扣(LeetCode) 链接:leetcode.cn/problems/st…

请你来实现一个 myAtoi(string s) 函数,使其能将字符串转换成一个 32 位有符号整数(类似 C/C++ 中的 atoi 函数)。

函数 myAtoi(string s) 的算法如下:

  1. 读入字符串并丢弃无用的前导空格
  2. 检查下一个字符(假设还未到字符末尾)为正还是负号,读取该字符(如果有)。 确定最终结果是负数还是正数。 如果两者都不存在,则假定结果为正。
  3. 读入下一个字符,直到到达下一个非数字字符或到达输入的结尾。字符串的其余部分将被忽略。
  4. 将前面步骤读入的这些数字转换为整数(即,"123" -> 123, "0032" -> 32)。如果没有读入数字,则整数为 0 。必要时更改符号(从步骤 2 开始)。
  5. 如果整数数超过 32 位有符号整数范围 [−231, 231 − 1] ,需要截断这个整数,使其保持在这个范围内。具体来说,小于 −231 的整数应该被固定为 −231 ,大于 231 − 1 的整数应该被固定为 231 − 1 。
  6. 返回整数作为最终结果。

注意:

  • 本题中的空白字符只包括空格字符 ' ' 。
  • 除前导空格或数字后的其余字符串外,请勿忽略 任何其他字符。

示例 1:

输入:s = "42"

输出:42

解释:加粗的字符串为已经读入的字符,插入符号是当前读取的字符。

第 1 步:"42"(当前没有读入字符,因为没有前导空格)
         ^
第 2 步:"42"(当前没有读入字符,因为这里不存在 '-' 或者 '+')
         ^
第 3 步:"42"(读入 "42")
           ^
解析得到整数 42 。

由于 "42" 在范围 [-231, 231 - 1] 内,最终结果为 42

示例 2:

输入:s = "   -42"

输出:-42

解释:

第 1 步:"   -42"(读入前导空格,但忽视掉)
            ^
第 2 步:"   -42"(读入 '-' 字符,所以结果应该是负数)
             ^
第 3 步:"   -42"(读入 "42")
               ^
解析得到整数 -42 。

由于 "-42" 在范围 [-231, 231 - 1] 内,最终结果为 -42

示例 3:

输入:s = "4193 with words"

输出:4193

解释:

第 1 步:"4193 with words"(当前没有读入字符,因为没有前导空格)
         ^
第 2 步:"4193 with words"(当前没有读入字符,因为这里不存在 '-' 或者 '+')
         ^
第 3 步:"4193 with words"(读入 "4193";由于下一个字符不是一个数字,所以读入停止)
             ^
解析得到整数 4193 。

由于 "4193" 在范围 [-231, 231 - 1] 内,最终结果为 4193

提示:

  • 0 <= s.length <= 200
  • s 由英文字母(大写和小写)、数字(0-9)、' '、'+'、'-' 和 '.' 组成

代码

class Solution {
    public int myAtoi(String s) {
        int index = 0;
        int sign = 1;
        int result = 0;
        
        // 移除前导空格
        while (index < s.length() && s.charAt(index) == ' ') {
            index++;
        }
        
        // 处理正负号
        if (index < s.length() && (s.charAt(index) == '+' || s.charAt(index) == '-')) {
            sign = s.charAt(index) == '+' ? 1 : -1;
            index++;
        }
        
        // 将数字字符转换为整数
        while (index < s.length()) {
            char c = s.charAt(index);
            if (c < '0' || c > '9') {
                break;
            }
            
            // 处理溢出情况
            if (result > Integer.MAX_VALUE / 10 || (result == Integer.MAX_VALUE / 10 && (c - '0') > Integer.MAX_VALUE % 10)) {
                return sign == 1 ? Integer.MAX_VALUE : Integer.MIN_VALUE;
            }
            
            result = result * 10 + (c - '0');
            index++;
        }
        
        return sign * result;
    }
}

思路分析

  1. 定义一个指针index,用于遍历字符串s的每个字符。
  2. 移除字符串开头的空格,即将指针index向后移动到第一个非空格字符的位置。
  3. 处理正负号,如果指针index指向正号或负号,则根据正负号确定变量sign的值,并将指针index向后移动。
  4. 遍历剩余的字符,将数字字符转换为整数。如果遇到非数字字符,则跳出循环。
  5. 在转换过程中,判断整数是否溢出。如果溢出,根据正负号返回最大或最小整数值。
  6. 将转换后的整数乘以正负号并返回。