1. 合并两个有序链表
将两个有序链表合并为一个新的有序链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。
示例:
输入:1->2->4, 1->3->4
输出:1->1->2->3->4->4
解法:
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) {
* val = x;
* next = null;
* }
* }
*/
public class Solution {
public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
//新建一个空的头结点方便处理
ListNode head=new ListNode(-1);
//归并后的链表
ListNode p=head;
while(l1!=null && l2!=null){
if(l1.val<l2.val){
p.next=l1;
l1=l1.next;
}else{
p.next=l2;
l2=l2.next;
}
p=p.next;
}
if(l1!=null){
p.next=l1;
}
if(l2!=null){
p.next=l2;
}
return head.next;
}
}
2. 排序链表
在O(nlogn)时间复杂度和常数级空间复杂度下,对链表进行排序。
示例:
输入: 4->2->1->3
输出: 1->2->3->4
解法:
采用归并排序:
- 找到链表中点(快慢指针法)
- 分别排序左半部分和右半部分
- 归并
/**
* Definition for singly-linked list.
* class ListNode {
* int val;
* ListNode next;
* ListNode(int x) {
* val = x;
* next = null;
* }
* }
*/
public class Solution {
public ListNode sortList(ListNode head){
if(head==null|| head.next==null){
return head;
}
ListNode middle=findMiddle(head);
//排序右半边链表
ListNode right=sortList(middle.next);
middle.next=null;
//排序左半边链表
ListNode left=sortList(head);
//归并
return mergeTwoLists(left,right);
}
//快慢指针,慢指针一次走一步,快指针一次走两步,快指针达到末尾时,慢指针刚好在中间
private ListNode findMiddle(ListNode list){
ListNode chaser=list;
ListNode runner=chaser.next;
//结点数为偶数时,chaser停在前半部分链表节点的尾结点
while(runner.next!=null && runner.next.next!=null){
chaser=chaser.next;
runner=runner.next.next;
}
return chaser;
}
//归并两个有序链表
private ListNode mergeTwoLists(ListNode l1, ListNode l2) {
//新建一个空的头结点方便处理
ListNode head=new ListNode(-1);
//归并后的链表
ListNode p=head;
while(l1!=null && l2!=null){
if(l1.val<l2.val){
p.next=l1;
l1=l1.next;
}else{
p.next=l2;
l2=l2.next;
}
p=p.next;
}
if(l1!=null){
p.next=l1;
}
if(l2!=null){
p.next=l2;
}
return head.next;
}
}
3. 对链表进行插入排序
解法:
新建一个链表,遍历原链表,将每个节点加入新链表正确的位置。
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) {
* val = x;
* next = null;
* }
* }
*/
public class Solution {
public ListNode insertionSortList(ListNode head) {
ListNode dummy=new ListNode(0);
ListNode cur = head;//待排序/插入的节点
ListNode pre;//正确插入位置的指针
while(cur!=null){
pre=dummy;
ListNode next=cur.next;//保存下一个节点
//找插入位置
while(pre.next != null && pre.next.val < cur.val){
pre=pre.next;
}
//将当前节点插入到新新链表中
cur.next=pre.next;
pre.next=cur;
//处理下一个节点
cur=next;
}
return dummy.next;
}
}
4. 合并两个有序数组
给定两个有序整数数组 nums1 和 nums2,将 nums2 合并到 nums1 中,使得 num1 成为一个有序数组。
说明:
- 初始化 nums1 和 nums2 的元素数量分别为 m 和 n。
- 你可以假设 nums1 有足够的空间(空间大小大于或等于 m + n)来保存 nums2 中的元素。
示例:
输入:
nums1 = [1,2,3,0,0,0], m = 3
nums2 = [2,5,6], n = 3
输出: [1,2,2,3,5,6]
解法:
public class Solution {
public void merge(int A[], int m, int B[], int n) {
int i=m-1,j=n-1,k=m+n-1;
while(i>=0 && j>=0){
if(A[i]>B[j]){
A[k--]=A[i--];
}else{
A[k--]=B[j--];
}
}
//如果B有剩余,则移到A中
while(j>=0){
A[k--]=B[j--];
}
}
}