元のタイトル:
最初にコードを貼り付けます。
public class Solution147 {
public ListNode insertionSortList(ListNode head) {
//当链表为空时,不需排序,直接返回
if (head == null){
return head;
}
//创建一个虚拟头节点,方便处理头节点
ListNode newhead = new ListNode(-1);
newhead.next = head;
//ret为待排序的节点
ListNode ret = head.next;
//进入循环,直到待排序的节点为空(不存在待排序的节点)
while (ret != null){
//情况1:头节点小于等于待排序节点
if (head.val <= ret.val){
head = head.next;
//情况2:头节点大于待排序节点
}else {
//新建一个cur节点来寻找前面有序链表中大于待排序节点的节点,插入它的前面
ListNode cur = newhead;
while (cur.next.val <= ret.val){
cur = cur.next;
}
head.next = ret.next;
ret.next = cur.next;
cur.next = ret;
}
ret = head.next;
}
return newhead.next;
}
}
アイデアの分析:
この質問では、問題を解決するために挿入ソートを使用する必要がありますが、挿入ソートとは何ですか?
1.挿入ソートは反復的であり、すべての要素が順序付けられた出力リストを形成できるようになるまで、一度に1つの要素のみを移動します。
2.各反復で、挿入ソートは、ソートされる要素を1つだけ入力データから削除し、シーケンス内の適切な位置を見つけて挿入します。
3.すべての入力データが挿入されるまで繰り返します。
上記からわかるように、最初にリンクリスト内のノードをマークする必要があります。これは、ソートされるretノードとして記録されます。このノードをリンクリストのヘッドノードと比較してサイズを決定します。retノードがヘッドノード以上の場合、ノードはヘッドノードの後ろに配置する必要があることを意味するため、小さな順序でリンクされます。リスト。retノードは、順序付きリンクリストのテールノードです。
ヘッドノードとretノードの両方を1ビット後方に移動して、ヘッドノードが再び順序付きリンクリストのテールノードになるようにします(ヘッドノードの前にノードはなく、1つのノードのみで、デフォルトはテールです)。順序付きリンクリストのノード)。
次のノードと前の順序付きリストのテールノードとの比較を続けます。テールノードよりも大きい場合は後ろになり、テールノードよりも小さい場合は前の順序付きリストに入り、比較します。ソートされるリンクリストのノードがその前に挿入されます。
下の図に示すように(画像が良くない場合は非難しないでください)、retがhead以上の場合は挿入する必要はありません。retがhead未満の場合は、に順序付きリストを入力してください。頭の前でもう一度並べ替えて、適切な位置を見つけます(retより大きいノードを見つけて、ここにノードの前に置きます)。
その前の順序付けられたリンクリストでretノードよりも小さいノードを見つけて、その後ろにランク付けしてみませんか?retより大きく、headよりも小さいノードが後ろにある場合、前のリンクリストに入るときに混乱し、再度並べ替えることができないためです。