diff --git a/solution/1800-1899/1850.Minimum Adjacent Swaps to Reach the Kth Smallest Number/README.md b/solution/1800-1899/1850.Minimum Adjacent Swaps to Reach the Kth Smallest Number/README.md index 4e1748f6f2f94..9ca361dfbcbb6 100644 --- a/solution/1800-1899/1850.Minimum Adjacent Swaps to Reach the Kth Smallest Number/README.md +++ b/solution/1800-1899/1850.Minimum Adjacent Swaps to Reach the Kth Smallest Number/README.md @@ -69,6 +69,32 @@ +**方法一:求下一个排列 + 逆序对** + +我们可以调用 $k$ 次 `next_permutation` 函数,得到第 $k$ 个最小妙数 $s$。 + +接下来,我们只需要计算 $num$ 需要经过多少次交换才能变成 $s$ 即可。 + +我们先考虑一个简单的情况,即 $num$ 中的数字都不相同。在这种情况下,我们可以直接把 $num$ 中的数字字符映射为下标。例如 $num$ 等于 `"54893"`,而 $s$ 等于 `"98345"`。我们将 $num$ 中的每个数字映射为下标,即: + +$$ +\begin{aligned} +num[0] &= 5 &\rightarrow& \quad 0 \\ +num[1] &= 4 &\rightarrow& \quad 1 \\ +num[2] &= 8 &\rightarrow& \quad 2 \\ +num[3] &= 9 &\rightarrow& \quad 3 \\ +num[4] &= 3 &\rightarrow& \quad 4 \\ +\end{aligned} +$$ + +那么 $s$ 中的每个数字映射为下标,就是 `"32410"`。这样,将 $num$ 变成 $s$ 所需要的交换次数,就等于 $s$ 映射后的下标数组的逆序对数。 + +如果 $num$ 中存在相同的数字,那么我们可以使用一个数组 $d$ 来记录每个数字出现的下标,其中 $d[i]$ 表示数字 $i$ 出现的下标列表。为了使得交换次数尽可能少,在将 $s$ 映射为下标数组时,我们只需要按顺序贪心地选择 $d$ 中对应数字的下标即可。 + +最后,我们可以直接使用双重循环来计算逆序对数,也可以使用树状数组来优化。 + +时间复杂度 $O(n \times (k + n))$,空间复杂度 $O(n)$。其中 $n$ 是 $num$ 的长度。 + ### **Python3** @@ -76,7 +102,37 @@ ```python - +class Solution: + def getMinSwaps(self, num: str, k: int) -> int: + def next_permutation(nums: List[str]) -> bool: + n = len(nums) + i = n - 2 + while i >= 0 and nums[i] >= nums[i + 1]: + i -= 1 + if i < 0: + return False + j = n - 1 + while j >= 0 and nums[j] <= nums[i]: + j -= 1 + nums[i], nums[j] = nums[j], nums[i] + nums[i + 1 : n] = nums[i + 1 : n][::-1] + return True + + s = list(num) + for _ in range(k): + next_permutation(s) + d = [[] for _ in range(10)] + idx = [0] * 10 + n = len(s) + for i, c in enumerate(num): + j = ord(c) - ord("0") + d[j].append(i) + arr = [0] * n + for i, c in enumerate(s): + j = ord(c) - ord("0") + arr[i] = d[j][idx[j]] + idx[j] += 1 + return sum(arr[j] > arr[i] for i in range(n) for j in range(i)) ``` ### **Java** @@ -84,7 +140,195 @@ ```java +class Solution { + public int getMinSwaps(String num, int k) { + char[] s = num.toCharArray(); + for (int i = 0; i < k; ++i) { + nextPermutation(s); + } + List[] d = new List[10]; + Arrays.setAll(d, i -> new ArrayList<>()); + int n = s.length; + for (int i = 0; i < n; ++i) { + d[num.charAt(i) - '0'].add(i); + } + int[] idx = new int[10]; + int[] arr = new int[n]; + for (int i = 0; i < n; ++i) { + arr[i] = d[s[i] - '0'].get(idx[s[i] - '0']++); + } + int ans = 0; + for (int i = 0; i < n; ++i) { + for (int j = 0; j < i; ++j) { + if (arr[j] > arr[i]) { + ++ans; + } + } + } + return ans; + } + + private boolean nextPermutation(char[] nums) { + int n = nums.length; + int i = n - 2; + while (i >= 0 && nums[i] >= nums[i + 1]) { + --i; + } + if (i < 0) { + return false; + } + int j = n - 1; + while (j >= 0 && nums[i] >= nums[j]) { + --j; + } + swap(nums, i++, j); + for (j = n - 1; i < j; ++i, --j) { + swap(nums, i, j); + } + return true; + } + + private void swap(char[] nums, int i, int j) { + char t = nums[i]; + nums[i] = nums[j]; + nums[j] = t; + } +} +``` + +### **C++** + +```cpp +class Solution { +public: + int getMinSwaps(string num, int k) { + string s = num; + for (int i = 0; i < k; ++i) { + next_permutation(begin(s), end(num)); + } + vector d[10]; + int n = num.size(); + for (int i = 0; i < n; ++i) { + d[num[i] - '0'].push_back(i); + } + int idx[10]{}; + vector arr(n); + for (int i = 0; i < n; ++i) { + arr[i] = d[s[i] - '0'][idx[s[i] - '0']++]; + } + int ans = 0; + for (int i = 0; i < n; ++i) { + for (int j = 0; j < i; ++j) { + if (arr[j] > arr[i]) { + ++ans; + } + } + } + return ans; + } +}; +``` + +### **Go** + +```go +func getMinSwaps(num string, k int) (ans int) { + s := []byte(num) + for ; k > 0; k-- { + nextPermutation(s) + } + d := [10][]int{} + for i, c := range num { + j := int(c - '0') + d[j] = append(d[j], i) + } + idx := [10]int{} + n := len(s) + arr := make([]int, n) + for i, c := range s { + j := int(c - '0') + arr[i] = d[j][idx[j]] + idx[j]++ + } + for i := 0; i < n; i++ { + for j := 0; j < i; j++ { + if arr[j] > arr[i] { + ans++ + } + } + } + return +} + +func nextPermutation(nums []byte) bool { + n := len(nums) + i := n - 2 + for i >= 0 && nums[i] >= nums[i+1] { + i-- + } + if i < 0 { + return false + } + j := n - 1 + for j >= 0 && nums[j] <= nums[i] { + j-- + } + nums[i], nums[j] = nums[j], nums[i] + for i, j = i+1, n-1; i < j; i, j = i+1, j-1 { + nums[i], nums[j] = nums[j], nums[i] + } + return true +} +``` +### **TypeScript** + +```ts +function getMinSwaps(num: string, k: number): number { + const n = num.length; + const s = num.split(''); + for (let i = 0; i < k; ++i) { + nextPermutation(s); + } + const d: number[][] = Array.from({ length: 10 }, () => []); + for (let i = 0; i < n; ++i) { + d[+num[i]].push(i); + } + const idx: number[] = Array(10).fill(0); + const arr: number[] = []; + for (let i = 0; i < n; ++i) { + arr.push(d[+s[i]][idx[+s[i]]++]); + } + let ans = 0; + for (let i = 0; i < n; ++i) { + for (let j = 0; j < i; ++j) { + if (arr[j] > arr[i]) { + ans++; + } + } + } + return ans; +} + +function nextPermutation(nums: string[]): boolean { + const n = nums.length; + let i = n - 2; + while (i >= 0 && nums[i] >= nums[i + 1]) { + i--; + } + if (i < 0) { + return false; + } + let j = n - 1; + while (j >= 0 && nums[i] >= nums[j]) { + j--; + } + [nums[i], nums[j]] = [nums[j], nums[i]]; + for (i = i + 1, j = n - 1; i < j; ++i, --j) { + [nums[i], nums[j]] = [nums[j], nums[i]]; + } + return true; +} ``` ### **...** diff --git a/solution/1800-1899/1850.Minimum Adjacent Swaps to Reach the Kth Smallest Number/README_EN.md b/solution/1800-1899/1850.Minimum Adjacent Swaps to Reach the Kth Smallest Number/README_EN.md index c028dedd18bc8..712c42d049db9 100644 --- a/solution/1800-1899/1850.Minimum Adjacent Swaps to Reach the Kth Smallest Number/README_EN.md +++ b/solution/1800-1899/1850.Minimum Adjacent Swaps to Reach the Kth Smallest Number/README_EN.md @@ -10,7 +10,6 @@
  • For example, when num = "5489355142": -
    • The 1st smallest wonderful integer is "5489355214".
    • The 2nd smallest wonderful integer is "5489355241".
    • @@ -18,7 +17,6 @@
    • The 4th smallest wonderful integer is "5489355421".
  • -

Return the minimum number of adjacent digit swaps that needs to be applied to num to reach the kth smallest wonderful integer.

@@ -68,18 +66,262 @@ ## Solutions +**Solution 1: Find Next Permutation + Inversion Pairs** + +We can call the `next_permutation` function $k$ times to get the $k$th smallest permutation $s$. + +Next, we just need to calculate how many swaps are needed for $num$ to become $s$. + +Let's first consider a simple situation where all the digits in $num$ are different. In this case, we can directly map the digit characters in $num$ to indices. For example, if $num$ is `"54893"` and $s$ is `"98345"`. We map each digit in $num$ to an index, that is: + +$$ +\begin{aligned} +num[0] &= 5 &\rightarrow& \quad 0 \\ +num[1] &= 4 &\rightarrow& \quad 1 \\ +num[2] &= 8 &\rightarrow& \quad 2 \\ +num[3] &= 9 &\rightarrow& \quad 3 \\ +num[4] &= 3 &\rightarrow& \quad 4 \\ +\end{aligned} +$$ + +Then, mapping each digit in $s$ to an index results in `"32410"`. In this way, the number of swaps needed to change $num$ to $s$ is equal to the number of inversion pairs in the index array after $s$ is mapped. + +If there are identical digits in $num$, we can use an array $d$ to record the indices where each digit appears, where $d[i]$ represents the list of indices where the digit $i$ appears. To minimize the number of swaps, when mapping $s$ to an index array, we only need to greedily select the index of the corresponding digit in $d$ in order. + +Finally, we can directly use a double loop to calculate the number of inversion pairs, or we can optimize it with a Binary Indexed Tree. + +The time complexity is $O(n \times (k + n))$, and the space complexity is $O(n)$. Where $n$ is the length of $num$. + ### **Python3** ```python +class Solution: + def getMinSwaps(self, num: str, k: int) -> int: + def next_permutation(nums: List[str]) -> bool: + n = len(nums) + i = n - 2 + while i >= 0 and nums[i] >= nums[i + 1]: + i -= 1 + if i < 0: + return False + j = n - 1 + while j >= 0 and nums[j] <= nums[i]: + j -= 1 + nums[i], nums[j] = nums[j], nums[i] + nums[i + 1 : n] = nums[i + 1 : n][::-1] + return True + s = list(num) + for _ in range(k): + next_permutation(s) + d = [[] for _ in range(10)] + idx = [0] * 10 + n = len(s) + for i, c in enumerate(num): + j = ord(c) - ord("0") + d[j].append(i) + arr = [0] * n + for i, c in enumerate(s): + j = ord(c) - ord("0") + arr[i] = d[j][idx[j]] + idx[j] += 1 + return sum(arr[j] > arr[i] for i in range(n) for j in range(i)) ``` ### **Java** ```java +class Solution { + public int getMinSwaps(String num, int k) { + char[] s = num.toCharArray(); + for (int i = 0; i < k; ++i) { + nextPermutation(s); + } + List[] d = new List[10]; + Arrays.setAll(d, i -> new ArrayList<>()); + int n = s.length; + for (int i = 0; i < n; ++i) { + d[num.charAt(i) - '0'].add(i); + } + int[] idx = new int[10]; + int[] arr = new int[n]; + for (int i = 0; i < n; ++i) { + arr[i] = d[s[i] - '0'].get(idx[s[i] - '0']++); + } + int ans = 0; + for (int i = 0; i < n; ++i) { + for (int j = 0; j < i; ++j) { + if (arr[j] > arr[i]) { + ++ans; + } + } + } + return ans; + } + + private boolean nextPermutation(char[] nums) { + int n = nums.length; + int i = n - 2; + while (i >= 0 && nums[i] >= nums[i + 1]) { + --i; + } + if (i < 0) { + return false; + } + int j = n - 1; + while (j >= 0 && nums[i] >= nums[j]) { + --j; + } + swap(nums, i++, j); + for (j = n - 1; i < j; ++i, --j) { + swap(nums, i, j); + } + return true; + } + + private void swap(char[] nums, int i, int j) { + char t = nums[i]; + nums[i] = nums[j]; + nums[j] = t; + } +} +``` + +### **C++** + +```cpp +class Solution { +public: + int getMinSwaps(string num, int k) { + string s = num; + for (int i = 0; i < k; ++i) { + next_permutation(begin(s), end(num)); + } + vector d[10]; + int n = num.size(); + for (int i = 0; i < n; ++i) { + d[num[i] - '0'].push_back(i); + } + int idx[10]{}; + vector arr(n); + for (int i = 0; i < n; ++i) { + arr[i] = d[s[i] - '0'][idx[s[i] - '0']++]; + } + int ans = 0; + for (int i = 0; i < n; ++i) { + for (int j = 0; j < i; ++j) { + if (arr[j] > arr[i]) { + ++ans; + } + } + } + return ans; + } +}; +``` + +### **Go** + +```go +func getMinSwaps(num string, k int) (ans int) { + s := []byte(num) + for ; k > 0; k-- { + nextPermutation(s) + } + d := [10][]int{} + for i, c := range num { + j := int(c - '0') + d[j] = append(d[j], i) + } + idx := [10]int{} + n := len(s) + arr := make([]int, n) + for i, c := range s { + j := int(c - '0') + arr[i] = d[j][idx[j]] + idx[j]++ + } + for i := 0; i < n; i++ { + for j := 0; j < i; j++ { + if arr[j] > arr[i] { + ans++ + } + } + } + return +} + +func nextPermutation(nums []byte) bool { + n := len(nums) + i := n - 2 + for i >= 0 && nums[i] >= nums[i+1] { + i-- + } + if i < 0 { + return false + } + j := n - 1 + for j >= 0 && nums[j] <= nums[i] { + j-- + } + nums[i], nums[j] = nums[j], nums[i] + for i, j = i+1, n-1; i < j; i, j = i+1, j-1 { + nums[i], nums[j] = nums[j], nums[i] + } + return true +} +``` + +### **TypeScript** + +```ts +function getMinSwaps(num: string, k: number): number { + const n = num.length; + const s = num.split(''); + for (let i = 0; i < k; ++i) { + nextPermutation(s); + } + const d: number[][] = Array.from({ length: 10 }, () => []); + for (let i = 0; i < n; ++i) { + d[+num[i]].push(i); + } + const idx: number[] = Array(10).fill(0); + const arr: number[] = []; + for (let i = 0; i < n; ++i) { + arr.push(d[+s[i]][idx[+s[i]]++]); + } + let ans = 0; + for (let i = 0; i < n; ++i) { + for (let j = 0; j < i; ++j) { + if (arr[j] > arr[i]) { + ans++; + } + } + } + return ans; +} +function nextPermutation(nums: string[]): boolean { + const n = nums.length; + let i = n - 2; + while (i >= 0 && nums[i] >= nums[i + 1]) { + i--; + } + if (i < 0) { + return false; + } + let j = n - 1; + while (j >= 0 && nums[i] >= nums[j]) { + j--; + } + [nums[i], nums[j]] = [nums[j], nums[i]]; + for (i = i + 1, j = n - 1; i < j; ++i, --j) { + [nums[i], nums[j]] = [nums[j], nums[i]]; + } + return true; +} ``` ### **...** diff --git a/solution/1800-1899/1850.Minimum Adjacent Swaps to Reach the Kth Smallest Number/Solution.cpp b/solution/1800-1899/1850.Minimum Adjacent Swaps to Reach the Kth Smallest Number/Solution.cpp new file mode 100644 index 0000000000000..25c90b2ec34f7 --- /dev/null +++ b/solution/1800-1899/1850.Minimum Adjacent Swaps to Reach the Kth Smallest Number/Solution.cpp @@ -0,0 +1,28 @@ +class Solution { +public: + int getMinSwaps(string num, int k) { + string s = num; + for (int i = 0; i < k; ++i) { + next_permutation(begin(s), end(num)); + } + vector d[10]; + int n = num.size(); + for (int i = 0; i < n; ++i) { + d[num[i] - '0'].push_back(i); + } + int idx[10]{}; + vector arr(n); + for (int i = 0; i < n; ++i) { + arr[i] = d[s[i] - '0'][idx[s[i] - '0']++]; + } + int ans = 0; + for (int i = 0; i < n; ++i) { + for (int j = 0; j < i; ++j) { + if (arr[j] > arr[i]) { + ++ans; + } + } + } + return ans; + } +}; \ No newline at end of file diff --git a/solution/1800-1899/1850.Minimum Adjacent Swaps to Reach the Kth Smallest Number/Solution.go b/solution/1800-1899/1850.Minimum Adjacent Swaps to Reach the Kth Smallest Number/Solution.go new file mode 100644 index 0000000000000..6513ca3afddd6 --- /dev/null +++ b/solution/1800-1899/1850.Minimum Adjacent Swaps to Reach the Kth Smallest Number/Solution.go @@ -0,0 +1,47 @@ +func getMinSwaps(num string, k int) (ans int) { + s := []byte(num) + for ; k > 0; k-- { + nextPermutation(s) + } + d := [10][]int{} + for i, c := range num { + j := int(c - '0') + d[j] = append(d[j], i) + } + idx := [10]int{} + n := len(s) + arr := make([]int, n) + for i, c := range s { + j := int(c - '0') + arr[i] = d[j][idx[j]] + idx[j]++ + } + for i := 0; i < n; i++ { + for j := 0; j < i; j++ { + if arr[j] > arr[i] { + ans++ + } + } + } + return +} + +func nextPermutation(nums []byte) bool { + n := len(nums) + i := n - 2 + for i >= 0 && nums[i] >= nums[i+1] { + i-- + } + if i < 0 { + return false + } + j := n - 1 + for j >= 0 && nums[j] <= nums[i] { + j-- + } + nums[i], nums[j] = nums[j], nums[i] + for i, j = i+1, n-1; i < j; i, j = i+1, j-1 { + nums[i], nums[j] = nums[j], nums[i] + } + return true +} \ No newline at end of file diff --git a/solution/1800-1899/1850.Minimum Adjacent Swaps to Reach the Kth Smallest Number/Solution.java b/solution/1800-1899/1850.Minimum Adjacent Swaps to Reach the Kth Smallest Number/Solution.java new file mode 100644 index 0000000000000..fbec106f34d7e --- /dev/null +++ b/solution/1800-1899/1850.Minimum Adjacent Swaps to Reach the Kth Smallest Number/Solution.java @@ -0,0 +1,54 @@ +class Solution { + public int getMinSwaps(String num, int k) { + char[] s = num.toCharArray(); + for (int i = 0; i < k; ++i) { + nextPermutation(s); + } + List[] d = new List[10]; + Arrays.setAll(d, i -> new ArrayList<>()); + int n = s.length; + for (int i = 0; i < n; ++i) { + d[num.charAt(i) - '0'].add(i); + } + int[] idx = new int[10]; + int[] arr = new int[n]; + for (int i = 0; i < n; ++i) { + arr[i] = d[s[i] - '0'].get(idx[s[i] - '0']++); + } + int ans = 0; + for (int i = 0; i < n; ++i) { + for (int j = 0; j < i; ++j) { + if (arr[j] > arr[i]) { + ++ans; + } + } + } + return ans; + } + + private boolean nextPermutation(char[] nums) { + int n = nums.length; + int i = n - 2; + while (i >= 0 && nums[i] >= nums[i + 1]) { + --i; + } + if (i < 0) { + return false; + } + int j = n - 1; + while (j >= 0 && nums[i] >= nums[j]) { + --j; + } + swap(nums, i++, j); + for (j = n - 1; i < j; ++i, --j) { + swap(nums, i, j); + } + return true; + } + + private void swap(char[] nums, int i, int j) { + char t = nums[i]; + nums[i] = nums[j]; + nums[j] = t; + } +} \ No newline at end of file diff --git a/solution/1800-1899/1850.Minimum Adjacent Swaps to Reach the Kth Smallest Number/Solution.py b/solution/1800-1899/1850.Minimum Adjacent Swaps to Reach the Kth Smallest Number/Solution.py new file mode 100644 index 0000000000000..ac0c38688734a --- /dev/null +++ b/solution/1800-1899/1850.Minimum Adjacent Swaps to Reach the Kth Smallest Number/Solution.py @@ -0,0 +1,31 @@ +class Solution: + def getMinSwaps(self, num: str, k: int) -> int: + def next_permutation(nums: List[str]) -> bool: + n = len(nums) + i = n - 2 + while i >= 0 and nums[i] >= nums[i + 1]: + i -= 1 + if i < 0: + return False + j = n - 1 + while j >= 0 and nums[j] <= nums[i]: + j -= 1 + nums[i], nums[j] = nums[j], nums[i] + nums[i + 1 : n] = nums[i + 1 : n][::-1] + return True + + s = list(num) + for _ in range(k): + next_permutation(s) + d = [[] for _ in range(10)] + idx = [0] * 10 + n = len(s) + for i, c in enumerate(num): + j = ord(c) - ord("0") + d[j].append(i) + arr = [0] * n + for i, c in enumerate(s): + j = ord(c) - ord("0") + arr[i] = d[j][idx[j]] + idx[j] += 1 + return sum(arr[j] > arr[i] for i in range(n) for j in range(i)) diff --git a/solution/1800-1899/1850.Minimum Adjacent Swaps to Reach the Kth Smallest Number/Solution.ts b/solution/1800-1899/1850.Minimum Adjacent Swaps to Reach the Kth Smallest Number/Solution.ts new file mode 100644 index 0000000000000..3ef2268d7859b --- /dev/null +++ b/solution/1800-1899/1850.Minimum Adjacent Swaps to Reach the Kth Smallest Number/Solution.ts @@ -0,0 +1,45 @@ +function getMinSwaps(num: string, k: number): number { + const n = num.length; + const s = num.split(''); + for (let i = 0; i < k; ++i) { + nextPermutation(s); + } + const d: number[][] = Array.from({ length: 10 }, () => []); + for (let i = 0; i < n; ++i) { + d[+num[i]].push(i); + } + const idx: number[] = Array(10).fill(0); + const arr: number[] = []; + for (let i = 0; i < n; ++i) { + arr.push(d[+s[i]][idx[+s[i]]++]); + } + let ans = 0; + for (let i = 0; i < n; ++i) { + for (let j = 0; j < i; ++j) { + if (arr[j] > arr[i]) { + ans++; + } + } + } + return ans; +} + +function nextPermutation(nums: string[]): boolean { + const n = nums.length; + let i = n - 2; + while (i >= 0 && nums[i] >= nums[i + 1]) { + i--; + } + if (i < 0) { + return false; + } + let j = n - 1; + while (j >= 0 && nums[i] >= nums[j]) { + j--; + } + [nums[i], nums[j]] = [nums[j], nums[i]]; + for (i = i + 1, j = n - 1; i < j; ++i, --j) { + [nums[i], nums[j]] = [nums[j], nums[i]]; + } + return true; +}