第一步找剩余数组里的最大值,然后从头到这里翻转一次,这样最大值就到了开头,再把开头从当前结尾翻转一次,就把当前的最大值翻转到了最后
- class Solution {
- public:
- vector<int> pancakeSort(vector<int>& arr)
- {
- /*一种类选择排序的思路
- 我们有一种方法可以把当前数组最大元素放到数组结尾
- 假设当前数组长度为n 设最大元素的下标为index
- 如果它的下标就在n - 1 那就不用翻转了 它已经处于正确位置了
- 首先翻转index + 1 然后这个元素就会到首位
- 然后翻转n 就是整个数组翻转一下 这个元素就会到末尾
- 因此每次摆放玩最大元素就让数组长度减1,接着操作
- 直到数组长度为1为止
- 这样总共最多会翻转2 * (arr.length - 1)次 是符合题意的*/
- vector<int> ret;
- for (int n = arr.size(); n > 1; --n)
- {
- int index = max_element(arr.begin(), arr.begin() + n) - arr.begin();
- if (index == n - 1) continue;
- reverse(arr.begin(), arr.begin() + index + 1);
- reverse(arr.begin(), arr.begin() + n);
- ret.push_back(index + 1);
- ret.push_back(n);
- }
- return ret;
- }
- };
D.2*(N-2)+1
每次都选一个基元,然后有一个左指针和一个右指针,完成两个目的,一个是固定基元的最终实际位置,另一个是说,让其最终位置之前的元素都比它小,其之后的元素都比它大
如果左指针向后遍历,直到遇到第一个比基元大的;右指针向前遍历,直到遇到第一个比基元小的;都停止时,进行交换,然后重复这一过程,直到左指针和右指针指向同一个元素,这时就是终点,让其和基元交换,就是基元的最终位置
- void quick_sort(int num[], int low, int high )
- {
- int i,j,temp;
- int tmp;
-
- i = low;
- j = high;
- tmp = num[low]; //任命为中间分界线,左边比他小,右边比他大,通常第一个元素是基准数
-
- if(i > j) //如果下标i大于下标j,函数结束运行
- {
- return;
- }
-
- while(i != j)
- {
- while(num[j] >= tmp && j > i)
- {
- j--;
- }
-
- while(num[i] <= tmp && j > i)
- {
- i++;
- }
-
- if(j > i)
- {
- temp = num[j];
- num[j] = num[i];
- num[i] = temp;
- }
- }
-
- num[low] = num[i];
- num[i] = tmp;
-
- quick_sort(num,low,i-1);
- quick_sort(num,i+1,high);
- }
-
从头开始遍历,如果当前元素比后一个元素大,就交换其位置,如果说遇到了最大值,那么每次交换后,都必定比后一个元素大,所以就一定会“冒泡”到此时数组的最后一个位置,由此就是每次都会使当前数组里的最大元素冒泡到对应位置
对于相邻的两个元素AB交换位置,不影响其前后所有元素的情况,也就是说只会影响这两个元素之间的关系,A和B后面的元素能组成逆序对时,AB交换后,A依然能和B后面的元素组成逆序对,如果AB构成逆序对,那么交换后AB的逆序对就消失了,所以相邻元素只会减少一个(交换的条件是前面元素比后面大,即交换时前面元素必定比后面元素大,即交换时就是逆序对),最后排序完后数组有序,逆序对都没了,那就是已经把所有逆序对都计上了
假设前i个是有序的,从第i个开始,往后k个找到最小的,然后和第i+1位交换(冒泡交换),共需要J-1次交换,那么此时还剩下k-j+1次交换次数,前i+1有序
递归解决,记录开始下标与剩余交换次数,直到下标到顶或者交换次数为0