返回

Java与C++题解与拓展——leetcode779.第K个语法符号【么的新知识】

后端







**摘要** 

本文主要讲述了leetcode 779.第K个语法符号题目及解题思路,提供Java、C++和Rust三种语言代码实现并提供详细注释,并分享了所使用类和方法的学习心得。

**正文** 

**题目** 

给你一个字符串 s,它只包含字符 '0' 和 '1',你需要返回第 k 个语法符号。

我们定义一个助记词 sequence 来记录下语法的变化,依次为 "0", "01", "011", "0111", "01111", "011111", "0111111", ... 并观察如下规律:

- sequence 中的第 1 个元素是 "0"。
- sequence 中的第 k 个元素可以由 sequence[k - 1] 算出:如果 sequence[k - 1] 以 "0" 开头,那么 sequence[k] 就是 "0" 后接一个 "1";如果 sequence[k - 1] 以 "1" 开头,那么 sequence[k] 就是 "1" 后接一个 "0"。
- 给你一个整数 k,你需要返回 sequence[k] 的最后一个字符。

**算法** 

我们可以通过以下步骤来解决这个问题:

1. 初始化一个字符串 sequence,它只包含一个 "0" 字符。
2. 对于 k 从 2 到 n,我们做以下操作:
    - 如果 sequence[k - 1] 以 "0" 开头,那么 sequence[k] 就是 "0" 后接一个 "1"。
    - 如果 sequence[k - 1] 以 "1" 开头,那么 sequence[k] 就是 "1" 后接一个 "0"3. 返回 sequence[k] 的最后一个字符。

**Java代码实现** 

```java
class Solution {
    public int kthGrammar(int n, int k) {
        // 如果是第一个字符,直接返回0
        if (n == 1) {
            return 0;
        }
        // 否则,我们递归地计算出sequence[n - 1]
        int prev = kthGrammar(n - 1, (k + 1) / 2);
        // 如果sequence[n - 1]以0开头,那么sequence[n]就是0后接一个1
        if (prev == 0) {
            return k % 2;
        } else {
            // 如果sequence[n - 1]以1开头,那么sequence[n]就是1后接一个0
            return 1 - (k % 2);
        }
    }
}

C++代码实现

class Solution {
public:
    int kthGrammar(int n, int k) {
        // 如果是第一个字符,直接返回0
        if (n == 1) {
            return 0;
        }
        // 否则,我们递归地计算出sequence[n - 1]
        int prev = kthGrammar(n - 1, (k + 1) / 2);
        // 如果sequence[n - 1]以0开头,那么sequence[n]就是0后接一个1
        if (prev == 0) {
            return k % 2;
        } else {
            // 如果sequence[n - 1]以1开头,那么sequence[n]就是1后接一个0
            return 1 - (k % 2);
        }
    }
};

Rust代码实现

fn kth_grammar(n: usize, k: usize) -> usize {
    // 如果是第一个字符,直接返回0
    if n == 1 {
        return 0;
    }
    // 否则,我们递归地计算出sequence[n - 1]
    let prev = kth_grammar(n - 1, (k + 1) / 2);
    // 如果sequence[n - 1]以0开头,那么sequence[n]就是0后接一个1
    if prev == 0 {
        return k % 2;
    } else {
        // 如果sequence[n - 1]以1开头,那么sequence[n]就是1后接一个0
        return 1 - (k % 2);
    }
}

所用类和方法的学习心得

在本文中,我们使用了以下类和方法:

  • Java中的StringBuilder类,用于动态创建和修改字符串。
  • C++中的string类,用于表示字符串。
  • Rust中的String类型,用于表示字符串。
  • Java中的substring()方法,用于截取字符串。
  • C++中的substr()方法,用于截取字符串。
  • Rust中的slice()方法,用于截取字符串。
  • Java中的indexOf()方法,用于查找子字符串在字符串中的位置。
  • C++中的find()方法,用于查找子字符串在字符串中的位置。
  • Rust中的find()方法,用于查找子字符串在字符串中的位置。

通过学习这些类和方法,我更好地理解了字符串操作的基本原理,并能够更加轻松地编写出高效的字符串处理代码。