返回介绍

solution / 1600-1699 / 1625.Lexicographically Smallest String After Applying Operations / README

发布于 2024-06-17 01:03:16 字数 8353 浏览 0 评论 0 收藏 0

1625. 执行操作后字典序最小的字符串

English Version

题目描述

给你一个字符串 s 以及两个整数 ab 。其中,字符串 s 的长度为偶数,且仅由数字 09 组成。

你可以在 s 上按任意顺序多次执行下面两个操作之一:

  • 累加:将  a 加到 s 中所有下标为奇数的元素上(下标从 0 开始)。数字一旦超过 9 就会变成 0,如此循环往复。例如,s = "3456"a = 5,则执行此操作后 s 变成 "3951"
  • 轮转:将 s 向右轮转 b 位。例如,s = "3456"b = 1,则执行此操作后 s 变成 "6345"

请你返回在 s 上执行上述操作任意次后可以得到的 字典序最小 的字符串。

如果两个字符串长度相同,那么字符串 a 字典序比字符串 b 小可以这样定义:在 ab 出现不同的第一个位置上,字符串 a 中的字符出现在字母表中的时间早于 b 中的对应字符。例如,"0158” 字典序比 "0190" 小,因为不同的第一个位置是在第三个字符,显然 '5' 出现在 '9' 之前。

 

示例 1:

输入:s = "5525", a = 9, b = 2
输出:"2050"
解释:执行操作如下:
初态:"5525"
轮转:"2555"
累加:"2454"
累加:"2353"
轮转:"5323"
累加:"5222"
累加:"5121"
轮转:"2151"
累加:"2050"​​​​​
无法获得字典序小于 "2050" 的字符串。

示例 2:

输入:s = "74", a = 5, b = 1
输出:"24"
解释:执行操作如下:
初态:"74"
轮转:"47"
累加:"42"
轮转:"24"​​​​​
无法获得字典序小于 "24" 的字符串。

示例 3:

输入:s = "0011", a = 4, b = 2
输出:"0011"
解释:无法获得字典序小于 "0011" 的字符串。

 

提示:

  • 2 <= s.length <= 100
  • s.length 是偶数
  • s 仅由数字 09 组成
  • 1 <= a <= 9
  • 1 <= b <= s.length - 1

解法

方法一:BFS

本题数据规模较小,我们可以使用 BFS 暴力搜索所有可能的状态,然后取字典序最小的状态即可。

class Solution:
  def findLexSmallestString(self, s: str, a: int, b: int) -> str:
    q = deque([s])
    vis = {s}
    ans = s
    while q:
      s = q.popleft()
      if ans > s:
        ans = s
      t1 = ''.join(
        [str((int(c) + a) % 10) if i & 1 else c for i, c in enumerate(s)]
      )
      t2 = s[-b:] + s[:-b]
      for t in (t1, t2):
        if t not in vis:
          vis.add(t)
          q.append(t)
    return ans
class Solution {
  public String findLexSmallestString(String s, int a, int b) {
    Deque<String> q = new ArrayDeque<>();
    q.offer(s);
    Set<String> vis = new HashSet<>();
    vis.add(s);
    String ans = s;
    int n = s.length();
    while (!q.isEmpty()) {
      s = q.poll();
      if (ans.compareTo(s) > 0) {
        ans = s;
      }
      char[] cs = s.toCharArray();
      for (int i = 1; i < n; i += 2) {
        cs[i] = (char) (((cs[i] - '0' + a) % 10) + '0');
      }
      String t1 = String.valueOf(cs);
      String t2 = s.substring(n - b) + s.substring(0, n - b);
      for (String t : List.of(t1, t2)) {
        if (vis.add(t)) {
          q.offer(t);
        }
      }
    }
    return ans;
  }
}
class Solution {
public:
  string findLexSmallestString(string s, int a, int b) {
    queue<string> q{{s}};
    unordered_set<string> vis{{s}};
    string ans = s;
    int n = s.size();
    while (!q.empty()) {
      s = q.front();
      q.pop();
      ans = min(ans, s);
      string t1 = s;
      for (int i = 1; i < n; i += 2) {
        t1[i] = (t1[i] - '0' + a) % 10 + '0';
      }
      string t2 = s.substr(n - b) + s.substr(0, n - b);
      for (auto& t : {t1, t2}) {
        if (!vis.count(t)) {
          vis.insert(t);
          q.emplace(t);
        }
      }
    }
    return ans;
  }
};
func findLexSmallestString(s string, a int, b int) string {
  q := []string{s}
  vis := map[string]bool{s: true}
  ans := s
  n := len(s)
  for len(q) > 0 {
    s = q[0]
    q = q[1:]
    if ans > s {
      ans = s
    }
    t1 := []byte(s)
    for i := 1; i < n; i += 2 {
      t1[i] = byte((int(t1[i]-'0')+a)%10 + '0')
    }
    t2 := s[n-b:] + s[:n-b]
    for _, t := range []string{string(t1), t2} {
      if !vis[t] {
        vis[t] = true
        q = append(q, t)
      }
    }
  }
  return ans
}

方法二:枚举

我们观察发现,对于累加操作,数字最多累加 $10$ 次,就会回到原来的状态;对于轮转操作,字符串最多轮转 $n$ 次,也会回到原来的状态。

因此,轮转操作最多产生 $n$ 种状态,如果轮转位数 $b$ 为偶数,累加操作只会对奇数位数字产生影响,因此总共产生 $n \times 10$ 种状态;如果轮转位数 $b$ 为奇数,累加操作既会对奇数位数字产生影响,也会对偶数位数字产生影响,因此总共产生 $n \times 10 \times 10$ 种状态。

所以,我们直接枚举所有的字符串状态,取字典序最小的状态即可。

时间复杂度 $O(n^2 \times 10^2)$,空间复杂度 $O(n)$。其中 $n$ 为字符串 $s$ 的长度。

class Solution:
  def findLexSmallestString(self, s: str, a: int, b: int) -> str:
    ans = s
    n = len(s)
    s = list(s)
    for _ in range(n):
      s = s[-b:] + s[:-b]
      for j in range(10):
        for k in range(1, n, 2):
          s[k] = str((int(s[k]) + a) % 10)
        if b & 1:
          for p in range(10):
            for k in range(0, n, 2):
              s[k] = str((int(s[k]) + a) % 10)
            t = ''.join(s)
            if ans > t:
              ans = t
        else:
          t = ''.join(s)
          if ans > t:
            ans = t
    return ans
class Solution {
  public String findLexSmallestString(String s, int a, int b) {
    int n = s.length();
    String ans = s;
    for (int i = 0; i < n; ++i) {
      s = s.substring(b) + s.substring(0, b);
      char[] cs = s.toCharArray();
      for (int j = 0; j < 10; ++j) {
        for (int k = 1; k < n; k += 2) {
          cs[k] = (char) (((cs[k] - '0' + a) % 10) + '0');
        }
        if ((b & 1) == 1) {
          for (int p = 0; p < 10; ++p) {
            for (int k = 0; k < n; k += 2) {
              cs[k] = (char) (((cs[k] - '0' + a) % 10) + '0');
            }
            s = String.valueOf(cs);
            if (ans.compareTo(s) > 0) {
              ans = s;
            }
          }
        } else {
          s = String.valueOf(cs);
          if (ans.compareTo(s) > 0) {
            ans = s;
          }
        }
      }
    }
    return ans;
  }
}
class Solution {
public:
  string findLexSmallestString(string s, int a, int b) {
    int n = s.size();
    string ans = s;
    for (int i = 0; i < n; ++i) {
      s = s.substr(n - b) + s.substr(0, n - b);
      for (int j = 0; j < 10; ++j) {
        for (int k = 1; k < n; k += 2) {
          s[k] = (s[k] - '0' + a) % 10 + '0';
        }
        if (b & 1) {
          for (int p = 0; p < 10; ++p) {
            for (int k = 0; k < n; k += 2) {
              s[k] = (s[k] - '0' + a) % 10 + '0';
            }
            ans = min(ans, s);
          }
        } else {
          ans = min(ans, s);
        }
      }
    }
    return ans;
  }
};
func findLexSmallestString(s string, a int, b int) string {
  n := len(s)
  ans := s
  for _ = range s {
    s = s[n-b:] + s[:n-b]
    cs := []byte(s)
    for j := 0; j < 10; j++ {
      for k := 1; k < n; k += 2 {
        cs[k] = byte((int(cs[k]-'0')+a)%10 + '0')
      }
      if b&1 == 1 {
        for p := 0; p < 10; p++ {
          for k := 0; k < n; k += 2 {
            cs[k] = byte((int(cs[k]-'0')+a)%10 + '0')
          }
          s = string(cs)
          if ans > s {
            ans = s
          }
        }
      } else {
        s = string(cs)
        if ans > s {
          ans = s
        }
      }
    }
  }
  return ans
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文