用正则表达式刷力扣每日一题(2026/06/29)
2029. 石子游戏 IX
2029. 石子游戏 IX
查看正则表达式可视化匹配过程
更多的正则表达式解法,请看我的合集
using System.Text.RegularExpressions;
public class Solution {
static Regex regex = new Regex(@"(?x)
^(?>
(?>(?=[147]()|)(?>[258](?'1'){2}|\d)(?>(?'-2')(?'1')|){2}(?>(?'-1'){3}|((?'-1'))|){2})+
(?((?'-2'))(?((?'-2'))(?#index is 2)()|(?#index is 1)())|(?#index is 0)())(?>,|$)
)+$
(?<=(?>(?'-5'){2}.)*)
(?(5)(?<=(?>(?'-4')(?'-3').)*)(?<=(?>(?'1')(?'-4').)*(?>(?'1')(?'-3').)*)(?'-1'){3}
|(?'-3')(?'-4')
)", RegexOptions.Compiled);
public bool StoneGameIX(int[] stones) {
return regex.IsMatch(string.Join(",", stones));
}
}
using System.Text.RegularExpressions;
public class Solution {
static Regex regex = new Regex(@"(?x)
# ==================== 阶段一:扫描输入,分类统计 ====================
^ # 字符串开头
(?>
# --- 内层循环:逐个字符处理当前石头的每一位 ---
(?>(?=[147]()|) # Lookahead:若当前字符是 1/4/7(即 %3==1),向隐式组压入空捕获(c[1]++)
(?>[258](?'1'){2} # 若当前字符是 2/5/8(即 %3==2),向命名组 ""1"" 压入 2 个空捕获(c[2] += 2)
| \d) # 否则(%3==0 的数字),仅匹配该字符,不做计数
(?>(?'-2')(?'1')|){2} # 从组 2 弹出,同时向组 1 压入;重复 2 次(中间寄存器转移)
(?>(?'-1'){3} # 尝试从组 1 连续弹出 3 次(消去一个完整的 3)
| ((?'-1')) # 若不足 3 但至少有 1,弹出 1 次,并把 ""余 1"" 记录到编号组 2
| # 若组 1 已空,什么都不做
){2} # 重复两次后,编号组 2 的深度 = 当前数字对 ""状态索引"" 的贡献(0/1/2)
)+ # 内层 +:处理当前石头的每一位(个位数时只执行一次)
# --- 根据 ""状态索引"" 将当前石头归类到 3 个状态桶 ---
(?(
(?'-2') # 尝试从组 2 再弹一次
)
(?(
(?'-2') # 再弹一次
)
(?#index is 2) () # 组 2 原本 ≥2:向编号组 3 压栈(index=2 的桶)
|
(?#index is 1) () # 组 2 原本 =1:向编号组 4 压栈(index=1 的桶)
)
|
(?#index is 0) () # 组 2 原本 =0:向编号组 5 压栈(index=0 的桶,即 c[0])
)
(?>,|$) # 匹配逗号(下一个石头)或字符串结尾
)+$ # 外层 +:循环处理所有石头,直到字符串结尾
# ==================== 阶段二:最终胜负判定 ====================
(?<= # 正向 lookbehind:从字符串末尾往回检查最终状态
(?>(?'-5'){2}.)* # 每次从组 5 弹出 2 个,同时匹配任意字符
# 若组 5 深度(c[0])为偶数,可刚好弹完;若为奇数,剩余 1 个
)
# --- 条件分支:根据 c[0] 的奇偶性走不同判定逻辑 ---
(?(5) # 如果组 5 还有剩余(即 c[0] 为奇数)→ 走奇数分支
(?<=
(?>(?'-4')(?'-3').)* # 同时从组 4 和组 3 各弹 1 个并匹配字符
# 反复执行,把 min(c[1], c[2]) 完全配对消去
)
(?<=
(?>(?'1')(?'-4').)* # 若组 4 还有剩余(c[1] > c[2]),向组 1 转移
(?>(?'1')(?'-3').)* # 若组 3 还有剩余(c[2] > c[1]),向组 1 转移
# 执行后,组 1 的深度 = abs(c[1] - c[2])
)
(?'-1'){3} # 要求组 1 还能再弹出 3 个
# 即 abs(c[1] - c[2]) > 2 → Alice 必胜
|
# 偶数分支:c[0] 为偶数 → 判定 min(c[1], c[2]) > 0
(?'-3')(?'-4') # 同时从组 3 和组 4 各弹 1 个
# 只有当两者都非空时才能成功 # 即 min(c[1], c[2]) > 0 → Alice 必胜
)", RegexOptions.Compiled);
public bool StoneGameIX(int[] stones) {
return regex.IsMatch(string.Join(",", stones));
}
}
文章摘自:https://www.cnblogs.com/regexdev/p/22502736
