【面试准备 算法题】用快排的思路对单链表进行排序(不能进行值拷贝)

前言

最近面试碰到这个题目感觉很有意思,既考察二分/递归的思想,也考察链表的操作,尤其对于边界情况的处理需要细心

题目要求

struct LinkNode {
  LinkNode() : val(0), next(nullptr) { }
  LinkNode(int v) : val(v), next(nullptr) { }

  int val;
  LinkNode* next;
};
  1. 给定单链表进行排序(链表节点定义如上)
  2. 不能通过值拷贝来实现元素交换(必须通过修改next指针实现 元素位置排序 )

实现

#include <vector>
#include <iostream>

/**
 * LinkList Uitil Functions
 * 
 **/ 
// ========================================================================
struct LinkNode {
  LinkNode() : val(0), next(nullptr) { }
  LinkNode(int v) : val(v), next(nullptr) { }

  int val;
  LinkNode* next;
};

LinkNode* CreateLinkList(const std::vector<int>& nums) {
  LinkNode head;
  LinkNode* tmp = &head;

  for (const auto& num : nums) {
    tmp->next = new LinkNode(num);
    tmp = tmp->next;
  }

  return head.next;
}

void PrintLinkList(LinkNode* head) {
  while (head != nullptr) {
    std::cout << head->val << " ";
    head = head->next;
  }
  std::cout << std::endl;
}
// ========================================================================


// return <head, tail>;
std::pair<LinkNode*, LinkNode*> LinkSort(LinkNode* head, LinkNode* tail) {
  if (head == nullptr || head == tail ) return { head, tail };

  // first store it, in case be modfied
  auto tail_next = tail->next;

  // 1. Get mid node;
  int mid_val = head->val;

  // 2. Travel and split link list;
  LinkNode left_dummy;
  LinkNode right_dummy;

  LinkNode* left = &left_dummy;
  LinkNode* right = &right_dummy;

  auto tmp = head->next;

  while (tmp != tail_next) {
    if (tmp->val < mid_val) {
      left->next = tmp;
      left = left->next;
    } else {
      right->next = tmp;
      right = right->next;
    }
    tmp = tmp->next;
  }

  // 3. Recursive sort
  auto lpair = LinkSort(left_dummy.next, left);
  auto rpair = LinkSort(right_dummy.next, right);

  // 4. Merge sorted list;
  LinkNode* sorted_head = nullptr;
  LinkNode* sorted_tail = nullptr;

  if (lpair.first == nullptr) {
    sorted_head = head;
  } else {
    sorted_head = lpair.first;
    lpair.second->next = head;
  }

  if (rpair.first == nullptr) {
    head->next = tail_next;
    sorted_tail = head;
  } else {
    head->next = rpair.first;
    rpair.second->next = tail_next;
    sorted_tail = rpair.second; 
  }

  return { sorted_head, sorted_tail };
}

LinkNode* LinkSort(LinkNode* head) {
  auto tail = head;

  while(tail->next != nullptr) {
    tail = tail->next;
  }

  return LinkSort(head, tail).first;
}

int main() {
  std::vector<int> nums = { 5, 4, 3, 2, 1 };
  auto head = CreateLinkList(nums);

  auto sorted_head = LinkSort(head);
  PrintLinkList(sorted_head);

  return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值