力扣 779. 第K个语法符号

题目来源:https://leetcode.cn/problems/k-th-symbol-in-grammar/

大致题意:
题目构建了一个 n 行的表,表的第一行为 0,之后每一行的内容都由上一行的内容变化而来。变化规则为:

  • 0 变为 01
  • 1 变为 10

求第 n 行第 k 个元素的值

思路

根据题意,那么表的前几行为

  • 0
  • 01
  • 0110
  • 01101001
  • 0110100110010110
  • 01101001100101100110100110010110

那么可以看出,第 i 行的第 j 个数由第 i - 1 行的第 (j + 1) / 2 个数变化而来,它们的关系有

  • 第 i - 1 行的第 (j + 1) / 2 个数为 0,变化数为 01,第 i 行的第 j 个数为奇数,那么对应 01 的第 1 个值 0
  • 第 i - 1 行的第 (j + 1) / 2 个数为 0,变化数为 01,第 i 行的第 j 个数为偶数,那么对应 01 的第 2 个值 1
  • 第 i - 1 行的第 (j + 1) / 2 个数为 1,变化数为 10,第 i 行的第 j 个数为奇数,那么对应 01 的第 1 个值 1
  • 第 i - 1 行的第 (j + 1) / 2 个数为 1,变化数为 10,第 i 行的第 j 个数为偶数,那么对应 01 的第 2 个值 0

综上可知

  • 第 i - 1 行的第 (j + 1) / 2 个数的变化数为 xy,若第 i 行的第 j 个数为奇数,那么其为 x;否则,其为 y

同样,根据上面的规律可以看出第 1 个数永远为 0,那么可以逆序求出每一行的奇偶性,直至当前元素值为 1,再根据刚刚求得的奇偶性求出最终结果

具体解题流程为

  1. 使用 k 表示当前数为所在行第 k 个数,使用栈存储 k 大于 1 时 k 的奇偶性
  2. 在 k 大于 1 时执行循环,存下当前奇偶性并更新 k 的值为 (k + 1) / 2。这里表示当前行第 k 个值,由上一行第 (k + 1) / 2 值变化而来
  3. 初始化当前值为 0,根据奇偶性更新下一行的值,直至栈空

代码:

public int kthGrammar(int n, int k) {
        // 存每一行的奇偶情况
        Deque<Integer> stack = new ArrayDeque<>();
        while (k > 1) {
            // 偶数将 2 入栈,表示当前数是上一行对应位置变化数的第 2 个
            if (k % 2 == 0) {
                stack.push(2);
            } else {    // 奇数将 1 入栈,表示当前数是上一行对应位置变化数的第 1 个
                stack.push(1);
            }
            // 更新索引
            k = (k + 1) / 2;
        }
        // 取当前索引对应的数
        int ans = 0;
        while (!stack.isEmpty()) {
            // 取出当前行标志位
            int cur = stack.pop();
            // 根据上一行对应位置的值,计算其变化的值
            // 0 变为 01;1 变为 10
            int first = ans == 0 ? 0 : 1;
            int second = first == 0 ? 1 : 0;
            // 如果标志位为 1,表示当前行是奇数位,为第一个值
            if (cur == 1) {
                ans = first;
            } else {    // 否则表示当前行为偶数位,为第二个值
                ans = second;
            }
        }
        return ans;
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

三更鬼

谢谢老板!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值