今天是打卡的第36天,今天的难度一般般,赶紧写写复习考试了-.-知识点在:
《算法零基础100讲》(第36讲) 排序进阶 - 归并排序
c语言中常见的排序方式
划分中间位置为分割点,对分割后的元素进行排序,其中利用了选择排序的相对有序情况下时间复杂度较低的特性。
int a[maxn];
void MergeSort(int *nums, int l, int r) {
int i, mid, p, lp, rp;
int *tmp = (int *)malloc( (r-l+1) * sizeof(int) ); //辅助数组
if(l >= r) {
return ; //只有一个元素
}
mid = (l + r) >> 1; // 划分
MergeSort(nums, l, mid); // 排序右边
MergeSort(nums, mid+1, r); // 排序左边
p = 0; // 辅助数组指针
lp = l, rp = mid+1; // 指向左右两边的元素
while(lp <= mid || rp <= r) {
// 双指针判断
if(lp > mid) {
tmp[p++] = nums[rp++]; // 左部分插入完了
}else if(rp > r) {
tmp[p++] = nums[lp++]; // 右部分插入结束
}else {
if(nums[lp] <= nums[rp]) {
// 选择较小的插入
tmp[p++] = nums[lp++];
}else {
tmp[p++] = nums[rp++];
}
}
}
for(i = 0; i < r-l+1; ++i) {
nums[l+i] = tmp[i]; // 写回
}
free(tmp); // 释放空间
}
164. 最大间距
给定一个无序的数组,找出数组在排序之后,相邻元素之间最大的差值。
如果数组元素个数小于 2,则返回 0。
解题思路
先排序然后用max记录最大值 返回就好了?
int cmp(int *a, int *b){
return *b < *a;}//排序数组
int maximumGap(int* nums, int numsSize){
qsort(nums ,numsSize ,sizeof(int) ,cmp);//排序
int max = 0; //判断
for(int i = 1;i < numsSize;i++)
if(max < nums[i] - nums[i - 1]) max = nums[i] - nums[i - 1];//更新值
return max;
}
912. 排序数组
给你一个整数数组 nums,请你将该数组升序排列。
解题思路
直接排序就好了
int cmp(const void *a,const void *b){
return *(int *)a - *(int *)b;
}
int* sortArray(int* nums, int numsSize, int* returnSize){
qsort(nums,numsSize,sizeof(int),cmp);//排序
*returnSize = numsSize;//返回
return nums;
}
217. 存在重复元素
给定一个整数数组,判断是否存在重复元素。
如果存在一值在数组中出现至少两次,函数返回 true 。如果数组中每个元素都不相同,则返回 false 。。
解题思路
直接排序就好了,如果两个元素相同就返回false
int cmp(int *a,int *b){
return *a > *b;
}
bool containsDuplicate(int* nums, int numsSize){
qsort(nums,numsSize,sizeof(int),cmp);//排序
for(int i = 1;i < numsSize;i++) //验证
if(nums[i] == nums[i-1]) return true;
return false;
}
169. 多数元素
给定一个大小为 n 的数组,找到其中的多数元素。多数元素是指在数组中出现次数 大于 ⌊ n/2 ⌋ 的元素。
你可以假设数组是非空的,并且给定的数组总是存在多数元素。
解题思路
这个其实很有意思,假如 我用一个出现最多的元素和其它元素相消除,那么由于最多的元素是大于一半 的,最后剩下的一定是最多的元素。 基于这种思想我就可以写出来下面的代码。
int majorityElement(int* nums, int numsSize){
int maxnum = 0,maxtime = 0;
for(int i = 0;i < numsSize;i++){
if(maxtime == 0){
//选择此元素为最多元素
maxnum = nums[i];
maxtime++;
}
else if(nums[i] == maxnum) maxtime++;//增加计数
else maxtime--; //减少计数
}
return maxnum;
}
面试题 10.01. 合并排序的数组
给定两个排序后的数组 A 和 B,其中 A 的末端有足够的缓冲空间容纳 B。 编写一个方法,将 B 合并入 A 并排序。
初始化 A 和 B 的元素数量分别为 m 和 n。
解题思路
这个如果采用辅助元素啥的,都是浪费空间,最简单的就是从后往前进行二路归并排序。这样不会产生覆盖问题。
void merge(int* A, int ASize, int m, int* B, int BSize, int n){
int k = m + n -1, low = m - 1,high = n - 1; //k为最终数组指针
while(low != -1|| high != -1){
//A或B还有元素
if(low != -1 && high != -1) //A和B都有元素
if(A[low] < B[high]) A[k--] = B[high--];
else A[k--] = A[low --];
else if(low != -1) A[k--] = A[low--]; //将所有B插入
else A[k--] = B[high--]; //将所有A插入
}
}
148. 排序链表
给你链表的头结点 head ,请将其按 升序 排列并返回 排序后的链表 。
解题思路
我用一个数组把所有的节点存进去,然后排序,然后再链接起来0.0
bool sort(const struct ListNode **a,const struct ListNode **b){
struct ListNode *p = *a, *q = *b;
return p->val > q->val;
}
struct ListNode* sortList(struct ListNode* head){
if(!head) return head;
struct ListNode *a[50001];
int len = 0;
while(head){
//插入表中
a[len++] = head;
head = head->next;
}
qsort(a,len,sizeof(struct ListNode* ),sort);//对表内元素按照val大小排序
for(int i = 0;i<len - 1;++i){
//链接起来
a[i]->next =a[i+1];
//printf("%d",a[i]->val);
}
a[len -1]->next = 0; //最后的NULL
return a[0]; //返回第一个元素
}
其实这道题将里面的值交换的话 空间复杂度会低很多
最近实在是有些迷茫,还没完全走出来,但是还是会努力复习,完成这些计划,应该要好好规划一下人生了呢。