剑指offer-day2
从尾到头打印链表
简单题,但是实现方法与答案有些不同。
我考虑的是用一个ArrayList来记录链表中的值,最后逆序赋值给一个int数组。答案用的是模拟栈的LinkedList。我尝试了两个方法,发现时空复杂度并没有什么变化,所以就放上自己的答案吧。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
|
class Solution { public int[] reversePrint(ListNode head) { ArrayList<Integer> list = new ArrayList<>(); while(head != null){ list.add(head.val); head = head.next; } int[] res = new int[list.size()]; for(int i = 0; i < list.size(); i++){ res[i] = list.get(list.size() - i - 1); } return res; } }
|
反转链表
经典题目了,但是发现自己死活做不出来,总是有空指针异常,一看答案发现语句顺序错了…但总体思路是对的。利用三个指针来指向前元素、现元素和后元素,然后进行反转操作,操作顺序为:
- next指针指向当前元素的后一个元素
- cur指向的当前元素的指针改为指向pre
- pre改为指向cur指向的元素
- cur改为指向next指向的元素
唯一要注意的点是next指针需要在循环内创建,否则在链表本身为空时会报空指针。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
|
class Solution { public ListNode reverseList(ListNode head){ ListNode pre = null; ListNode cur = head;
while(cur != null){ ListNode next = cur.next; cur.next = pre; pre = cur; cur = next; } return pre; } }
|
之前有想过同上一题目一样,用一个辅助栈来完成反转,看了答案发现这样做并没有三指针快,就放弃这个思路了。
复杂链表的复制
完全不会做,选择睡大觉(恼)
好好看了看答案,大概知道思路是怎样的,复述一下。
有两种解法:辅助哈希表和拼接链表,因为后者在空间复杂度上优于前者,所以使用后者。
因为random节点的存在,导致复制时指针可能指向一个还没有创建的节点,所以可以将原链表两倍拉长,使原链表节点先指向复制节点,复制节点再指向原链表的下一个节点。完成复制后进行random节点的指向初始化,通过原节点的信息来让复制节点的指向正确的节点。最后将链表拆开,复制完成。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
|
class Solution { public Node copyRandomList(Node head) { if(head == null) return null; Node cur = head; while(cur != null) { Node tmp = new Node(cur.val); tmp.next = cur.next; cur.next = tmp; cur = tmp.next; } cur = head; while(cur != null) { if(cur.random != null) cur.next.random = cur.random.next; cur = cur.next.next; } cur = head.next; Node pre = head, res = head.next; while(cur.next != null) { pre.next = pre.next.next; cur.next = cur.next.next; pre = pre.next; cur = cur.next; } pre.next = null; return res; } }
|
可以发现自己对链表还不够熟练,这道题要多加练习。