难度:中等
题目:
对链表进行插入。
从第一个元素开始,该链表可以被认为已经部分排序(用黑色表示)。
每次迭代时,从输入数据中移除一个元素(用红色表示),并原地将其插入到已排好序的链表中。
插入排序算法:
插入排序是迭代的,每次只移动一个元素,直到所有元素可以形成一个有序的输出列表。
每次迭代中,插入排序只从输入数据中移除一个待排序的元素,找到它在序列中适当的位置,并将其插入。
重复直到所有输入数据插入完为止。
思路:
①咋一看题目,关键字 链表、排序,第一时间比较容易想到的就是能不能不操作链表,换种做法。
②能不能先把列表中的数据弄出来,弄到list里边,然后排好序,再弄回到原来的链表里。
③好像阔以。
代码:
public ListNode insertionSortList(ListNode head) { ListNode temp = head; Listlist = new ArrayList<>(); while (temp != null) { // 把链表数据放到List里 list.add(temp.val); temp = temp.next; } list.sort(Comparator.comparingInt(o -> o)); // List排序 ListNode res = head; for (Integer a : list) { // 放回到原来head的链表里 head.next = new ListNode(a); head = head.next; } return res!=null ? res.next : res;}
成了,
就这样?
不太好,可以但没必要,这样不仅太慢,两次循环再加上一次排序,而且这样对操作链表毫无意义,也不太道德,相当于打了插边球,没有体育精神,还是老老实实的弄个链表的。
而且如果面试说这样的思路,估计得被面试官喷一脸。。
思路2:
①首先,我们可以查到排好序的节点的最后一个
②然后用另一个指针pre,从表头开始遍历,每次拿出未排序的节点,和前面一个节点作比较,大于或等于则跳过不排序,如果前面一个节点更小,则进入第二个循环,续个和pre对比较,找到对应位置插入。(其实就是插入排序,只不过这是链表)
③对头。
代码:
public ListNode insertionSortList(ListNode head) { ListNode temp = new ListNode(0), pre; temp.next = head; while(head != null && head.next != null) { if(head.val <= head.next.val) { // 找到第一个未排序节点 head = head.next; continue; } pre = temp; while (pre.next.val next.val) pre = pre. ListNode curr = head.next; // 插入 head.next = curr.next; curr.next = pre.next; pre.next = curr; } return temp.next; }
---------------------------------------------
星会感到痛楚
每天去想,月亮喜欢我