LeetCode 148.排序链表 题目链接
在 O(n log n) 时间复杂度和常数级空间复杂度下,对链表进行排序。
示例 1:
输入: 4->2->1->3
输出: 1->2->3->4
示例 2:
输入: -1->5->3->4->0
输出: -1->0->3->4->5
解题思路:我采用的是一种取巧的方式,定义了一条和链表等长的数组,将每个结点的 val 值存储在数组中,用快速排序法将数组排序后,再一一赋值给链表。
时间复杂度肯定是 O(nlogn) 但是空间复杂度就大了,因为定义了等长的数组,在链表过长的情况下很有可能找不到满足大小的内存块,可以尝试普遍采用的 归并排序方法,社区解答参考
代码如下,没有采用 C 语言 stdlib.h 库中的 qsort 方法而且使用了 三数中值快速排序法。(因为 qsort 适应不同大小的数据,增加了程序的时间复杂度)
#include <malloc.h>
void insertSort(int *nums, int n)
{
//int *temps = (int *)malloc(sizeof(int )*n);
/*
把数据分成两个部分一部分是有序的另一部分是无序的,
每次把无序数列中的第一个数插入到有序数列中按顺序排列的位置
*/
int j = 0, i = 0;
for (; i < n - 1; i++)
{
int value = *(nums + i + 1);
for (j = i; j >= 0; )
{
if (*(nums + j) > value)
{
*(nums + j + 1) = *(nums + j);
j--;
}
else
break;
}
*(nums + j + 1) = value;
}
}
void swap(int *a, int *b)
{
int c;
c = *a;
*a = *b;
*b = c;
}
int median3(int a[], int left, int right) //获得枢纽元,使用三数中值法
{
int center = (left + right) / 2;
if (a[left]>a[center])
swap(&a[left], &a[center]);
if (a[left]>a[right])
swap(&a[left], &a[right]);
if (a[center]>a[right])
swap(&a[center], &a[right]);
swap(&a[center], &a[right - 1]); //将枢纽元放到数组最后
return a[right - 1];
}
void Qsort(int a[], int left, int right)
{
int i, j;
int pivot;
if ((left + 3) <= right)
{
pivot = median3(a, left, right);
i = left, j = right - 1;
for (;;)
{
while (a[++i]<pivot) {} //因为第一次是a[i]小于pivot,a[j]是大于pivot,所以用++i
while (a[--j]>pivot) {}
if (i<j)
swap(&a[i], &a[j]); //出现等于的情况,交换,平均分配到子数组中
else
break;
}
swap(&a[i], &a[right - 1]);
Qsort(a, left, i - 1); //在i的位置之前,所有的元素都小于它,在i之后,所有的元素都大于它,所以A[i]的位置不需要变
Qsort(a, i + 1, right);
}
else //当数组很小的时候,只做插入排序,从而退出递归,不需要等到数组长度等于1的时候,因为对于小数组来说,插入排序好过快速排序
insertSort(a + left, right - left + 1); //插入排序例程在前面的文章中已经实现了
}
void quickSort(int a[], int length)
{
Qsort(a, 0, length - 1);
}
int* intersect(int* nums1, int nums1Size, int* nums2, int nums2Size, int* returnSize) {
int min = nums1Size<nums2Size ? nums1Size : nums2Size;
*returnSize = 0;
int *tempNums = (int *)malloc(min*sizeof(int));
if (min == nums1Size)
{
quickSort(nums1, nums1Size); quickSort(nums2, nums2Size);
int i = 0, k = 0;
while (i != min)
{
if (nums1[i] == nums2[k])
{
tempNums[*returnSize] = nums1[i];
i++; k++; (*returnSize)++;
//printf("%d ",*returnSize);
}
else if (nums1[i]>nums2[k])
k++;
else if (nums1[i] < nums2[k])
i++;
if (k == nums2Size)
break;
}
}
else
{
tempNums = intersect(nums2, nums2Size, nums1, nums1Size, returnSize);
}
return tempNums;
}
/// 题目限定时间复杂度为 O(nlogn) 或 O(n),采用快速排序。
/// 先定义一个和链表等长的数组,将每个链表的每个值都赋给数组
/// 对数组使用快速排序,再一一赋值给链表
struct ListNode* sortList(struct ListNode* head) {
int count = 0, i = 0;
struct ListNode* p = head;
//p = head->next;
while (p != NULL)
{
count++;
p = p->next;
}
if (count == 1 || count == 0)
return head;
int *vals = (int *)malloc(count*sizeof(int));
p = head;
while (p != NULL)
{
vals[i] = p->val;
i++;
p = p->next;
}
//qsort(vals, count, sizeof(int), cmp);
quickSort(vals, count);
p = head; i = 0;
while (p != NULL)
{
p->val = vals[i];
i++;
p = p->next;
}
return head;
}