number-of-submatrices-that-sum-to-target
给你一个字符串 num 和一个整数 k 。其中,num 表示一个很大的整数,字符串中的每个字符依次对应整数上的各个数位 。
你可以交换这个整数相邻数位的数字 最多 k 次。
请你返回你能得到的最小整数,并以字符串形式返回。
- 我第一反应是冒泡排序,因为只能交换相邻元素。
- 敲完冒泡排序发现样例1过不去,手推了一会,发现是因为冒泡排序可能会在某一轮中断。
- 然后我想到了先贪心后冒泡排序,冒泡排序的交换次数$\sum_{i=n-1}^x i<k$(后来发现这个交换次数是错误的,这只是交换次数的上界),先找到满足不等式最大的$x$,贪心交换$k-\sum_{i=n-1}^x i$ 轮后再进行冒泡排序。
- 上面那个方案当然过不了样例5啦,比赛快结束的时候,想到了要在每一轮冒泡排序前,计算出该轮所需的交换次数,离AC很近了。
- 比赛结束前还是没做出来,后来看到其实就是活用一点冒泡排序这个题解,阔然开朗,只要每一轮的冒泡排序只考虑$k$满足的区间$[i,i+k]$即可,
- 代码:
class Solution
{
public:
string minInteger(string num, int k)
{
int n = num.size();
if (k > n * (n - 1) / 2)
{
sort(num.begin(), num.end());
return num;
}
for (int i = 0; i < n; i++)
{
int minx = num[i];
int idx = i;
for (int j = i + 1; j < n && j - i <= k; j++)
if (num[j] < minx)
{
minx = num[j];
idx = j;
}
for (int j = idx; j >= i + 1; j--)
{
swap(num[j], num[j - 1]);
--k;
}
}
return num;
}
};
以上解法是$O(n^2)$的,事实上这题有$O(n\log n)$的解法:贪心地填每一位数,用线段树/树状数组维护置换次数,坑待填~,可参考: