新农上路
- 积分
- 98
- 大米
- 颗
- 鳄梨
- 个
- 水井
- 尺
- 蓝莓
- 颗
- 萝卜
- 根
- 小米
- 粒
- 学分
- 个
- 注册时间
- 2015-3-31
- 最后登录
- 1970-1-1
|
本帖最后由 littleric 于 2020-11-9 03:32 编辑
其实 我觉得1313 这个 不算是corner case 呀 。
其实这道题的核心思想是,怎么样可以变小,但是变得没那么小。所以这就决定了你做交换的时候保证1. 尽量对高位的数字不要有影响 2. 对有影响的低位数字消减的最小。
比如 [1,9,4,6,7],我们的思路应该是从后往前搜索,比如我在 6 这个位置,我一定是要向后搜索,找一个比6小,但是在比6小的情况下最大的那个,相当于 矮子里面挑高个,这样才可以保证
1. 换了 6之后对前面高位的数字没有影响
2. 交换之后的低位数字是我能凑到的最大的数字
满足这两点就可以保证得到的数组组成的数字一定是比原来的小,但是是小的里面最大的那个。当然在这个6 的例子里面是没有找到合适的交换数字。
但是换成9的话就不一样了,明显在后面有4,6,7比9小,但是明显7最大,那理所应当就是9和7交换变成 [1,7,4,6,9]
基于以上两点一个O(N^2) 的解法是
- public int[] prevPermOpt1(int[] A) {
- if (A.length == 1 || A.length == 0) {
- return A;
- } else { //从后往前搜索哦
- for (int i = A.length-1; i >= 0; i--) {
- // 比当前小,但是是小的里面最大的那个value
- int tempMax = -1;
- //value 的index,方便我之后交换
- int index = -1;
- for (int j = A.length-1; j > i; j--) {
- //第二重循环,找i之后的数字,如果比i指向的小,而且比当前以及得到的最大值还要大,这个就是合适的candidate
- if (A[j] < A[i] && A[j] >= tempMax) {
- tempMax = A[j];
- index = j;
- }
- }[/i]
- [i] //只要找到了一个合适的,这个肯定是最终答案,
- if (tempMax != -1) {
- swap(i, index , A);
- return A;
- }
- }
- return A;
- }
- }
- private void swap(int i, int j, int[] A) {
- int temp = A[i];
- A[i] = A[j];
- A[j] = temp;
- }
复制代码
所以 3113 也是同样思路。 你在最后一个3的时候,后面没有数字可以交换 ,忽略它。两个1后面都没有比他小的,忽略。到第一个3的时候,你从后找,找到一个1比他小,而且1是能找到比第一个3小的最大值了。交换就得出 1313
这个是AC答案而且速度是100%。我暂时没想到O(N)的解法,不过关键在于怎么快速找到比当前index的数字小,但是是小的里面最大的这样一个数据结构。[/i][/i][/i]
|
|