今天学习到的内容是八大排序
八大排序思想简述:
冒泡排序
每次比较相邻的两个数,让最大的数右移(或者最小的数)
选择排序
遍历每个元素,让其插入前面的有序区间,要求插入后仍然有序,如果按升序,也就是将比插入元素大的元素右移,直到该位置左边比插入元素小右边比插入元素大,就在该位置插入。
插入排序
每次都选择数组中最小的与数组第一个元素交换,第二次就是次最小的与第二个元素交换,以此类推。
希尔排序
先将元素分组,假设有八个元素,那么以元素个数的一半为步长,例如:将下标 0,4分为一组,1,5,分为一组,对每组元素执行插入排序,排好序之后,步长减半,例如:将0,2,4,6,分为一组,再次执行插入排序,直到步长为1,执行最后全部元素为一组的插入排序。
归并排序
先利用递归每次将数组分为两组,最后递归到两个元素,就进行归并排序,先把这两个元素拷贝到两个数组,然后比较大小将小的先放回原数组,再将大的放回原数组,就完成了归并,然后再将两个有序的数组进行归并,直到最后对大数组进行归并,就排好序了。
快速排序
每次选取区间第一个元素为pivot标准值,然后用两个指针遍历,一个从left一个right,先看如果right指向的值大于pivot则right–,直到right指向的值小于pivot,将right指向的元素赋值给left指向的位置,然后移动left,left不断++找到一个大于pivot的值然后赋值给right,再次开始移动right,直到最后right==left,这个位置就是pivot的位置,将pivot放到这里,然后再次对pivot左边进行同样的操作,右边进行同样的操作,直到该区间只有一个值。
计数排序
只适合于数组元素的大小较小的数组,创建一个哈希表,将元素映射到哈希表中,然后遍历哈希表取出数组元素即可。
基数排序
创建一个0~9的哈希,第一次迭代将按照个位将数组映射到哈希表中,然后按照升序取出哈希表中的数组,然后再按照十位将数组映射到哈希表中,再就是百位,千位,直到最高位元素的位数,最后升序取出的元素就是已经排好序的了。
今日题解
排序后直接最大-1乘上次大-1,返回即可
int cmp(const void* str1,const void* str2)
{
return *(int*)str1 - *(int*)str2;
}
int maxProduct(int* nums, int numsSize){
qsort(nums,numsSize,sizeof(int),cmp);
return (nums[numsSize-1]-1)*(nums[numsSize-2]-1);
}
思路:根据题干,按照频率升序排序,如果频率相同则按照数值大小降序排列,定义一个哈希表,记录数字出现的频率,然后使用哈希表的频率用qsort对数组排序,如果频率相同,就用数值进行降序排序。
注意:这里数字范围为-100到100,所以要在映射哈希表的时候加上一个偏移量,我加的是100,这样下标范围就是0–200,哈希表大小就是201;
int hash[201];
int cmp(const void*str1,const void* str2)
{
if(hash[*(int*)str1+100] - hash[*(int*)str2+100]==0)//频率相同,用数值排序
{
return -(*(int*)str1 - *(int*)str2);
}
return hash[*(int*)str1+100] - hash[*(int*)str2+100];//调用哈希表中的频率进行排序。
}
int* frequencySort(int* nums, int numsSize, int* returnSize){
//int* ans = (int*)malloc(sizoef(int)*numsSize);
*returnSize = numsSize;
memset(hash,0,sizeof(int)*201);
for(int i = 0;i<numsSize;i++)
{
++hash[nums[i]+100];//加上一个偏移量
}
qsort(nums,numsSize,sizeof(int),cmp);//按照频率升序
return nums;
}
思路:定义一个count记录数字出现的次数,定义一个count_num记录出现的数字是哪个,然后遍历数组,如果arr[i] = = count_num 那么计数器就++,如果不相等就更新count_num 并且计数器归1(因为这个数出现了一次)循环过程中判断,如果count大于了arrsize/4就跳出循环返回count_num;
int findSpecialInteger(int* arr, int arrSize){
int count = 0;
int count_num = arr[0];
for(int i =0;i<arrSize;i++)
{
if(count>(arrSize/4))
{
break;
}
if(count_num==arr[i])
{
count++;
}
else
{
count_num = arr[i];
count = 1;
}
}
return count_num;
}
二位数组按照第一列元素排序的需要特别注意,传过去的是一个模拟的二维数组,首元素地址,是一维数组的地址,每个元素是(int*)特别是设计cmp函数设计,因为str1,是一级指针的地址,所以用二级指针接受,然后解引用拿到这个一维数组的地址,再次解引用访问数组元素。
思路:就是先创建一个start数组,二维数组,第一个位置存放start i 数据,第二个位置,存放下标。然后对它进行排序,然后遍历intervals数组,用end i 在start里面进行二分查找,找到>=end i 的最小下标,然后将该下标保存,存放到ans数组中。
int cmp(const void** str1,const void** str2)
{
return (*(int**)str1)[0] - (*(int**)str2)[0];
}
int* findRightInterval(int** intervals, int intervalsSize, int* intervalsColSize, int* returnSize){
int** start_i = (int**)malloc(sizeof(int*)*intervalsSize);
for(int i =0;i<intervalsSize;i++)
{
start_i[i] = (int*)malloc(sizeof(int)*2);
}
for(int i =0;i<intervalsSize;i++)
{
start_i[i][0] = intervals[i][0];//存数据
start_i[i][1] = i;//存下标
}
int* ans = (int*)malloc(sizeof(int)*intervalsSize);
*returnSize = 0;
qsort(start_i,intervalsSize,sizeof(int*),cmp);
for(int i =0;i<intervalsSize;i++)
{
int left = 0;
int right = intervalsSize-1;
int min = -1;
while(left<=right)
{
int mid = (left+right)>>1;
if(start_i[mid][0]>=intervals[i][1])
{
min = start_i[mid][1];
right = mid-1;
}
else
{
left = mid+1;
}
}
ans[*returnSize] = min;
(*returnSize)++;
}
return ans;
}
宫水三叶的莫队思想解法:优雅的暴力:思路同前面,就是将开始的数据和下标存放到start数组,end的数组和下标存放到end数组里面。然后对这两个二维数组按照数据大小排序,然后用双指针遍历end数组的数值位,找到>=end_i[i][0] 的start_i的数值,然后将其数值,赋值给ans数组,如果找不到>=end_i[i][0]的start_i的数值,就给ans赋值为-1。最后返回即可。
/**
* Note: The returned array must be malloced, assume caller calls free().
*/
int cmp(const void** str1,const void** str2)
{
return (*(int**)str1)[0] - (*(int**)str2)[0];
}
int* findRightInterval(int** intervals, int intervalsSize, int* intervalsColSize, int* returnSize){
int** start_i = (int**)malloc(sizeof(int*)*intervalsSize);
int** end_i = (int**)malloc(sizeof(int*)*intervalsSize);
int* ans = (int*)malloc(sizeof(int)*intervalsSize);
*returnSize = intervalsSize;
int i = 0;
int j = 0;
for(i =0;i<intervalsSize;i++)
{
start_i[i] = (int*)malloc(sizeof(int)*2);
end_i[i] = (int*)malloc(sizeof(int)*2);
}
for(i =0;i<intervalsSize;i++)
{
start_i[i][0] = intervals[i][0];//存数据
start_i[i][1] = i;//存下标
end_i[i][0] = intervals[i][1];//存数据
end_i[i][1] = i;//存下标
}
qsort(start_i,intervalsSize,sizeof(int*),cmp);
qsort(end_i,intervalsSize,sizeof(int*),cmp);
i = 0;
j = 0;
for(i = 0;i<intervalsSize;i++)
{
while(j<intervalsSize && start_i[j][0] < end_i[i][0] )
{
j++;
}
if(j>=intervalsSize)
{
ans[end_i[i][1]] = -1;
}
else
{
ans[end_i[i][1]] = start_i[j][1];
}
}
return ans;
}