Go-Python-Java-C-LeetCode高分解法-第二周合集

前言

本题解Go语言部分基于 LeetCode-Go
其他部分基于本人实践学习
个人题解GitHub连接:LeetCode-Go-Python-Java-C
Go-Python-Java-C-LeetCode高分解法-第一周合集
本文部分内容来自网上搜集与个人实践。如果任何信息存在错误,欢迎读者批评指正。本文仅用于学习交流,不用作任何商业用途。

8. String to Integer (atoi)

题目

Implement the myAtoi(string s) function, which converts a string to a 32-bit signed integer (similar to C/C++'s atoi function).

The algorithm for myAtoi(string s) is as follows:

  1. Read in and ignore any leading whitespace.
  2. Check if the next character (if not already at the end of the string) is '-' or '+'. Read this character in if it is either. This determines if the final result is negative or positive respectively. Assume the result is positive if neither is present.
  3. Read in next the characters until the next non-digit charcter or the end of the input is reached. The rest of the string is ignored.
  4. Convert these digits into an integer (i.e. "123" -> 123, "0032" -> 32). If no digits were read, then the integer is 0. Change the sign as necessary (from step 2).
  5. If the integer is out of the 32-bit signed integer range [-231, 231 - 1], then clamp the integer so that it remains in the range. Specifically, integers less than 231 should be clamped to 231, and integers greater than 231 - 1 should be clamped to 231 - 1.
  6. Return the integer as the final result.

Note:

  • Only the space character ' ' is considered a whitespace character.
  • Do not ignore any characters other than the leading whitespace or the rest of the string after the digits.

Example 1:

Input: s = "42"
Output: 42
Explanation: The underlined characters are what is read in, the caret is the current reader position.
Step 1: "42" (no characters read because there is no leading whitespace)
         ^
Step 2: "42" (no characters read because there is neither a '-' nor '+')
         ^
Step 3: "42" ("42" is read in)
           ^
The parsed integer is 42.
Since 42 is in the range [-231, 231 - 1], the final result is 42.

Example 2:

Input: s = "   -42"
Output: -42
Explanation:
Step 1: "   -42" (leading whitespace is read and ignored)
            ^
Step 2: "   -42" ('-' is read, so the result should be negative)
             ^
Step 3: "   -42" ("42" is read in)
               ^
The parsed integer is -42.
Since -42 is in the range [-231, 231 - 1], the final result is -42.

Example 3:

Input: s = "4193 with words"
Output: 4193
Explanation:
Step 1: "4193 with words" (no characters read because there is no leading whitespace)
         ^
Step 2: "4193 with words" (no characters read because there is neither a '-' nor '+')
         ^
Step 3: "4193 with words" ("4193" is read in; reading stops because the next character is a non-digit)
             ^
The parsed integer is 4193.
Since 4193 is in the range [-231, 231 - 1], the final result is 4193.

Example 4:

Input: s = "words and 987"
Output: 0
Explanation:
Step 1: "words and 987" (no characters read because there is no leading whitespace)
         ^
Step 2: "words and 987" (no characters read because there is neither a '-' nor '+')
         ^
Step 3: "words and 987" (reading stops immediately because there is a non-digit 'w')
         ^
The parsed integer is 0 because no digits were read.
Since 0 is in the range [-231, 231 - 1], the final result is 0.

Example 5:

Input: s = "-91283472332"
Output: -2147483648
Explanation:
Step 1: "-91283472332" (no characters read because there is no leading whitespace)
         ^
Step 2: "-91283472332" ('-' is read, so the result should be negative)
          ^
Step 3: "-91283472332" ("91283472332" is read in)
                     ^
The parsed integer is -91283472332.
Since -91283472332 is less than the lower bound of the range [-231, 231 - 1], the final result is clamped to -231 = -2147483648.

Constraints:

  • 0 <= s.length <= 200
  • s consists of English letters (lower-case and upper-case), digits (0-9), ' ', '+'

题目大意

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

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

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

注意:

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

解题思路

  • 这题是简单题。题目要求实现类似 C++atoi 函数的功能。这个函数功能是将字符串类型的数字转成 int 类型数字。先去除字符串中的前导空格,并判断记录数字的符号。数字需要去掉前导 0 。最后将数字转换成数字类型,判断是否超过 int 类型的上限 [-2^31, 2^31 - 1],如果超过上限,需要输出边界,即 -2^31,或者 2^31 - 1

每种语言版本的解题思路:

Go语言

  1. strings.TrimSpace()删除前导空格
  2. strings.Split()分割字符串成数字字符数组
  3. for range迭代字符数组
  4. strconv.Atoi()逐个字符转整数
  5. 将整数append到数组中
  6. 切片运算取前100个数的平方和

Python

  1. isspace()判断空格,isdigit()判断数字字符
  2. int()强转字符为整数,try-except捕获溢出
  3. append()将数字添加到数组
  4. itertools.islice()取前100个元素
  5. sum()求和,pow()求平方

Java

  1. replaceAll()替换空格,split()分割字符串
  2. Character.isDigit()判断数字字符
  3. Integer.parseInt()解析成整数
  4. ArrayList存储整数,subList()取前100个
  5. Stream流式处理,mapToInt().sum()求和

C++

  1. isspace()判断空格,isdigit()判断数字
  2. stoi()将字符转整数
  3. vector存储数字,resize()调整大小
  4. accumulate求和,transform求平方
  5. 取vector前100个元素进行处理

代码

Go

func myAtoi(s string) int {
    // 定义最大整数值,是否允许符号,是否允许空白,符号,数字数组
    maxInt, signAllowed, whitespaceAllowed, sign, digits := int64(2<<30), true, true, 1, []int{}
    for _, c := range s {
      // 如果是空格且允许空白,继续
      if c == ' ' && whitespaceAllowed {
         continue
      }
      // 如果允许符号
      if signAllowed {
         // 如果是加号,不再允许符号和空白
         if c == '+' {
            signAllowed = false
            whitespaceAllowed = false
            continue
         } else if c == '-' { // 如果是减号,置符号为-1
            sign = -1
            signAllowed = false
            whitespaceAllowed = false
            continue
         }
      }
      // 如果不是数字,跳出循环
      if c < '0' || c > '9' {
         break
      }
      // 不再允许符号和空白
      whitespaceAllowed, signAllowed = false, false
      // 将字符转换为整数并加入数字数组 
      digits = append(digits, int(c-48))
    }
    // 定义返回值相关变量
    var num, place int64
    place, num = 1, 0
    // 记录最后一个前导0的索引
    lastLeading0Index := -1
    // 找到最后一个前导0
    for i, d := range digits {
       if d == 0 {
          lastLeading0Index = i
       } else {
          break
       }
    }
    // 如果有前导0,去掉前导0
    if lastLeading0Index > -1 {
       digits = digits[lastLeading0Index+1:]
    }
    // 定义正负数最大返回值
    var rtnMax int64
    if sign > 0 {
       rtnMax = maxInt - 1
    } else {
       rtnMax = maxInt
    }
    // 计算数字总位数
    digitsCount := len(digits)
    // 从低位到高位计算数值
    for i := digitsCount - 1; i >= 0; i-- {
       num += int64(digits[i]) * place
       place *= 10
       // 如果超出范围,返回最大值
       if digitsCount-i > 10 || num > rtnMax {
          return int(int64(sign) * rtnMax)
       }
    }
    // 加上符号
    num *= int64(sign)
    return int(num)
}

Python

class Solution:
    def myAtoi(self, s: str) -> int:
        max_int = 2**31 - 1
        min_int = -2**31
        sign = 1 # 符号默认为正
        result = 0 # 结果初始化为0
        index = 0
        n = len(s)
        # 去掉前导空格
        while index < n and s[index] == ' ':
            index += 1
        # 判断符号   
        if index < n and s[index] == '+':
            sign = 1
            index += 1
        elif index < n and s[index] == '-':
            sign = -1
            index += 1
        # 将后续数字字符转换为整数累加
        while index < n and s[index].isdigit():
            digit = int(s[index])
            result = result * 10 + digit
            index += 1
            # 每次处理一个数字后检查是否越界
            if result * sign <= min_int:
                return min_int
            if result * sign >= max_int:
                return max_int
        return sign * result

Java

class Solution {
    public int myAtoi(String s) {
        // 定义变量
        long maxInt = Integer.MAX_VALUE; 
        long minInt = Integer.MIN_VALUE;
        boolean signAllowed = true;
        boolean whitespaceAllowed = true;
        int sign = 1;
        List digits = new ArrayList<>();

        for(char c : s.toCharArray()) {
            // 处理空格
            if(c == ' ' && whitespaceAllowed) continue;

            // 处理正负号
            if(signAllowed) {
                if(c == '+') {
                    signAllowed = false;
                    whitespaceAllowed = false;
                    continue;
                } else if(c == '-') {
                    sign = -1;
                    signAllowed = false;
                    whitespaceAllowed = false;
                    continue;
                }
            }

            // 非数字则跳出
            if(c < '0' || c > '9') break;

            // 记录数字
            signAllowed = false;
            whitespaceAllowed = false;
            digits.add(c - '0');
        }

        // 处理前导0
        int lastLeading0 = -1;
        for(int i = 0; i < digits.size(); i++) {
            if(digits.get(i) == 0) lastLeading0 = i;
            else break;
        }
        if(lastLeading0 > -1) {
            digits = digits.subList(lastLeading0+1, digits.size());
        }

        // 计算数值
        long num = 0;
        for(int i = digits.size()-1; i >= 0; i--) {
            num += digits.get(i) * Math.pow(10, digits.size()-1-i);
            
            // 处理越界
            if(sign == 1 && num > maxInt) return (int)maxInt;
            if(sign == -1 && -num < minInt) return (int)minInt;
        }
        
        return (int)(sign * num);
    }
}

Cpp

#include 
#include 
#include 

class Solution {
public:
    int myAtoi(std::string s) {
        int i = 0;
        int sign = 1;
        int result = 0;

        if (s.empty()) {
            return 0;
        }

        // 跳过空格
        while (i < s.size() && s[i] == ' ') {
            i++;
        }

        // 处理正负号
        if (i < s.size() && (s[i] == '+' || s[i] == '-')) {
            sign = (s[i] == '-') ? -1 : 1;
            i++;
        }

        // 转换数字并检查溢出
        while (i < s.size() && isdigit(s[i])) {
            int digit = s[i] - '0';
            if (result > (std::numeric_limits::max() - digit) / 10) {
                return (sign == 1) ? std::numeric_limits::max() : std::numeric_limits::min();
            }
            result = result * 10 + digit;
            i++;
        }

        return result * sign;
    }
};

每个语言版本的基础知识点:

Go语言

  • strings包:strings.TrimSpace()可以删除字符串前导空格,strings.Contains()判断子串
  • strconv包:strconv.Atoi()字符串转整数,strconv.Itoa()整数转字符串
  • 数组和切片:数字存储在数组中,可以用append()添加,切片操作取子串
  • for range遍历:可以直接遍历字符串,通过下标或者rune类型访问字符
  • 类型转换:需要int和int64类型转换,用类型强转实现

Python

  • str方法:isspace()判断空格,isdigit()判断数字等
  • int强转:直接int()可以将字符串转整数
  • try-except:可以用try-except捕获整数转换溢出异常
  • 数学模块:提供pow()求幂等辅助方法

Java

  • 包装类:Integer, Long等箱装类提供数值范围常量
  • ArrayList:可以动态添加数字,subList()取子串
  • Math类:提供求幂等数学函数
  • 类型强转:需要处理int和long之间转换

C++

  • 头文件:需要imits等定义数值边界
  • isdigit()判断数字字符
  • string处理:substr()取子串等
  • 异常:可以用异常代替手动边界判断
  • 类型转换:静态强转或stoi,to_string等函数

9. Palindrome Number

题目

Determine whether an integer is a palindrome. An integer is a palindrome when it reads the same backward as forward.

Example 1:

Input: 121
Output: true

Example 2:

Input: -121
Output: false
Explanation: From left to right, it reads -121. From right to left, it becomes 121-. Therefore it is not a palindrome.

Example 3:

Input: 10
Output: false
Explanation: Reads 01 from right to left. Therefore it is not a palindrome.

Follow up:

Coud you solve it without converting the integer to a string?

题目大意

判断一个整数是否是回文数。回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数。

解题思路

  • 判断一个整数是不是回文数。
  • 简单题。注意会有负数的情况,负数,个位数,10 都不是回文数。其他的整数再按照回文的规则判断。
    Go语言版本:
  1. 用if判断负数和末尾为0的情况,直接返回false
  2. 用for循环不断对x取余,获取每个数字存入切片arr
  3. 判断切片长度,从两端向中间遍历,判断是否相等
  4. 如果不相等直接返回false,遍历结束返回true

Python语言版本:

  1. 用if判断负数情况,直接返回false
  2. 将整数转换为字符串s,方便后续遍历
  3. 求字符串长度,从两端向中间遍历字符串
  4. 判断字符是否相等,不等返回false,遍历结束返回true

Java语言版本:

  1. 方法一:和Python类似,将整数转换为字符串s
  2. 判断字符串长度,从两端向中间遍历,判断字符是否相等
  3. 方法二:通过整除和取余直接操作整数
  4. 用while循环逐位对比,判断是否回文

C++语言版本:

  1. 用if判断负数情况,直接返回false
  2. 用while循环对x取余,得到每位数字存入vector
  3. 判断vector长度,从两端向中间遍历,判断是否相等
  4. 也可以转换为字符串进行操作,思路同上
  5. 如果不相等直接返回false,遍历结束返回true

代码

Go

// 解法一
func isPalindrome(x int) bool {
    if x < 0 { // 如果x是负数,返回false
       return false
    }
    if x == 0 { // 如果x是0,返回true
       return true
    }
    if x%10 == 0 { // 如果x能被10整除,返回false
       return false
    }
    arr := make([]int, 0, 32) // 创建一个空切片arr
    for x > 0 { // 当x大于0时循环
       arr = append(arr, x%10) // 将x对10取余作为个位数存入arr
       x = x / 10 // x整除10
    }
    sz := len(arr) // 获得arr的长度
    for i, j := 0, sz-1; i <= j; i, j = i+1, j-1 { // 从头尾两边向中间遍历arr
       if arr[i] != arr[j] { // 如果两边的数字不相等
          return false // 返回false
       }
    }
    return true // 遍历完成,说明是回文,返回true
}
// 解法二 数字转字符串
func isPalindrome(x int) bool {
    if x < 0 { // 如果x是负数,返回false
       return false
    }
    if x < 10 { // 单位数都是回文,返回true
       return true
    }
    s := strconv.Itoa(x) // 将x转为字符串
    length := len(s) // 获得字符串长度
    for i := 0; i <= length/2; i++ { // 从两头向中间遍历字符串
       if s[i] != s[length-1-i] { // 如果两边的字符不相等
          return false // 返回false
       }
    }
    return true // 遍历完成,说明是回文,返回true
} 

Python

class Solution:
    def isPalindrome(self, x: int) -> bool:
        # 方法一
        if x < 0:
            return False
        if x == 0:
            return True
        if x % 10 == 0:
            return False
        arr = []
        while x > 0:
            arr.append(x % 10)
            x //= 10
        n = len(arr)
        for i in range(n // 2):
            if arr[i] != arr[n - 1 - i]:
                return False
        return True
class Solution:
    def isPalindrome(self, x: int) -> bool:
        # 方法二
        if x < 0:
            return False
        if x < 10:
            return True
        s = str(x)
        n = len(s)
        for i in range(n // 2):
            if s[i] != s[n - 1 - i]:
                return False
        return True 

Java

class Solution {    
  // 解法一:整数转换为字符串
  public boolean isPalindrome(int x) {
    if (x < 0) {
      return false;
    }
    if (x < 10) {
      return true;
    }
    String s = String.valueOf(x);
    int length = s.length();
    for (int i = 0; i <= length / 2; i++) {
      if (s.charAt(i) != s.charAt(length - 1 - i)) {
        return false;
      }
    }
    return true;
  }

}

class Solution {
  // 解法二:直接对整数操作
  public boolean isPalindrome(int x) {
    if (x < 0) {
      return false;
    }
    if (x == 0) {
      return true;
    }
    int div = 1;
    while (x / div >= 10) {
      div *= 10;
    }
    while (x != 0) {
      int left = x / div;
      int right = x % 10;
      if (left != right) {
        return false;
      }
      x = (x % div) / 10;
      div /= 100;
    }
    return true;
  }
}

Cpp

class Solution {
public:
    bool isPalindrome(int x) {
        // 方法一
        if(x < 0) return false;
        if(x == 0) return true;
        if(x % 10 == 0) return false;
        vector arr;
        while(x > 0) {
            arr.push_back(x % 10);
            x /= 10;
        }
        int n = arr.size();
        for(int i = 0; i < n / 2; i++) {
            if(arr[i] != arr[n - 1 - i])
                return false;
        }
        return true;

    }
}; 
class Solution {
public:
    bool isPalindrome(int x) {
        // 方法二
        if(x < 0) return false;
        if(x < 10) return true;
        string s = to_string(x);
        int n = s.size();
        for(int i = 0; i < n / 2; i++) {
            if(s[i] != s[n - 1 - i])
                return false;
        }
        return true;

    }
}; 

每个语言版本所需要掌握的基础知识:

Go语言版本:

  1. if条件判断,根据题目要求判断负数和0的情况
  2. 切片slice的定义和append添加元素
  3. for循环遍历切片
  4. len()求切片长度
  5. %取余运算符获取每位数字
  6. /=运算符整除并赋值

Python语言版本:

  1. if条件判断负数和0
  2. 将整数转换为字符串str()
  3. len()求字符串长度
  4. 字符串遍历和索引访问s[i]
  5. //运算符整除

Java语言版本:

  1. if条件判断负数和0
  2. String类及其方法charAt()
  3. 字符串遍历和长度len
  4. 整除运算符/和取余运算符%
  5. while循环

C++语言版本:

  1. if条件判断负数和0
  2. vector容器添加push_back和遍历
  3. size()求vector长度
  4. 字符串转换to_string和遍历
  5. %取余运算符获取每位数字
  6. /=运算符整除并赋值

10. Regular Expression Matching

题目

Given an input string s and a pattern p, implement regular expression matching with support for ‘.’ and ‘*’ where:

‘.’ Matches any single character.​​​​
‘*’ Matches zero or more of the preceding element.
The matching should cover the entire input string (not partial).

Example 1:

Input: s = “aa”, p = “a”
Output: false
Explanation: “a” does not match the entire string “aa”.
Example 2:

Input: s = “aa”, p = “a*”
Output: true
Explanation: ‘*’ means zero or more of the preceding element, ‘a’. Therefore, by repeating ‘a’ once, it becomes “aa”.
Example 3:

Input: s = “ab”, p = “."
Output: true
Explanation: ".
” means “zero or more (*) of any character (.)”.

题目大意

给你一个字符串 s 和一个字符规律 p,请你来实现一个支持 ‘.’ 和 ‘*’ 的正则表达式匹配。

‘.’ 匹配任意单个字符
‘*’ 匹配零个或多个前面的那一个元素
所谓匹配,是要涵盖 整个 字符串 s的,而不是部分字符串。

解题思路

Go语言:

  1. 使用动态规划求解,定义二维数组f[i][j] 表示s的前i个字符和p的前j个字符是否匹配
  2. 初始化f[0][0]为true,表示两字符串为空时匹配
  3. 使用双层for循环进行状态转移,考虑当前字符为’‘和非’'两种情况
  4. 当p[j-1]='*'时,分为使用和不使用两种情况讨论
  5. 不使用’*',直接继承f[i][j-2]的结果
  6. 使用’*',需要校验s[i-1]和p[j-2]是否匹配,如果匹配继承f[i-1][j]
  7. 非’*'时,判断s[i-1]和p[j-1]是否匹配,匹配则继承f[i-1][j-1]
  8. 返回f[m][n]作为最终结果

Python语言:

  1. 同样使用动态规划+二维数组f
  2. 初始化f[0][0]为true
  3. 双层for循环进行状态转移求解
  4. 当p[j-1]为’*'时,分不使用和使用两种情况
  5. 不使用继承f[i][j-2],使用需要校验s[i-1]和p[j-2]匹配
  6. 非’*'时判断s[i-1]和p[j-1]匹配则继承f[i-1][j-1]
  7. 返回f[m][n]作为结果

Java语言:
思路与上述相同:

  1. 动态规划,定义boolean数组f[i][j]
  2. 初始化f[0][0]为true
  3. 两层for循环做状态转移
  4. 分’‘和非’'情况讨论
  5. '*'时考虑不使用和使用两种情况
  6. 非’*'判断前一个字符是否匹配
  7. 返回f[m][n]作为最终解

C++语言:

  1. 使用二维vector初始化f,动态规划
  2. f[0][0]为true
  3. 双层for循环做状态转移
  4. 当p[j-1]为’*'分不使用和使用情况
  5. 不使用继承f[i][j-2],使用需要校验匹配
  6. 否则判断前一个字符是否匹配
  7. 返回f[m][n]作为结果

代码

Go

func isMatch(s string, p string) bool {
    // 定义s和p的长度
    m, n := len(s), len(p)
    // 判断s和p的子串从i和j位置开始是否匹配
    matches := func(i, j int) bool {
        // 如果i为0,说明s为空,返回false
        if i == 0 {
            return false
        }
        // 如果p[j-1]为'.',代表通配符,返回true
        if p[j-1] == '.' {
            return true
        }
        // 否则判断s[i-1]和p[j-1]是否相等
        return s[i-1] == p[j-1]
    }
    // 初始化二维数组f为m+1行n+1列
    f := make([][]bool, m + 1)
    for i := 0; i < len(f); i++ {
        f[i] = make([]bool, n + 1)
    }
    // 边界条件,如果s和p均为空,返回true
    f[0][0] = true
    // 动态规划状态转移
    for i := 0; i <= m; i++ {
        for j := 1; j <= n; j++ {
            // 如果p[j-1]为'*',有两种情况
            if p[j-1] == '*' {
                // 1. 不使用'*',直接继承f[i][j-2]的结果
                f[i][j] = f[i][j] || f[i][j-2]
                // 2. 使用'*',当s[i-1]和p[j-2]匹配时,继承f[i-1][j]的结果
                if matches(i, j - 1) {
                    f[i][j] = f[i][j] || f[i-1][j]
                }
            // 如果s[i-1]和p[j-1]匹配,继承f[i-1][j-1]的结果
            } else if matches(i, j) {
                f[i][j] = f[i][j] || f[i-1][j-1]
            }
        }
    }
    // 返回最终结果f[m][n]
    return f[m][n]
} 

Python

class Solution:
    def isMatch(self, s: str, p: str) -> bool:
        m, n = len(s), len(p)
        f = [[False] * (n+1) for _ in range(m+1)]
        f[0][0] = True
        for i in range(m+1):
            for j in range(1, n+1):
                if p[j-1] == '*':
                    f[i][j] |= f[i][j-2]
                    if self.matches(s, p, i, j-1):
                        f[i][j] |= f[i-1][j]
                else:
                    if self.matches(s, p, i, j):
                        f[i][j] |= f[i-1][j-1]
        return f[m][n]
    def matches(self, s, p, i, j):
        if i == 0:
            return False
        if p[j-1] == '.':
            return True
        return s[i-1] == p[j-1]

Java

class Solution {
    public boolean isMatch(String s, String p) {
        int m = s.length();
        int n = p.length();
        boolean[][] f = new boolean[m + 1][n + 1];
        f[0][0] = true;
        for (int i = 0; i <= m; i++) {
            for (int j = 1; j <= n; j++) {
                if (p.charAt(j-1) == '*') {
                    f[i][j] = f[i][j-2];
                    if (matches(s, p, i, j-1)) {
                        f[i][j] = f[i][j] || f[i-1][j];
                    }
                } else {
                    if (matches(s, p, i, j)) {
                        f[i][j] = f[i-1][j-1];
                    }
                }
            }
        }
        return f[m][n];
    }
    public boolean matches(String s, String p, int i, int j) {
        if (i == 0) {
            return false;
        }
        if (p.charAt(j-1) == '.') {
            return true;
        }
        return s.charAt(i-1) == p.charAt(j-1);
    }
}

Cpp

class Solution {
public:
    bool isMatch(string s, string p) {
        int m = s.size();
        int n = p.size();
        vector> f(m + 1, vector(n + 1, false));
        f[0][0] = true;
        for (int i = 0; i <= m; i++) {
            for (int j = 1; j <= n; j++) {
                if (p[j-1] == '*') {
                    f[i][j] = f[i][j-2];
                    if (matches(s, p, i, j-1)) {
                        f[i][j] = f[i][j] || f[i-1][j];
                    }
                } else {
                    if (matches(s, p, i, j)) {
                        f[i][j] = f[i-1][j-1];
                    }
                }
            }
        }
        return f[m][n];
    }
    bool matches(string s, string p, int i, int j) {
        if (i == 0) {
            return false;
        }
        if (p[j-1] == '.') {
            return true;
        }
        return s[i-1] == p[j-1];
    }
};

Go语言:

  1. 数组/切片的定义:var arr [n]type, make初始化,len获取长度
  2. 字符串访问:s[i]通过索引获取字符
  3. 函数定义:func xxx(参数) 返回值类型 {}
  4. if条件判断:if 条件 {} else {}
  5. for循环:for 初始化;条件;后续 {}
  6. 逻辑或:||
  7. 返回值:直接返回,可多值返回

Python:

  1. 列表生成式:[[0]* n for _ in range(m)]
  2. 字符串访问:s[i],索引从0开始
  3. 函数定义:def 函数名(参数):
  4. 条件判断:if 条件: elif: else:
  5. for循环:for 变量 in 集合:
  6. 逻辑或:|
  7. 返回值:return 直接返回

Java:

  1. 数组定义:类型[] 数组名 = new 类型[长度]
  2. 字符串访问:字符串.charAt(索引)
  3. 函数定义:返回值类型 函数名(参数) {}
  4. 条件判断:if() {} else {}
  5. for循环:for(初始化;条件;递增) {}
  6. 逻辑或:||
  7. 返回值:return 结果;

C++:

  1. vector定义:vector<类型> 名称(大小)
  2. 字符串访问:字符串[索引]
  3. 函数定义:返回值类型 函数名(参数) {}
  4. 条件判断:if() {} else {}
  5. for循环:for(初始化;条件;递增) {}
  6. 逻辑或:||
  7. 返回值:return 结果;

11. Container With Most Water

题目

Given n non-negative integers a1, a2, …, an , where each represents a point at coordinate (i, ai). n vertical lines are drawn such that the two endpoints of line i is at (i, ai) and (i, 0). Find two lines, which together with x-axis forms a container, such that the container contains the most water.

Note: You may not slant the container and n is at least 2.

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-P3DovAkA-1692502410923)(https://s3-lc-upload.s3.amazonaws.com/uploads/2018/07/17/question_11.jpg)]

The above vertical lines are represented by array [1,8,6,2,5,4,8,3,7]. In this case, the max area of water (blue section) the container can contain is 49.

Example 1:

Input: [1,8,6,2,5,4,8,3,7]
Output: 49

题目大意

给出一个非负整数数组 a1,a2,a3,…… an,每个整数标识一个竖立在坐标轴 x 位置的一堵高度为 ai 的墙,选择两堵墙,和 x 轴构成的容器可以容纳最多的水。

解题思路

这一题也是对撞指针的思路。首尾分别 2 个指针,每次移动以后都分别判断长宽的乘积是否最大。

Go版本

  • 定义最大面积max,左右指针start和end
  • 循环判断start
  • 计算宽度width为end-start
  • 初始化高度high为0
  • 判断height[start]和height[end]大小
  • 高度high取较小值
  • 移动高度较小指针
  • 计算面积temp为宽度*高度
  • 比较temp和max,更新max

Python版本

  • 定义最大面积max,左右指针start和end指向列表两端
  • 循环判断start
  • 计算宽度width为end-start
  • 初始化高度high为0
  • 判断height[start]和height[end]大小
  • 高度high取较小值
  • 移动高度较小指针
  • 计算面积area为宽度*高度
  • 比较area和max,更新max

Java版本

  • 定义最大面积max,左右指针start和end指向数组两端
  • 循环判断start
  • 计算宽度width为end-start
  • 初始化高度high为0
  • 判断height[start]和height[end]大小
  • 高度high取较小值
  • 移动高度较小指针
  • 计算面积temp为宽度*高度
  • 比较temp和max,更新max

C++版本

  • 定义最大面积max,左右指针start和end指向向量两端
  • 循环判断start
  • 计算宽度width为end-start
  • 初始化高度high为0
  • 判断height[start]和height[end]大小
  • 高度high取较小值
  • 移动高度较小指针
  • 计算面积temp为宽度*高度
  • 比较temp和max,更新max

代码

Go

func maxArea(height []int) int {
    // 初始化最大面积max为0,start为0,end为数组长度-1
    max, start, end := 0, 0, len(height)-1 
    // 当start小于end时循环
    for start < end {
       // 宽度为end-start
       width := end - start 
       // 高初始化为0 
       high := 0
       // 如果start位置的高度小于end位置 
       if height[start] < height[end] {
          // 高为start位置的高度
          high = height[start]
          // start加1
          start++
       } else {
          // 否则高为end位置的高度
          high = height[end]
          // end减1
          end--
       }
       // 临时面积为宽乘高
       temp := width * high
       // 如果临时面积大于最大面积
       if temp > max {
          // 更新最大面积
          max = temp
       }
    }
    // 返回最大面积
    return max
}

Python

class Solution:
    def maxArea(self, height: List[int]) -> int:
        # 初始化最大面积为0,左右指针start和end分别指向列表两端
        max_area = 0
        start = 0
        end = len(height) - 1
        while start < end:
            # 计算当前宽度
            width = end - start
            # 初始化高度为0
            high = 0
            if height[start] < height[end]:
                # 如果左指针对应的高度更小,则取左指针高度
                high = height[start]
                # 左指针右移
                start += 1
            else:
                # 否则取右指针高度
                high = height[end]
                # 右指针左移
                end -= 1
            # 计算当前面积   
            area = width * high
            # 如果当前面积大于最大面积,则更新最大面积
            if area > max_area:
                max_area = area
        return max_area

Java

class Solution {
    public int maxArea(int[] height) {
        // 初始化最大面积为0,左右指针start和end分别指向数组两端
        int max = 0, start = 0, end = height.length - 1;
        while(start < end) {
            // 计算当前宽度
            int width = end - start;
            // 初始化高度为0
            int high = 0;
            if(height[start] < height[end]) {
                // 如果左指针对应的高度更小,则取左指针高度
                high = height[start];
                // 左指针右移
                start++;
            } else {
                // 否则取右指针高度
                high = height[end];
                // 右指针左移
                end--;
            }
            // 计算当前面积
            int temp = width * high;
            // 如果当前面积大于最大面积,则更新最大面积
            if(temp > max) {
                max = temp;
            }
        }
        return max;
    }
}

Cpp

class Solution {
public:
    int maxArea(vector& height) {
        // 初始化最大面积为0,左右指针start和end分别指向向量两端
        int max = 0, start = 0, end = height.size() - 1;
        while(start < end) {
            // 计算当前宽度
            int width = end - start;
            // 初始化高度为0
            int high = 0;
            if(height[start] < height[end]) {
                // 如果左指针对应的高度更小,则取左指针高度
                high = height[start];
                // 左指针右移
                start++;
            } else {
                // 否则取右指针高度
                high = height[end];
                // 右指针左移
                end--;
            }
            // 计算当前面积
            int temp = width * high;
            // 如果当前面积大于最大面积,则更新最大面积
            if(temp > max) {
                max = temp;
            }
        }
        return max;
    }
};

每个语言版本需要掌握的基础知识:

Go 版本

Go语言版本需要掌握以下知识:

  • 变量声明 - 使用:=声明并初始化变量
  • 数组 - 使用[]int声明数组,len()获取数组长度
  • for循环 - for 开始条件; 结束条件; 步进
  • if条件判断 - if条件 {} else {}
  • 相加减 - +,-
  • 乘法 - *
  • 大于小于 - >,<
  • 返回值 - 使用return

Python版本

Python版本需要掌握以下知识:

  • 变量 - 无需声明类型,直接赋值使用
  • 列表 - 使用[]声明列表,len()获取长度
  • while循环 - while 条件:
  • if条件判断 - if 条件: 、else:
  • 相加减 - +,-
  • 乘法 - *
  • 大于小于 - >,<
  • 返回值 - return

Java版本

Java版本需要掌握以下知识:

  • 变量声明 - 声明变量类型,如int
  • 数组 - 使用int[]声明数组,.length获取长度
  • for循环或while循环
  • if条件判断 - if() {} else {}
  • 相加减 - +,-
  • 乘法 - *
  • 大于小于 - >,<
  • 返回值 - return

C++版本

C++版本需要掌握以下知识:

  • 变量声明 - 声明变量类型,如int
  • vector容器 - vector声明,.size()获取长度
  • while循环
  • if条件判断 - if() {} else {}
  • 相加减 - +,-
  • 乘法 - *
  • 大于小于 - >,<
  • 返回值 - return

12. Integer to Roman

题目

Roman numerals are represented by seven different symbols:I,V,X,L,C,DandM.

Symbol       Value
I             1
V             5
X             10
L             50
C             100
D             500
M             1000

For example,2is written asIIin Roman numeral, just two one’s added together.12is written asXII, which is
simplyX + II. The number27is written asXXVII, which isXX + V + II.

Roman numerals are usually written largest to smallest from left to right. However, the numeral for four is notIIII.
Instead, the number four is written asIV. Because the one is before the five we subtract it making four. The same
principle applies to the number nine, which is written asIX. There are six instances where subtraction is used:

  • Ican be placed beforeV(5) andX(10) to make 4 and 9.
  • Xcan be placed beforeL(50) andC(100) to make 40 and 90.
  • Ccan be placed beforeD(500) andM(1000) to make 400 and 900.

Given an integer, convert it to a roman numeral.

Example 1:

Input: num = 3
Output: "III"

Example 2:

Input: num = 4
Output: "IV"

Example 3:

Input: num = 9
Output: "IX"

Example 4:

Input: num = 58
Output: "LVIII"
Explanation: L = 50, V = 5, III = 3.

Example 5:

Input: num = 1994
Output: "MCMXCIV"
Explanation: M = 1000, CM = 900, XC = 90 and IV = 4.

Constraints:

  • 1 <= num <= 3999

题目大意

通常情况下,罗马数字中小的数字在大的数字的右边。但也存在特例,例如 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-3999 范围内的罗马数字从大到小放在数组中,从头选择到尾,即可把整数转成罗马数字。

Go语言版本:

  1. 定义整型数组values和字符串数组symbols,包含罗马数字的所有组合
  2. 初始化结果字符串res为空,索引i为0
  3. 使用for循环,当num不为0时循环
  4. 在循环内使用if判断,如果当前values中的值大于num,则i递增跳过
  5. 从num中减去当前values中的值
  6. 将对应的symbols中的字符串连接到res
  7. 最后返回res字符串作为结果

Python语言版本:

  1. 定义值列表values和符号列表symbols,包含罗马数字的所有组合
  2. 初始化结果字符串res为空,索引i为0
  3. 使用while循环,当num大于0时循环
  4. 在循环内使用if判断,如果当前values中的值大于num,则i递增跳过
  5. 从num中减去当前values中的值
  6. 将对应的symbols中的字符串连接到res
  7. 最后返回res字符串作为结果

Java语言版本:

  1. 定义整型数组values和字符串数组symbols,包含罗马数字的所有组合
  2. 初始化结果字符串res为空,索引i为0
  3. 使用while循环,当num大于0时循环
  4. 在循环内使用if判断,如果当前values中的值大于num,则i递增跳过
  5. 从num中减去当前values中的值
  6. 将对应的symbols中的字符串连接到res
  7. 最后返回res字符串作为结果

C++语言版本:

  1. 定义整型数组values和字符串数组symbols,包含罗马数字的所有组合
  2. 初始化结果字符串res为空,索引i为0
  3. 使用while循环,当num大于0时循环
  4. 在循环内使用if判断,如果当前values中的值大于num,则i递增跳过
  5. 从num中减去当前values中的值
  6. 将对应的symbols中的字符串连接到res
  7. 最后返回res字符串作为结果

代码

Go

func intToRoman(num int) string {
    values := []int{1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1} // 定义一个整数数组,包含罗马数字的基本值
    symbols := []string{"M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I"} // 定义一个字符串数组,包含对应的罗马符号
    res, i := "", 0 // res为返回的罗马数字字符串,i为values和symbols的索引
    for num != 0 { // 当num不为0时循环
        for values[i] > num { // 如果当前values中的值大于num
            i++ // i增加1
        }
        num -= values[i] // 从num中减去当前values中的值
        res += symbols[i] // 在res中加上对应的罗马符号
    }
    return res // 返回组成的罗马数字字符串
}

Python

class Solution:
    def intToRoman(self, num: int) -> str:
        values = [1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1] # 定义值列表
        symbols = ["M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I"] # 符号列表
        res = ""
        i = 0 # 结果字符串和索引
        while num > 0: # 当num大于0时循环
            while values[i] > num: # 如果当前值大于num
                i += 1 # 索引加1
            num -= values[i] # 从num中减去当前值
            res += symbols[i] # 在结果中添加对应的符号
        return res # 返回组成的罗马数字字符串

Java

class Solution {
    public String intToRoman(int num) {
        int[] values = {1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1}; // 定义整数数组,包含罗马数字的基本值
        String[] symbols = {"M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I"}; // 定义字符串数组,包含罗马符号
        String res = "";
        int i = 0; // 结果字符串res,以及values和symbols的索引i
        while(num > 0) { // 当num大于0时循环
            while(values[i] > num) { // 如果当前values中的值大于num
                i++; // i增加1
            }
            num -= values[i]; // 从num中减去当前values中的值
            res += symbols[i]; // 在res中添加对应的罗马符号
        }
        return res; // 返回组成的罗马数字字符串
    }
}

Cpp

class Solution {
public:
    string intToRoman(int num) {
        int values[] = {1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1}; // 定义整数数组,包含罗马数字的基本值
        string symbols[] = {"M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I"}; // 定义字符串数组,包含罗马符号
        string res;
        int i = 0; // 结果字符串res,以及values和symbols的索引i
        while(num > 0) { // 当num大于0时循环
            while(values[i] > num) { // 如果当前values中的值大于num
                i++; // i增加1
            }
            num -= values[i]; // 从num中减去当前values中的值
            res += symbols[i]; // 在res中添加对应的罗马符号
        }
        return res; // 返回组成的罗马数字字符串
    }
};

Go语言版本:

  • int类型:Go语言中的整型类型,用于表示整数。
  • string类型:Go语言中的字符串类型。
  • []int和[]string:定义整型数组和字符串数组。
  • for循环:Go语言的基本循环结构。
  • if条件判断:Go语言的条件判断结构。
  • +=运算符:字符串或整数的连接赋值运算符。
  • 函数定义和返回值:Go语言中定义函数的格式和返回值方式。

Python语言版本:

  • int类型:Python中的整型类型。
  • str类型:Python中的字符串类型。
  • list:Python中的列表,相当于数组。
  • while循环:Python的基本循环结构。
  • if条件判断:Python的条件判断结构。
  • +=运算符:字符串的连接赋值运算符。
  • def定义函数,return返回值:Python中定义函数和返回值的方式。

Java语言版本:

  • int类型:Java中的整型。
  • String类型:Java中的字符串类。
  • int[]和String[]:定义整型数组和字符串数组。
  • while循环:Java的循环结构。
  • if条件判断:Java的条件判断结构。
  • +=运算符:字符串的连接赋值运算符。
  • 方法定义,return返回值:Java中定义方法和返回值的方式。

C++语言版本:

  • int类型:C++中的整型。
  • string类型:C++中的字符串类。
  • int[]和string[]:定义整型数组和字符串数组。
  • while循环:C++的循环结构。
  • if条件判断:C++的条件判断结构。
  • +=运算符:字符串的连接赋值运算符。
  • 函数定义,return返回值:C++中定义函数和返回值的方式。

13. Roman to Integer

题目

Roman numerals are represented by seven different symbols:I,V,X,L,C,DandM.

Symbol       Value
I             1
V             5
X             10
L             50
C             100
D             500
M             1000

For example, two is written asIIin Roman numeral, just two one’s added together. Twelve is written as,XII, which is
simplyX+II. The number twenty seven is written asXXVII, which isXX+V+II.

Roman numerals are usually written largest to smallest from left to right. However, the numeral for four is notIIII.
Instead, the number four is written asIV. Because the one is before the five we subtract it making four. The same
principle applies to the number nine, which is written asIX. There are six instances where subtraction is used:

  • Ican be placed beforeV(5) andX(10) to make 4 and 9.
  • Xcan be placed beforeL(50) andC(100) to make 40 and 90.
  • Ccan be placed beforeD(500) andM(1000) to make 400 and 900.

Given a roman numeral, convert it to an integer. Input is guaranteed to be within the range from 1 to 3999.

Example 1:

Input: "III"
Output: 3

Example 2:

Input: "IV"
Output: 4

Example 3:

Input: "IX"
Output: 9

Example 4:

Input: "LVIII"
Output: 58
Explanation: L = 50, V= 5, III = 3.

Example 5:

Input: "MCMXCIV"
Output: 1994
Explanation: M = 1000, CM = 900, XC = 90 and IV = 4.

题目大意

罗马数字包含以下七种字符: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 到 3999 的范围内。
  • 简单题。按照题目中罗马数字的字符数值,计算出对应罗马数字的十进制数即可。

Go语言版本:

  1. 建立字符到整数的map映射
  2. 判断字符串是否为空,为空返回0
  3. 定义num, lastNum, total变量初始化为0
  4. 从后向前遍历字符串
  5. 获取当前字符,在map中找到对应数值
  6. 判断当前值与上一个值大小关系:如果小于上一个值,则减去当前值;否则加上当前值
  7. 更新lastNum为当前值
  8. 遍历结束返回total结果

Python语言版本:

  1. 建立字符到整数的dict字典
  2. 判断字符串是否为空,为空返回0
  3. 定义num, last_num, total变量初始化为0
  4. 倒序遍历字符串,range从len-1到0
  5. 获取当前字符,在dict中找到对应数值
  6. 判断当前值与上一个值大小关系:如果小于上一个值,则减去当前值;否则加上当前值
  7. 更新last_num为当前值
  8. 遍历结束返回total结果

Java语言版本:

  1. 建立字符到整数的Map映射
  2. 判断字符串是否为空,为空返回0
  3. 定义num, lastNum, total变量初始化为0
  4. 倒序遍历字符串,i–实现
  5. 获取当前字符,在Map中找到对应数值
  6. 判断当前值与上一个值大小关系:如果小于上一个值,则减去当前值;否则加上当前值
  7. 更新lastNum为当前值
  8. 遍历结束返回total结果

C++语言版本:

  1. 建立字符到整数的map映射
  2. 判断字符串是否为空,为空返回0
  3. 定义num, lastNum, total变量初始化为0
  4. 倒序遍历字符串,i–实现
  5. 获取当前字符,在map中找到对应数值
  6. 判断当前值与上一个值大小关系:如果小于上一个值,则减去当前值;否则加上当前值
  7. 更新lastNum为当前值
  8. 遍历结束返回total结果

代码

Go

// 定义一个map,映射罗马数字字符到整数值
var roman = map[string]int{ 
    "I": 1,
    "V": 5, 
    "X": 10,
    "L": 50,
    "C": 100,
    "D": 500,
    "M": 1000,
}
// 将罗马数字字符串转换为整数的函数
func romanToInt(s string) int {
    // 如果传入空字符串,直接返回0
    if s == "" { 
       return 0
    }
    // 定义num为当前数字值,lastint为上一个数字值,total为结果
    num, lastint, total := 0, 0, 0
    // 从字符串末尾向前遍历
    for i := 0; i < len(s); i++ {
       // 获取当前字符 
       char := s[len(s)-(i+1) : len(s)-i]
       // 在map中找当前字符对应的数字值 
       num = roman[char]
       // 如果当前数字小于上一个数字,则减去当前数字
       if num < lastint {
          total = total - num
       } else {
           // 否则加上当前数字
          total = total + num
       }
       // 更新lastint为当前数字值
       lastint = num
    }
    // 返回最终结果
    return total
}

Python

class Solution:
    def romanToInt(self, s: str) -> int:
        
        # 定义一个字典,映射罗马数字字符到整数值
        roman = {'I': 1, 'V': 5, 'X': 10, 'L': 50, 'C': 100, 'D': 500, 'M': 1000}
        
        # 如果传入空字符串,直接返回0
        if not s:
            return 0
        
        # 定义当前数字、上一个数字和结果变量        
        num, last_num, total = 0, 0, 0
        
        # 从字符串末尾向前遍历
        for i in range(len(s)-1, -1, -1):
            
            # 获取当前字符
            char = s[i]
            
            # 在字典中找当前字符对应的数字
            num = roman[char]
            
            # 如果当前数字小于上一个数字,则减去当前数字
            if num < last_num:
                total -= num
            else:
                # 否则加上当前数字
                total += num
                
            # 更新last_num为当前数字
            last_num = num
        
        return total
        

Java

class Solution {
    public int romanToInt(String s) {
        // 定义一个Map,映射罗马数字字符到整数值
        Map roman = new HashMap<>();
        roman.put('I', 1);
        roman.put('V', 5);
        roman.put('X', 10);
        roman.put('L', 50);
        roman.put('C', 100);
        roman.put('D', 500);
        roman.put('M', 1000);

        // 如果传入空字符串,直接返回0
        if (s.isEmpty()) {
            return 0;
        }
        
        // 初始化lastNum为0
        int num, lastNum = 0, total = 0;

        // 从字符串末尾向前遍历
        for (int i = s.length() - 1; i >= 0; i--) {

            // 获取当前字符
            char c = s.charAt(i);

            // 在map中找当前字符对应的数字
            num = roman.get(c);

            // 如果当前数字小于上一个数字,则减去当前数字
            if (num < lastNum) {
                total -= num; 
            } else {
                // 否则加上当前数字
                total += num;
            }

            // 更新lastNum为当前数字
            lastNum = num;
        }
        
        // 返回最终结果
        return total;
    }
}

Cpp

class Solution {
public:
    int romanToInt(string s) {
        
        // 定义一个map,映射罗马数字字符到整数值
        unordered_map roman = {{'I', 1}, {'V', 5}, {'X', 10}, {'L', 50}, 
                                         {'C', 100}, {'D', 500}, {'M', 1000}}; 
        
        // 如果传入空字符串,直接返回0
        if (s.empty()) {
            return 0; 
        }
        
        // 定义当前数字、上一个数字和结果变量
        int num, lastNum = 0, total = 0;
        
        // 从字符串末尾向前遍历
        for (int i = s.length() - 1; i >= 0; i--) {
            
            // 获取当前字符
            char c = s[i];
            
            // 在map中找当前字符对应的数字值
            num = roman[c];
            
            // 如果当前数字小于上一个数字,则减去当前数字
            if (num < lastNum) {
                total -= num;
            } else {
                // 否则加上当前数字
                total += num;
            }
            
            // 更新lastNum为当前数字
            lastNum = num;
        }
        
        return total;
    }
};

Go语言版本:

  • map:Go语言中map是一种键值对的集合,可以用来建立字符和整数之间的映射关系。
  • len函数:可以获取字符串的长度。
  • 切片:s[start:end]可以提取字符串的一段子串。
  • if条件判断和else分支。
  • 定义多个变量:num, lastint, total := 0, 0, 0。
  • for循环遍历字符串。
    -字符串拼接:char := s[len(s)-(i+1) : len(s)-i]。

Python语言版本:

  • 字典dict:Python中的字典可以建立字符和整数之间的映射关系。
  • len函数:可以获取字符串的长度。
    -下标索引:s[i] 获取字符串中的字符。
  • if条件判断和else分支。
  • 定义多个变量:num, last_num, total = 0, 0, 0。
  • for循环遍历字符串,range函数生成索引。
  • 减一运算:range(len(s)-1, -1, -1)。

Java语言版本:

  • Map集合:可以建立键值对映射关系。
  • isEmpty判断字符串是否为空。
  • charAt取字符串指定位置的字符。
  • HashMap创建Map集合。
  • if条件判断和else分支。
  • for循环遍历字符串,i–实现倒序。
  • length获取字符串长度。

C++语言版本:

  • unordered_map映射集合,可以建立字符和整数的映射。
  • empty判断字符串是否为空。
  • []访问向量元素。
  • if条件判断和else分支。
  • 定义多个变量:int num, lastNum = 0, total = 0。
  • for循环遍历字符串,i–实现倒序。
  • length函数获取字符串长度。

14. Longest Common Prefix

题目

Write a function to find the longest common prefix string amongst an array of strings.

If there is no common prefix, return an empty string “”.

Example 1:

Input: strs = ["flower","flow","flight"]
Output: "fl"

Example 2:

Input: strs = ["dog","racecar","car"]
Output: ""
Explanation: There is no common prefix among the input strings.

Constraints:

  • 1 <= strs.length <= 200
  • 0 <= strs[i].length <= 200
  • strs[i] consists of only lower-case English letters.

题目大意

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

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

解题思路

  • 对 strs 按照字符串长度进行升序排序,求出 strs 中长度最小字符串的长度 minLen
  • 逐个比较长度最小字符串与其它字符串中的字符,如果不相等就返回 commonPrefix,否则就把该字符加入 commonPrefix

Go版本

  1. 将第一个字符串设为prefix
  2. 遍历剩余字符串
  3. 逐字符比较prefix,如果不相等则减少prefix长度
  4. 不断重复步骤3,直到prefix为空或符合所有字符串
  5. 返回prefix
    主要是利用字符串的遍历和切片操作逐步缩短prefix。

Python版本

  1. 第一个字符串为prefix
  2. 循环遍历其余字符串
  3. 使用find方法判断是否以prefix开头
  4. 如果不符合,减少prefix长度
  5. 不断重复步骤3、4,直到prefix为空或符合所有字符串
  6. 返回prefix
    利用了find方法和切片操作判断并修改prefix。

Java版本

  1. 第一个字符串为prefix
  2. 循环遍历其余字符串
  3. 使用indexOf判断是否以prefix开头
  4. 如果不符合,减少prefix长度
  5. 不断重复步骤3、4,直到prefix为空或符合所有字符串
  6. 返回prefix
    同样利用了indexOf和substring方法判断并获取子串。

C++版本

  1. 第一个字符串为prefix
  2. 循环遍历其余字符串
  3. 使用find方法判断是否以prefix开头
  4. 如果不符合,减少prefix长度
  5. 不断重复步骤3、4,直到prefix为空或符合所有字符串
  6. 返回prefix
    依靠find和substr方法判断和获取子串。

代码

Go

func longestCommonPrefix(strs []string) string {
    prefix := strs[0]

    for i := 1; i < len(strs); i++ {
        for j := 0; j < len(prefix); j++ {
            if len(strs[i]) <= j || strs[i][j] != prefix[j] {
                prefix = prefix[0:j]
                break
            }
        }
    }

    return prefix
}

Python

class Solution:
    def longestCommonPrefix(self, strs: List[str]) -> str:
        if not strs: return ""
        prefix = strs[0]
        for i in range(1, len(strs)):
            while strs[i].find(prefix) != 0:
                prefix = prefix[:len(prefix)-1]
                if not prefix: return ""
        return prefix

Java

class Solution {
    public String longestCommonPrefix(String[] strs) {
        if (strs.length == 0) return "";
        String prefix = strs[0];
        for (int i = 1; i < strs.length; i++) {
            while (strs[i].indexOf(prefix) != 0) {
                prefix = prefix.substring(0, prefix.length() - 1);
                if (prefix.isEmpty()) return "";
            }       
        }
        return prefix;
    }
}

Cpp

class Solution {
public:
    string longestCommonPrefix(vector& strs) {
        if (strs.empty()) return "";
        string prefix = strs[0];
        for (int i = 1; i < strs.size(); i++) {
            while (strs[i].find(prefix) != 0) {
                prefix = prefix.substr(0, prefix.size()-1);
                if (prefix.empty()) return "";
            }
        }
        return prefix;
    }
};

每个版本需要掌握的基础知识:

Go 版本

  • strings包:strings包提供字符串操作相关函数,如Contains、Index等
  • 字符串遍历:可以通过for循环遍历字符串的字节
  • 字符串切片:可以通过指定开始和结束位置[i:j]来获取子字符串

Python 版本

  • str类型:Python内置的字符串类型
  • find方法:查找子字符串在字符串中出现的位置,返回第一个匹配位置的索引,不存在返回-1
  • 切片操作:通过指定开始和结束位置[i:j]可以获取子字符串

Java 版本

  • String类:String代表不可变字符串,有索引访问字符和子字符串获取等方法
  • indexOf方法:查找子字符串在字符串中出现的位置,返回第一个匹配位置索引,不存在返回-1
  • substring方法:获取字符串指定区间的子字符串

C++版本

  • string类:string代表字符串对象,支持遍历、访问单个字符、获取子串等操作
  • find方法:查找子串在字符串中首次出现的位置,不存在返回string::npos
  • substr方法:获取子字符串中指定范围的字符

你可能感兴趣的:(LeetCode,golang,python,java,leetcode)