煎饼排序
第一步找剩余数组里的最大值,然后从头到这里翻转一次,这样最大值就到了开头,再把开头从当前结尾翻转一次,就把当前的最大值翻转到了最后
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的逆序对就消失了,所以相邻元素只会减少一个(交换的条件是前面元素比后面大,即交换时前面元素必定比后面元素大,即交换时就是逆序对),最后排序完后数组有序,逆序对都没了,那就是已经把所有逆序对都计上了
最多K次相邻交换
假设前i个是有序的,从第i个开始,往后k个找到最小的,然后和第i+1位交换(冒泡交换),共需要J-1次交换,那么此时还剩下k-j+1次交换次数,前i+1有序
递归解决,记录开始下标与剩余交换次数,直到下标到顶或者交换次数为0