912. 排序数组 - 力扣(LeetCode)
这道题他会设置一个数据量特别特别大的案例,对于一般的算法是一定过不去的
1.冒泡排序---这种的时间复杂度是O(n*n),对于这道题是不可能过得去的
/**
* Note: The returned array must be malloced, assume caller calls free().
*/
int* sortArray(int* nums, int numsSize, int* returnSize)
{
//冒泡
for(int i=0;i<numsSize;i++)
{
for(int j=0;j<numsSize-i-1;j++)
{
//小到大
if(nums[j]>nums[j+1])
{
int tem=nums[j];
nums[j]=nums[j+1];
nums[j+1]=tem;
}
}
}
*returnSize=numsSize;
return nums;
}
2.选择排序---时间复杂的是O(n*n),也是不能过得去的
/**
* Note: The returned array must be malloced, assume caller calls free().
*/
int* sortArray(int* nums, int numsSize, int* returnSize)
{
//选择排序,遍历数组找到最小的数位置记录下来,然后与第i位进行交换
*returnSize=numsSize;
for(int i=0;i<numsSize;i++)
{
int n=i;//记录最小的元素的下角标
for(int j=i+1;j<numsSize;j++)
{
if(nums[j]<nums[n])
{
n=j;
}
}
//将第n位与第i为进行交换
int tem=nums[n];
nums[n]=nums[i];
nums[i]=tem;
}
return nums;
}
3.插入排序---时间复杂度O(n*n),也是不能过的去的
int* sortArray(int* nums, int numsSize, int* returnSize)
{
//插入排序:在已经排好序的数组中进行插入
*returnSize=numsSize;
for(int i=0;i<numsSize;i++)
{
//从此位置向前比
for(int j=i;j>0;j--)
{
if(nums[j]<nums[j-1])
{
int tem=nums[j];
nums[j]=nums[j-1];
nums[j-1]=tem;
}
else
break;
}
}
return nums;
}
4.希尔排序---插入排序的进阶,时间复杂度O(n^1.3),可以实现
int* sortArray(int* nums, int numsSize, int* returnSize)
{
//希尔排序---插入排序的进阶,可以减少查找次数,移动次数减少
*returnSize=numsSize;
int i,j,inc,key;
for(inc=numsSize/2;inc>0;inc/=2)
//inc表示每次分组中元素的个数,直到为0的时候才停止
{
for(i=inc;i<numsSize;i++)//从inc位置开始,后面的每一个都要进行排序
{
//key=nums[i];//记录这个位置的值
for(j=i;j>=inc&&nums[j]<nums[j-inc];j-=inc)//每次比较的时候都要用组与组之间进行对比,并且我们比较的值不能比第一组的值更靠前
//而且我们是从尾向前开始比较的
{
//nums[j]=nums[j-inc];//每次向前走一组的位置
key=nums[j];
nums[j]=nums[j-inc];
nums[j-inc]=key;
}
//nums[j]=key;
}
}
return nums;
}
5.快排---时间复杂度O(nlogn)
快排第一次移动的必须是右边的角标,因为现在我们是以左边的为比较的对象,所以开始的时候必须是右边的角标先动
void quicksort(int* nums,int left,int right)
{
if(left>=right)
return;
else
{
int mem_left=left;
int mem_right=right;//分别记录左角标,右角标
int com=nums[left];
int flag=1;//0移动左角标,1移动右角标
while(left<right)
{
if(flag==0)
{
//左角标动
if(nums[left]<=com)
{
left++;
}
else
{
//换位
nums[right]=nums[left];
right--;
flag=1;
}
}
else
{
//右角标动
if(nums[right]>=com)
{
right--;
}
else
{
//换位
nums[left]=nums[right];
left++;
flag=0;
}
}
}
nums[left]=com;
quicksort(nums,mem_left,left-1);
quicksort(nums,left+1,mem_right);
}
}
int* sortArray(int* nums, int numsSize, int* returnSize)
{
//快排
*returnSize=numsSize;
int left=0;
int right=numsSize-1;
quicksort(nums,left,right);
return nums;
}
我们的快排还是无法通过本题----因为我们每次排序选取的比较对象是首元素没有随机性,需要改进
void quicksort(int* nums,int left,int right)
{
if(left>=right)
return;
else
{
int mem_left=left;
int mem_right=right;//分别记录左角标,右角标
int tem=rand()%(right-left+1)+left;
//交换两个位置的值到最左边
int com=nums[tem];
nums[tem]=nums[left];
nums[left]=com;
int flag=1;//0移动左角标,1移动右角标
while(left<right)
{
if(flag==0)
{
//左角标动
if(nums[left]<=com)
{
left++;
}
else
{
//换位
nums[right]=nums[left];
right--;
flag=1;
}
}
else
{
//右角标动
if(nums[right]>=com)
{
right--;
}
else
{
//换位
nums[left]=nums[right];
left++;
flag=0;
}
}
}
nums[left]=com;
quicksort(nums,mem_left,left-1);
quicksort(nums,left+1,mem_right);
}
}
int* sortArray(int* nums, int numsSize, int* returnSize)
{
//快排
//生成随机种子
srand((unsigned int)time(NULL));
*returnSize=numsSize;
int left=0;
int right=numsSize-1;
quicksort(nums,left,right);
return nums;
}