鉴于字符串str和一个整数的K形式的数量,任务是找到可以进行最多K个连续掉期交易后形成的最小整数。
The consecutive swaps mean at one swap the character at index i can be swapped with character at index i – 1 or i + 1.
例子:
Input: str = “76921”, K = 3
Output: 27691
Explanation:
27691 is the lexicographical smallest possible number.
Input: str = “9438957234785635408”, K = 23
Output: 0345989723478563548
Explanation:
0345989723478563548 is the lexicographical smallest possible number.
天真的方法:最简单的想法是生成给定字符串的所有可能排列,并检查哪个词典上最小的字符串是否满足最多K个交换的条件。打印该字符串。
时间复杂度: O(N!),其中N是给定字符串的长度。
辅助空间: O(1)
更好的方法:更好的方法是使用贪婪方法。步骤如下:
- 如果给定数字中存在前导零,则将其删除。
- 当K较小时从字符串str [考虑str [k]中选择最小的元素,否则为N ]。
- 将所有这些元素右移1个位置后,将最小的元素放置在第0个位置。
- 在上述步骤中,从K减去掉期数。
- 如果仍然使K> 0,则从下一个起始位置(即str [2,…N])开始执行相同的过程,然后将其放置到第一个位置。
- 因此,我们继续应用相同的过程,直到K变为0为止。
时间复杂度: O(N 2 ),其中N是给定字符串的长度。
辅助空间: O(1)
高效的方法:这个想法是使用Segment树和Hashing 。步骤如下:
- 如果给定数字中存在前导零,则将其删除。
- 将数字的原始位置存储在Map中,并找到最适合每个移位小于等于K的索引的数字。
- 使用地图查找数字的原始位置。
- 找到与当前位置正对且已移位的位数,为此,在段树中将其位置从[0…N-1]标记出来。
- 段树的每个节点都包含已移位的位置数。现在的任务是查找在[current_index,N-1]范围内移动了多少个位置,因为这只会影响原始位置。
- 要移动的新位置将是(original_position + number_of_right – element_shifted – i),即元素的原始位置被添加到刚移动的段树中。
下面是上述方法的程序:
C++
// C++ program for the above approach
#include
using namespace std;
// Function to mark the pos as 1 that
// are shifted in string in Segtree node
void segAdd(vector& seg, int start,
int end, int pos, int curr)
{
// Out of Range
if (pos < start or pos > end)
return;
// Check if we reach the positon
if (start == end) {
seg[curr] = 1;
return;
}
// Initialize the mid
int mid = (start + end) / 2;
// Recursion call
segAdd(seg, start, mid, pos,
2 * curr + 1);
segAdd(seg, mid + 1, end, pos,
2 * curr + 2);
// Every node contains no of
// marked postion that are
// shifted in a range
seg[curr] = seg[2 * curr + 1]
+ seg[2 * curr + 2];
return;
}
// Function to find the number of
// elements which got shifted
int segFind(
vector& seg, int pos_start,
int pos_end, int start, int end,
int curr)
{
// Return 0 is the end position is
// less than start or the start
// position is greater than end
if (pos_end < start
or pos_start > end)
return 0;
if (pos_start <= start
and pos_end >= end)
return seg[curr];
// Initialize the mid
int mid = (start + end) / 2;
// Recursion call
int left = segFind(
seg, pos_start, pos_end,
start, mid, 2 * curr + 1);
int rigt = segFind(
seg, pos_start, pos_end,
mid + 1, end, 2 * curr + 2);
// Return the result
return left + rigt;
}
// Function to remove leading zeros
// from the given string str
string removeLeadingZeros(string str)
{
int i = 0;
// To store the resultant string
string ans = "";
for (; i < str[i]; i++) {
// If Initial character is 0,
// then remove it
if (str[i] == '0') {
i++;
}
// Else break
else {
break;
}
}
ans = str.substr(i - 1,
str.length());
// Return the updated string
return ans;
}
// Function to find the lexiographically
// smallest integer
string findMinimumInteger(
string arr, int k)
{
// To remove leading zeros
arr = removeLeadingZeros(arr);
int n = arr.size();
// Segment tree vector
vector seg(
(2 * (int)pow(
2,
(int)(ceil(log2(n))))
- 1),
0);
// Hash to find the original
// position of the digit
unordered_map > m;
for (int i = 0; i < n; i++) {
m[arr[i] - '0'].push_back(i);
}
// Resultant string variable
string res = "";
for (int i = 0; i < n; i++) {
// Place a digit from
// 0-9 which fit best
for (int digit = 0;
digit <= 9; digit++) {
if (m[digit].size() != 0) {
int original_pos
= m[digit].front();
// Find the number of
// right elements that
// are shifted from
// current element
int shift
= segFind(
seg, original_pos,
n - 1, 0, n - 1, 0);
// Mark the new position
int new_pos = original_pos
+ shift
- i;
if (new_pos <= k) {
k -= new_pos;
// Add the original postion of
// the element which got shifted
segAdd(seg, 0, n - 1,
original_pos, 0);
res.push_back('0' + digit);
m[digit].pop_front();
break;
}
}
}
}
// Return the result
return res;
}
// Driver Code
int main()
{
// Given string
string s = "9438957234785635408";
// Given K swaps
int k = 23;
// Function Call
cout << findMinimumInteger(s, k)
<< endl;
}
0345989723478563548
时间复杂度: O(N * log N),其中N是字符串的长度。
辅助空间: O(N)