本文共 10347 字,大约阅读时间需要 34 分钟。
class Solution { public ListNode reverseList(ListNode head) { if(head==null||head.next==null) return head; ListNode cur=head,next=head.next; cur.next=null; //这一步不能忘 while (next!=null){ ListNode temp = next.next; next.next=cur; cur=next; next=temp; } return cur; } }
class Solution { public ListNode reverseList(ListNode head) { if(head==null||head.next==null) return head; ListNode rec = reverseList(head.next); head.next.next=head; head.next=null; return rec; }}
class Solution { public boolean isPalindrome(ListNode head) { Dequedeque = new LinkedList<>(); 1.存入双向链表数值 while (head!=null){ deque.addLast(head.val); head = head.next; } 2.size一半 int sizeHalf = deque.size()/2; for (int i = 0; i < sizeHalf; i++) { if (deque.pollFirst()!=deque.pollLast()) return false; } 3.到这里,说明是回文 return true; }}
1.建立快慢指针,slow 和 fast,slow每次滑动1个节点,fast每次滑动2个节点,当fast滑动至最后时,slow刚好到中间;
2.在slow,fast滑动过程中,逐个反转前半部分链表,pre作为反转链表的头节点;
3.当fast到达最后时,开始对比:slow向后,pre向前(其实也是向pre.next的方向),依次对比值是否相同。
时间复杂度:n;
空间复杂度:1.
class Solution { public boolean isPalindrome(ListNode head) { if (head==null || head.next==null) return true; ListNode slow=head,fast=head; ListNode prepre=null,pre=head; 1.此条件说明fast到达最后,当然分别对应:偶、奇个数 while (fast!=null && fast.next!=null){ 1.快慢部分 slow=slow.next; fast=fast.next.next; 2.反转部分 ListNode temp = pre.next; pre.next = prepre; prepre = pre; pre = temp; } 2.到这里说明fast已经到达最后,可能是尾节点(奇数时) 也可能是尾节点后的null(偶数时) 奇数时,slow此时在正中间,还需要向后移动1个 if (fast!=null){ slow=slow.next; } 3.开始对比 你说这里为啥要用prepre而非pre? 哈哈 while (prepre!=null){ if (prepre.val!=slow.val) return false; prepre=prepre.next; slow=slow.next; } 4.到这里说明是回文 return true; }}
class Solution { public int[] reversePrint(ListNode head) { if (head==null) return new int[0]; 1.获取链表长度 int lenOfList=0; ListNode temp = head; while (temp!=null){ lenOfList++; temp = temp.next; } 2.建立数组 int[] res = new int[lenOfList]; 3.从尾部开始存 while (head!=null){ res[--lenOfList] = head.val; head = head.next; } return res; }}
class Solution { public ListNode mergeTwoLists(ListNode l1, ListNode l2) { 1.新建第3条链表的头节点 ListNode head = new ListNode(0); 2.节点cur 进行具体的后续拼接 ListNode cur = head; while (l1!=null && l2!=null){ 1.拼接l1时 if (l1.val<= l2.val){ cur.next=l1; l1=l1.next; } 2.拼接l2时 else { cur.next=l2; l2=l2.next; } cur = cur.next; } 3.拼接另一条非空串 cur.next = l1==null?l2:l1; 4.返回head的下一个节点 return head.next; }}
输入一个链表,输出该链表中倒数第k个节点。为了符合大多数人的习惯,本题从1开始计数,即链表的尾节点是倒数第1个节点。
例如,一个链表有 6 个节点,从头节点开始,它们的值依次是 1、2、3、4、5、6。这个链表的倒数第 3 个节点是值为 4 的节点。
1.可以设置两个快慢指针,慢指针slow比快指针fast要慢k个节点;
2.当快指针fast到达尾部null时,慢指针slow正好是倒数第k的节点。
时间复杂度:n;
空间复杂度:1。
class Solution { public ListNode getKthFromEnd(ListNode head, int k) { ListNode slow = head; ListNode fast = head; 1.fast先走k步 while (k>0){ k--; 1.1判断是否k>链表长度,即是否fast指针提前到头 if (fast==null) return fast; fast=fast.next; } 2.slow 和 fast 共同向后走,直到 fast为null while (fast!=null){ fast=fast.next; slow = slow.next; } 3.返回slow即可 return slow; }}
给定单向链表的头指针和一个要删除的节点的值,定义一个函数删除该节点。
返回删除后的链表的头节点。注意:此题对比原题有改动
1.从头结点向后遍历,找到某个节点cur的值=target;
2.分两种情况:class Solution { public ListNode deleteNode(ListNode head, int val) { if (head==null) return null; ListNode pre = new ListNode(); ListNode cur = head; 1.当头节点就是要删除的时 if (head.val==val) return head.next; 2.当是头节点之后的节点要删除时 while (cur!=null){ 1.当节点数值不符合时 if (cur.val!=val){ 1.1.保存cur到pre pre = cur; 1.2.cur向后滑动1格 cur = cur.next; } 2.当节点值符合时 else { 越过cur进行连接 pre.next=cur.next; break; } } return head; }}
class Solution { public ListNode getIntersectionNode(ListNode headA, ListNode headB) { 0.这一步其实可以省略 if (headA==null || headB==null) return null; 1.保存两个链表的头节点 ListNode hA=headA; ListNode hB=headB; 2.只有两个头节点不是null才会继续执行 while (headA!=null || headB!=null){ 1.有公共节点 if (headA==headB) return headA; 2.向后滑动,如果自己的链表走完了,则从对方的链表头开始滑动;从对方链表结束,就不会再换路径继续滑动了 headA = headA==null?hB:headA.next; headB = headB==null?hA:headB.next; } 3.此时说明两个链表无公共交点 return null; }}
class Solution { public Node copyRandomList(Node head) { Mapmap = new HashMap<>(); 0.暂时性使用节点 Node cur = head; 1.先按数值一一对应存储新节点 while (cur!=null){ map.put(cur,new Node(cur.val)); cur=cur.next; } 2.进行连接 cur=head; 再赋值为head while (cur!=null){ Node curNew = map.get(cur); // if (cur.next!=null) 这里不判断也行,因为如果没有,map返回就是null curNew.next=map.get(cur.next); // if (cur.random!=null) 这里不判断也行,因为如果没有,map返回就是null curNew.random=map.get(cur.random); cur=cur.next; } return map.get(head); }}
class Solution { public Node treeToDoublyList(Node root) { if (root==null) return null; Listlist = new ArrayList<>(); inorder(root,list); 1.依次把头节点到尾节点之间的双向连接起来 for (int i = 0; i < list.size()-1; i++) { list.get(i).right=list.get(i+1); list.get(i+1).left=list.get(i); } 2.最后把头节点 和 尾节点 连接起来 list.get(0).left=list.get(list.size()-1); list.get(list.size()-1).right=list.get(0); return list.get(0); } 二叉树中序遍历 public void inorder(Node root,List list){ if (root==null) return; inorder(root.left,list); list.add(root); inorder(root.right,list); }}
class Solution { Node pre,head; public Node treeToDoublyList(Node root) { if (root==null) return null; inorder(root); head.left=pre; pre.right=head; return head; } 二叉树中序遍历 public void inorder(Node root){ if (root==null) return; inorder(root.left); if (pre!=null) pre.right=root; else head = root; root.left=pre; pre=root; inorder(root.right); }}
cur:当前节点;
pre:cur的前一个节点; temp:暂时存储cur.next节点,防止链表反转后cur找不到它后边的节点;1.ListNode temp = cur.next; 暂时存储cur.next节点2.cur.next = pre; 发生反转3.pre = cur; 反转完后,pre向后滑动4.cur = temp cur向后滑动
cur:当前待删除结点;
pre:cur的前1个结点;1.pre.next = cur.next; pre.next指针越过cur节点,连接至cur的下一个节点2.cur.next=null; cur.next设置为空,使其断开跟后边的连接(其实这一步有的时候可以没有)
class Solution { public void deleteNode(ListNode node) { node.val=node.next.val; node.next=node.next.next; }}
ListNode slow = head;ListNode fast = head;1.fast指针先走k步while(k!=0){ k--; fast=fast.next;}2.fast指针与slow指针开始一起走while(fast!=null){ fast=fast.next; slow=slow.next;}
ListNode slow = head;ListNode fast = head;while(fast!=null && fast.next!=null){ slow = slow.next; slow指针每次走1步 fast = fast.next.next; fast指针每次走2步}
转载地址:http://iqqn.baihongyu.com/