LeetCode148 排序链表

21 篇文章 0 订阅
11 篇文章 0 订阅

方法一 选择排序 时间复杂度O(N^2)空间复杂度O(1) 超时。。。

class Solution {
public:
	ListNode* sortList(ListNode* head) {
		ListNode* tail = NULL;
		ListNode* cur = head;
		ListNode* smallPre = NULL;
		ListNode* small = NULL;
		while (cur != NULL) {
			small = cur;
			smallPre = getSmallestPreNode(cur);
			if (smallPre != NULL) {
				small = smallPre->next;
				smallPre->next = small->next;
			}
			cur = cur == small ? cur->next : cur;
			if (tail != NULL) {
				tail->next = small;
			}
			else {
				head = small;
			}
			tail = small;

		}
		return head;


	}
	ListNode* getSmallestPreNode(ListNode* head) {
		ListNode* cur = head->next;
		ListNode* pre = head;
		ListNode* small = head;
		ListNode* smallPre = NULL;
		while (cur != NULL) {
			if (cur->val < small->val) {
				small = cur;
				smallPre = pre;
			}
			cur = cur->next;
			pre = pre->next;
		}

		return smallPre;
	}
};

虽然没有跑通,但是还有很多值得学习和思考的点

因为需要从链表中找到最小的值,那么就需要将最小节点取出以后,再将原链表连接起来。那么就需要找到最小点的前驱,来负责完成连接操作。那么此时又出现一直可能发生的情况,那就是未排序链表的第一个节点就是最小的,那么他的前驱就是NULL 所以我们在程序中应该把这种情况当做是初始条件,如果在寻找最小节点的过程中找到了最小节点和他的前驱,那么就可以更新最小值和前驱。如果没有找到,则前驱就是NULL,此时最小点就是当前节点cur,那么需要将未排序的链表部分的头节点修改为当前头节点也就是最小节点的后继。

方法二 归并排序 时间复杂度O(NlogN)空间复杂度O(N)

class Solution {
public:
	ListNode* sortList(ListNode* head) {
		if (head==NULL || head->next==NULL) return head;
		ListNode* fast = head;
		ListNode* slow = head;
		while (fast->next!=NULL&&fast->next->next!=NULL)
		{
			slow = slow->next;
			fast = fast->next->next;
		}
		fast = slow->next;
		slow->next = NULL;
		return merge(sortList(head), sortList(fast));
	}
	ListNode* merge(ListNode* head1,ListNode* head2) {
		ListNode dummyhead(0);
		ListNode* p = &dummyhead;
		while (head1 && head2) {
			if (head1->val < head2->val) {
				p->next = head1;
				p = head1;
				head1 = head1->next;
			}
			else {
				p->next = head2;
				p = head2;
				head2 = head2->next;
			}
		}
		p->next = head1 ? head1 : head2;
		return dummyhead.next;
	}
};

需要注意点就是使用的是递归的方法不断切分,那么就需要有递归基就是开始的当head或head的后继为空时,就可以返回。切链操作可以使链表不需要记录最后一个节点,将最后的节点置为空。

merge操作主要是使用了dummyhead节点,然后将两部分合并起来。当一个链表为空后,判断某个链表是否为空,将没有遍历完的链表接在后面,最后返回dummyhead的后继即可

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值