这篇博客用于记录Fortune的LeetCode的刷题记录,基本每道题都包括了基础思路和follow up,我会尽力保障代码风格和充足注释的💪!
链表 删除链表中的节点 请编写一个函数,使其可以删除某个链表中给定的(非末尾)节点,你将只被给定要求被删除的节点。
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 class Solution { public void deleteNode (ListNode node) { if (node == null ) { return ; } ListNode lastNode = node; while (node.next != null ) { lastNode = node; node.val = node.next.val; node = node.next; } lastNode.next = null ; } } class Solution { public void deleteNode (ListNode node) { if (node == null ) { return ; } node.val = node.next.val; node.next = node.next.next; } }
二进制链表转整数 给你一个单链表的引用结点 head。链表中每个结点的值不是 0 就是 1。已知此链表是一个整数数字的二进制表示形式。
请你返回该链表所表示数字的 十进制值 。
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 51 52 53 54 55 56 57 58 59 60 class Solution { public int getDecimalValue (ListNode head) { if (head == null ) { return 0 ; } int length = 0 , result = 0 ; ListNode tmpHead = head; while (tmpHead != null ) { length ++; tmpHead = tmpHead.next; } while (head != null ) { result += head.val * pow2(--length); head = head.next; } return result; } public int pow2 (int l) { int result = 1 ; for (int i = 0 ; i < l; i ++) { result *= 2 ; } return result; } } class Solution { public int getDecimalValue (ListNode head) { if (head == null ) { return 0 ; } int result = 0 ; while (head != null ) { result = (result << 1 ) | head.val; head = head.next; } return result; } }
返回倒数第K个节点 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 class Solution { public int kthToLast (ListNode head, int k) { if (head == null ) { return 0 ; } ListNode head2 = head; for (int i = 0 ; i < k - 1 ; i ++) { head = head.next; } while (head.next != null ) { head = head.next; head2 = head2.next; } return head2.val; } }
从尾到头打印链表 输入一个链表的头节点,从尾到头反过来返回每个节点的值(用数组返回)。
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 51 52 class Solution { public int [] reversePrint(ListNode head) { if (head == null ) { return new int [0 ]; } int lenght = 0 ; ListNode head2 = head; while (head != null ) { lenght ++; head = head.next; } int [] result = new int [lenght]; while (head2 != null ) { result[--lenght] = head2.val; head2 = head2.next; } return result; } } class Solution { public int [] reversePrint(ListNode head) { if (head == null ) { return new int [0 ]; } Stack<Integer> stack = new Stack<>(); while (head != null ) { stack.push(head.val); head = head.next; } int [] result = new int [stack.size()]; int index = 0 ; while (!stack.isEmpty()) { result[index ++] = stack.pop(); } return result; } }
反转链表 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 51 52 53 54 55 56 57 58 59 60 61 class Solution { public ListNode reverseList (ListNode head) { ListNode tmp = null ; ListNode cur = null ; ListNode pre = head; while (pre != null ) { tmp = pre.next; pre.next = cur; cur = pre; pre = tmp; } return cur; } } class Solution { public ListNode reverseList (ListNode head) { return reverseListRecursivr(head, null ); } public ListNode reverseListRecursivr (ListNode head, ListNode pre) { if (head == null ) { return pre; } ListNode tmp = head.next; head.next = pre; return reverseListRecursivr(tmp, head); } } class Solution { public ListNode reverseList (ListNode head) { if (head == null || head.next == null ) { return head; } ListNode rtn = reverseList(head.next); head.next.next = head; head.next = null ; return rtn; } }
移除重复节点 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 51 52 class Solution { public ListNode removeDuplicateNodes (ListNode head) { if (head == null ) return null ; ListNode result = head; ListNode cur; while (head != null ) { cur = head; while (cur.next != null ) { if (cur.next.val == head.val) { cur.next = cur.next.next; } else { cur = cur.next; } } head = head.next; } return result; } } class Solution { public ListNode removeDuplicateNodes (ListNode head) { if (head == null ) return null ; Set<Integer> exsited = new HashSet<>(); exsited.add(head.val); ListNode result = head; while (head.next != null ) { if (!exsited.add(head.next.val)) { head.next = head.next.next; } else { head = head.next; } } return result; } }
链表相交 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 51 public class Solution { public ListNode getIntersectionNode (ListNode headA, ListNode headB) { ListNode tmp; while (headA != null ) { tmp = headB; while (tmp != null ) { if (headA == tmp) return headA; tmp = tmp.next; } headA = headA.next; } return null ; } } public class Solution { public ListNode getIntersectionNode (ListNode headA, ListNode headB) { ListNode posA = headA; ListNode posB = headB; while (posA != posB) { if (posA == null ) { posA = headB; } else { posA = posA.next; } if (posB == null ) { posB = headA; } else { posB = posB.next; } } return posA; } }
两个链表的第一个公共节点 输入两个链表,找出它们的第一个公共节点
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 51 52 53 54 public class Solution { public ListNode getIntersectionNode (ListNode headA, ListNode headB) { ListNode posA = headA; ListNode posB = headB; while (posA != posB) { if (posA == null ) { posA = headB; } else { posA = posA.next; } if (posB == null ) { posB = headA; } else { posB = posB.next; } } return posA; } } public class Solution { public ListNode getIntersectionNode (ListNode headA, ListNode headB) { Set<ListNode> nodes = new HashSet<>(); while (headA != null ) { nodes.add(headA); headA = headA.next; } while (headB != null ) { if (nodes.add(headB)) { headB = headB.next; } else { return headB; } } return headB; } }
合并两个升序链表 将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。
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 51 class Solution { public ListNode mergeTwoLists (ListNode l1, ListNode l2) { ListNode head = new ListNode(-1 ); ListNode pos = head; while (l1 != null && l2 != null ) { if (l1.val >= l2.val) { pos.next = l2; l2 = l2.next; } else { pos.next = l1; l1 = l1.next; } pos = pos.next; } pos.next = l1 == null ? l2 : l1; return head.next; } } class Solution { public ListNode mergeTwoLists (ListNode l1, ListNode l2) { if (l1 == null ) { return l2; } else if (l2 == null ) { return l1; } if (l1.val >= l2.val) { l2.next = mergeTwoLists(l1,l2.next); return l2; } else { l1.next = mergeTwoLists(l1.next, l2); return l1; } } }
删除给定值的链表节点 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 class Solution { public ListNode deleteNode (ListNode head, int val) { if (head == null ) return head; ListNode result = head; while (head.val == val) { result = result.next; head = head.next; } while (head != null ) { if (head.next != null && head.next.val == val) { head.next = head.next.next; } else { head = head.next; } } return result; }
删除排序链表的重复元素 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 class Solution { public ListNode deleteDuplicates (ListNode head) { if (head == null ) return null ; ListNode result = head; ListNode tmp; while (head != null ) { tmp = head.next; while (tmp != null && tmp.val == head.val) { tmp = tmp.next; } head.next = tmp; head = head.next; } return result; } }
判断链表是否有环 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 public class Solution { public boolean hasCycle (ListNode head) { Set<ListNode> set = new HashSet<>(); while (head != null ) { if (set.add(head)) { head = head.next; } else { return true ; } } return false ; } } public class Solution { public boolean hasCycle (ListNode head) { if (head == null ) { return false ; } ListNode slow = head, fast = head; while (fast != null && fast.next != null ) { fast = fast.next.next; slow = slow.next; if (fast == slow) return true ; } return false ; } }
回文链表 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 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 class Solution { public boolean isPalindrome (ListNode head) { if (head == null ) return true ; Stack<Integer> stack = new Stack<>(); ListNode pos = head; while (pos != null ) { stack.push(pos.val); pos = pos.next; } while (head != null ) { if (head.val == stack.pop()) { head = head.next; } else { return false ; } } return true ; } } class Solution { public boolean isPalindrome (ListNode head) { if (head == null ) return true ; ListNode slow = head, fast = head; while (fast != null && fast.next != null ) { slow = slow.next; fast = fast.next.next; } if (fast != null ) { slow = slow.next; } ListNode cur = null ; ListNode pre = slow; ListNode tmp = null ; while (pre != null ) { tmp = pre.next; pre.next = cur; cur = pre; pre = tmp; } while (cur != null ) { if (cur.val == head.val) { cur = cur.next; head = head.next; } else { return false ; } } return true ; } } class Solution { public boolean isPalindrome (ListNode head) { if (head == null ) return true ; ListNode slow = head, fast = head, pre = null , tmp = null ; while (fast != null && fast.next != null ) { fast = fast.next.next; tmp = slow.next; slow.next = pre; pre = slow; slow = tmp; } if (fast != null ) { slow = slow.next; } while (slow != null ) { if (slow.val == pre.val) { slow = slow.next; pre = pre.next; } else { return false ; } } return true ; } }
有序链表转换二叉搜索树 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 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 class Solution { public TreeNode sortedListToBST (ListNode head) { if (head == null ) return null ; if (head.next == null ) return new TreeNode(head.val); ListNode slow = head, fast = head, pre = null ; while (fast != null && fast.next != null ) { pre = slow; slow = slow.next; fast = fast.next.next; } pre.next = null ; TreeNode mid = new TreeNode(slow.val); mid.left = sortedListToBST(head); mid.right = sortedListToBST(slow.next); return mid; } } class Solution { public TreeNode sortedListToBST (ListNode head) { int [] data = new int [20000 ]; int length = 0 ; while (head != null ) { data[length ++] = head.val; head = head.next; } return sortedArrayToBST(data, 0 , (length - 1 )); } public TreeNode sortedArrayToBST (int [] data, int head, int tail) { if (head > tail) return null ; TreeNode mid = new TreeNode(data[head + (tail - head) / 2 ]); mid.left = sortedArrayToBST(data, head, head +((tail - head) / 2 - 1 ); mid.right = sortedArrayToBST(data, head + (tail - head) / 2 + 1 , tail); return mid; } } class Solution { ListNode head; public TreeNode sortedListToBST (ListNode head) { int length = 0 ; this .head = head; while (head != null ) { length ++; head = head.next; } return convertListToBST(0 , length - 1 ); } public TreeNode convertListToBST (int left, int right) { if (left > right) return null ; int mid = (right + left) / 2 ; TreeNode leftNode = convertListToBST(left, mid - 1 ); TreeNode midNode = new TreeNode(head.val); midNode.left = leftNode; head = head.next; TreeNode rightNode = convertListToBST(mid + 1 , right); midNode.right = rightNode; return midNode; } }
复杂链表的深拷贝 给定一个链表,每个节点包含一个额外增加的随机指针,该指针可以指向链表中的任何节点或空节点。
要求返回这个链表的 深拷贝 。
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 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 class Solution { public Node copyRandomList (Node head) { if (head == null ) return null ; List<Node> oldList = new ArrayList<>(); List<Node> newList = new ArrayList<>(); Node pos = head; while (pos != null ) { oldList.add(pos); Node newNode = new Node(pos.val); newList.add(newNode); pos = pos.next; } oldList.add(null ); newList.add(null ); for (int i = 0 ; i < newList.size() - 1 ; i ++) { Node tmp = newList.get(i); tmp.next = newList.get(i + 1 ); tmp.random = newList.get(oldList.indexOf(oldList.get(i).random)); } return newList.get(0 ); } } class Solution { public Node copyRandomList (Node head) { Map<Node, Node> map = new HashMap<>(); Node pos = head; while (pos != null ) { Node newNode = new Node(pos.val); map.put(pos, newNode); pos = pos.next; } Node pos2 = head; while (pos2 != null ) { Node newNode = map.get(pos2); newNode.next = pos2.next == null ? null : map.get(pos2.next); newNode.random = pos2.random == null ? null : map.get(pos2.random); pos2 = pos2.next; } return map.get(head); } } class Solution { public Node copyRandomList (Node head) { if (head == null ) return null ; Node pos = head; while (pos != null ) { Node newNode = new Node(pos.val); Node tmp = pos.next; pos.next = newNode; newNode.next = tmp; pos = tmp; } Node pos2 = head; while (pos2 != null ) { Node newNode = pos2.next; newNode.random = pos2.random == null ? null : pos2.random.next; pos2 = newNode.next; } Node pos3 = head; Node result = head.next; Node pos4 = head.next; while (pos3 != null ) { pos3.next = pos3.next.next; pos3 = pos3.next; pos4.next = pos4.next == null ? null : pos4.next.next; pos4 = pos4.next; } return result; } }
链表的插入排序 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 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 class Solution { public ListNode insertionSortList (ListNode head) { if (head == null ) return null ; ListNode sortedTail = head; ListNode ptr = head.next; while (ptr != null ) { ListNode cur = head; ListNode pre = null ; while (pre != sortedTail && cur.val < ptr.val) { pre = cur; cur = cur.next; } if (pre == null ) { sortedTail.next = ptr.next; ptr.next = head; head = ptr; } else if (pre == sortedTail) { sortedTail = ptr; } else { sortedTail.next = ptr.next; ptr.next = cur; pre.next = ptr; } ptr = sortedTail.next; } return head; } } class Solution { public ListNode insertionSortList (ListNode head) { if (head == null ) return null ; ListNode sortedTail = head; ListNode ptr = head.next; while (ptr != null ) { if (ptr.val <= head.val) { sortedTail.next = ptr.next; ptr.next = head; head = ptr; } else if (ptr.val >= sortedTail.val) { sortedTail = ptr; } else { ListNode cur = head; ListNode pre = null ; while (pre != sortedTail && cur.val < ptr.val) { pre = cur; cur = cur.next; } sortedTail.next = ptr.next; ptr.next = cur; pre.next = ptr; } ptr = sortedTail.next; } return head; } }
分割链表 编写程序以 x 为基准分割链表,使得所有小于 x 的节点排在大于或等于 x 的节点之前。如果链表中包含 x,x 只需出现在小于 x 的元素之后(如下所示)。分割元素 x 只需处于“右半部分”即可,其不需要被置于左右两部分之间。
1 2 3 示例 输入: head = 3->5->8->5->10->2->1, x = 5 输出: 3->1->2->10->5->5->8
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 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 class Solution { public ListNode partition (ListNode head, int x) { if (head == null ) return null ; ListNode leftHead = null , leftPtr = null ; while (head != null && head.val < x){ if (leftHead == null ) { leftHead = head; leftPtr = leftHead; } else { leftPtr.next = head; leftPtr = leftPtr.next; } head = head.next; } ListNode rightPtr = head; while (rightPtr != null ) { if (rightPtr.next != null && rightPtr.next.val < x) { if (leftHead == null ) { leftHead = rightPtr.next; leftPtr = leftHead; } else { leftPtr.next = rightPtr.next; leftPtr = leftPtr.next; } rightPtr.next = rightPtr.next.next; } else { rightPtr = rightPtr.next; } } if (leftHead == null ) { return head; } else { leftPtr.next = head; return leftHead; } } } class Solution { public ListNode partition (ListNode head, int x) { if (head == null ) return null ; ListNode leftHead = new ListNode(0 ), rightHead = new ListNode(0 ); ListNode leftTail = leftHead, rightTail = rightHead; while (head != null ) { if (head.val < x) { leftTail.next = head; leftTail = leftTail.next; } else { rightTail.next = head; rightTail = rightTail.next; } head = head.next; } rightTail.next = null ; leftTail.next = rightHead.next; return leftHead.next; } }
奇偶链表 按链表节点的索引的奇偶分割链表
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 class Solution { public ListNode oddEvenList (ListNode head) { ListNode evenHead = new ListNode(0 ), oddHead = new ListNode(0 ); ListNode evenTail = evenHead, oddTail = oddHead; int index = 1 ; while (head != null ) { if (index % 2 == 0 ) { evenTail.next = head; evenTail = evenTail.next; } else { oddTail.next = head; oddTail = oddTail.next; } head = head.next; index ++; } evenTail.next = null ; oddTail.next = evenHead.next; return oddHead.next; } }
链表组件 给定链表头结点 head,该链表上的每个结点都有一个 唯一的整型值 。
同时给定列表 G,该列表是上述链表中整型值的一个子集。
返回列表 G 中组件的个数,这里对组件的定义为:链表中一段最长连续结点的值(该值必须在列表 G 中)构成的集合。
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 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 class Solution { public int numComponents (ListNode head, int [] G) { if (head == null || G.length == 0 ) return 0 ; List<Integer> list = new ArrayList<>(); while (head != null ) { list.add(head.val); head = head.next; } List<Integer> listForIndex = new ArrayList<>(); for (int i = 0 ; i < G.length; i++) { listForIndex.add(list.indexOf(G[i])); } int count = 0 ; while (listForIndex.size() > 0 ) { int index = Collections.min(listForIndex); listForIndex.remove(listForIndex.indexOf(index)); while (listForIndex.indexOf(++index) >= 0 ) { listForIndex.remove(listForIndex.indexOf(index)); } count++; } return count; } } class Solution { public int numComponents (ListNode head, int [] G) { if (head == null || G.length == 0 ) return 0 ; int count = 0 ; Set<Integer> set = new HashSet<>(); for (int i = 0 ; i < G.length; i++) { set.add(G[i]); } while (head != null ) { if (set.contains(head.val)) { ListNode componentHead = head; while (componentHead != null && set.contains(componentHead.val)) { componentHead = componentHead.next; } count ++; head = componentHead; } else { head = head.next; } } return count; } }
两两交换链表节点 给定一个链表,两两交换其中相邻的节点,并返回交换后的链表。
你不能只是单纯的改变节点内部的值 ,而是需要实际的进行节点交换。
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 51 52 53 54 class Solution { public ListNode swapPairs (ListNode head) { if (head == null || head.next == null ) { return head; } ListNode result = head.next; ListNode pre = null ; while (head != null && head.next != null ) { ListNode cur = head; ListNode post = head.next; cur.next = post.next; post.next = cur; if (pre != null ) { pre.next = post; } pre = cur; head = cur.next; } return result; } } class Solution { public ListNode swapPairs (ListNode head) { if (head == null || head.next == null ) { return head; } ListNode firstNode = head; ListNode secondNode = head.next; firstNode.next = swapPairs(secondNode.next); secondNode.next = firstNode; return secondNode; } }
排序链表 在 O (n * logn) 时间复杂度和O(1)空间复杂度下,对链表进行排序。
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 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 class Solution { public ListNode sortList (ListNode head) { if (head == null || head.next == null ) return head; int range = 1 ; int length = 0 ; ListNode ptr = head; while (ptr != null ) { length ++; ptr = ptr.next; } ListNode dummy = new ListNode(0 ); dummy.next = head; ListNode dummyPtr = dummy; while (range < length) { ListNode head1 = dummy.next; while (head1 != null ) { ListNode head2 = head1; int lengthOfHead1 = 0 ; for (int i = 0 ; i < range; i++) { if (head2 == null ) break ; head2 = head2.next; lengthOfHead1 ++; } ListNode nextHead1 = head2; int lengthOfHead2 = 0 ; for (int i = 0 ; i < range; i++) { if (nextHead1 == null ) break ; nextHead1 = nextHead1.next; lengthOfHead2 ++; } for (int i = 0 , index1 = 0 , index2 = 0 ; i < (lengthOfHead1 + lengthOfHead2); i++) { if (index1 >= lengthOfHead1) { dummyPtr.next = head2; head2 = head2.next; index2 ++; } else if (index2 >= lengthOfHead2) { dummyPtr.next = head1; head1 = head1.next; index1 ++; } else if (head1.val <= head2.val) { dummyPtr.next = head1; head1 = head1.next; index1 ++; } else { dummyPtr.next = head2; head2 = head2.next; index2 ++; } dummyPtr = dummyPtr.next; } head1 = nextHead1; } dummyPtr.next = null ; dummyPtr = dummy; range *= 2 ; } return dummy.next; } } class Solution { public ListNode sortList (ListNode head) { if (head == null || head.next == null ) { return head; } ListNode fast = head, slow = head, pre = null ; while (fast != null && fast.next != null ) { pre = slow; fast = fast.next.next; slow = slow.next; } pre.next = null ; ListNode head1 = sortList(head); ListNode head2 = sortList(slow); ListNode dummy = new ListNode(0 ); ListNode cur = dummy; while (head1 != null && head2 != null ) { if (head1.val <= head2.val) { cur.next = head1; head1 = head1.next; cur = cur.next; } else { cur.next = head2; head2 = head2.next; cur = cur.next; } } cur.next = head1 == null ? head2 : head1; return dummy.next; } } class Solution { public ListNode sortList (ListNode head) { if (head == null || head.next == null ) { return head; } ListNode dummy1 = new ListNode(0 ); ListNode dummy2 = new ListNode(0 ); ListNode ptr1 = dummy1, ptr2 = dummy2, ptr = head.next; while (ptr != null ) { if (ptr.val <= head.val) { ptr1.next = ptr; ptr1 = ptr1.next; } else { ptr2.next = ptr; ptr2 = ptr2.next; } ptr = ptr.next; } ptr1.next = null ; ptr2.next = null ; dummy1.next = sortList(dummy1.next); dummy2.next = sortList(dummy2.next); ptr1 = dummy1; while (ptr1.next != null ) { ptr1 = ptr1.next; } ptr1.next = head; head.next = dummy2.next; return dummy1.next; } }
链表相加 给你两个 非空 链表来代表两个非负整数。数字最高位位于链表开始位置。它们的每个节点只存储一位数字。将这两数相加会返回一个新的链表。
你可以假设除了数字 0 之外,这两个数字都不会以零开头。
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 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 class Solution { public ListNode addTwoNumbers (ListNode l1, ListNode l2) { ListNode res = null ; l1 = reverseList(l1); l2 = reverseList(l2); int carry = 0 ; while (l1 != null || l2 != null || carry != 0 ) { int sum = carry; sum += l1 == null ? 0 : l1.val; sum += l2 == null ? 0 : l2.val; carry = sum / 10 ; ListNode newNode = new ListNode(sum % 10 ); newNode.next = res; res = newNode; l1 = l1 == null ? null : l1.next; l2 = l2 == null ? null : l2.next; } return res; } public ListNode reverseList (ListNode head) { if (head == null || head.next == null ) { return head; } ListNode result = reverseList(head.next); head.next.next = head; head.next = null ; return result; } } class Solution { public ListNode addTwoNumbers (ListNode l1, ListNode l2) { ListNode res = null ; Stack<Integer> s1 = new Stack<>(); Stack<Integer> s2 = new Stack<>(); while (l1 != null ) { s1.push(l1.val); l1 = l1.next; } while (l2 != null ) { s2.push(l2.val); l2 = l2.next; } int carry = 0 ; while (!s1.isEmpty() || !s2.isEmpty() || carry > 0 ) { int sum = carry; sum += s1.isEmpty() ? 0 : s1.pop(); sum += s2.isEmpty() ? 0 : s2.pop(); carry = sum / 10 ; ListNode newNode = new ListNode(sum % 10 ); newNode.next = res; res = newNode; } return res; } }
链表重排 给定一个单链表 L:L0→L1→…→Ln-1→Ln , 将其重新排列后变为: L0→Ln→L1→Ln-1→L2→Ln-2→…
你不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。
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 class Solution { public void reorderList (ListNode head) { if (head == null || head.next == null ) return ; ListNode slow = head, fast = head, pre = null ; while (fast != null && fast.next != null ) { pre = slow; fast = fast.next.next; slow = slow.next; } if (pre != null ) pre.next = null ; slow = reverseList(slow); ListNode dummy = new ListNode(0 ); ListNode ptr = dummy; while (head != null ) { ptr.next = head; ptr = ptr.next; head = head.next; ptr.next = slow; ptr = ptr.next; slow = slow.next; } ptr.next = slow == null ? null : slow; } public ListNode reverseList (ListNode head) { if (head == null || head.next == null ) return head; ListNode result = reverseList(head.next); head.next.next = head; head.next = null ; return result; } }
下一个更大的节点 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 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 class Solution { public int [] nextLargerNodes(ListNode head) { if (head == null ) { return new int []{}; } int length = 0 ; ListNode ptr = head; while (ptr != null ) { length ++; ptr = ptr.next; } int [] result = new int [length]; int index = 0 ; while (head != null ) { ListNode cur = head; while (cur != null && cur.val <= head.val) { cur = cur.next; } result[index++] = cur == null ? 0 : cur.val; head = head.next; } return result; } } class Solution { public int [] nextLargerNodes(ListNode head) { List<Integer> list = new ArrayList<>(); while (head!=null ){ list.add(head.val); head = head.next; } int [] result = new int [list.size()]; Stack<Integer> stack = new Stack<>(); for (int i = 0 ; i < list.size(); i++) { while (!stack.empty() && list.get(stack.peek()) < list.get(i)) { result[stack.pop()] = list.get(i); } stack.push(i); } while (!stack.empty()){ result[stack.pop()] = 0 ; } return result; } } class Solution { public int [] nextLargerNodes(ListNode head) { if (head == null ) { return new int []{}; } List<Integer> list = new ArrayList<>(); while (head != null ) { list.add(head.val); head = head.next; } int [] result = new int [list.size()]; Stack<Integer> stack = new Stack<>(); for (int i = list.size() - 1 ; i >= 0 ; i--) { while (!stack.isEmpty() && stack.peek() <= list.get(i)) { stack.pop(); } result[i] = stack.isEmpty() ? 0 : stack.peek(); stack.push(list.get(i)); } return result; } }
分隔链表 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 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 class Solution { public ListNode[] splitListToParts(ListNode root, int k) { ListNode[] lists = new ListNode[k]; ListNode ptr = root; int length = 0 ; while (ptr != null ) { length ++; ptr = ptr.next; } int numOfPart = length / k; int numOfPlusOne = length % k; int index; for (index = 0 ; index < numOfPlusOne; index++) { lists[index] = root; ListNode pre = null ; for (int i = 0 ; i <= numOfPart; i++) { pre = root; root = root.next; } pre.next = null ; } while (root != null ) { lists[index++] = root; ListNode pre = null ; for (int i = 0 ; i < numOfPart; i++) { if (root == null ) break ; pre = root; root = root.next; } pre.next = null ; } for (index = index; index < k; index ++) { lists[index] = null ; } return lists; } } class Solution { public ListNode[] splitListToParts(ListNode root, int k) { ListNode[] lists = new ListNode[k]; ListNode ptr = root; int length = 0 ; while (ptr != null ) { length ++; ptr = ptr.next; } int width = length / k; int remainer = length % k; for (int i = 0 ; i < k; i ++) { lists[i] = root; if (root == null ) continue ; ListNode pre = null ; for (int j = 0 ; j < (remainer > 0 ? width + 1 : width); j ++){ pre = root; root = root.next; } remainer--; pre.next = null ; } return lists; } }
环形链表 找到环形链表的第一个入环节点
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 51 52 53 54 55 56 57 58 59 public class Solution { public ListNode detectCycle (ListNode head) { Set<ListNode> set = new HashSet<>(); while (head != null ) { if (!set.add(head)) { return head; } head = head.next; } return null ; } } public class Solution { public ListNode detectCycle (ListNode head) { ListNode inteact = getInteractNode(head); if (inteact == null ) { return null ; } else { ListNode res = head; while (res != inteact) { inteact = inteact.next; res = res.next; } return res; } } public ListNode getInteractNode (ListNode head) { if (head == null ) return null ; ListNode fast = head, slow = head; while (fast != null && fast.next != null ) { slow = slow.next; fast = fast.next.next; if (fast == slow) { return fast; } } return null ; } }
反转链表II 反转从链表从 m-n 的节点(要求一趟扫描完成)
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 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 class Solution { public ListNode reverseBetween (ListNode head, int m, int n) { if (head == null ) return null ; int index = 1 ; ListNode pre = null , cur = head; while (index < m) { pre = cur; cur = cur.next; index ++; } ListNode reversPre = null , reverseCur = cur, tmp = null ; while (index <= n) { tmp = reverseCur.next; reverseCur.next = reversPre; reversPre = reverseCur; reverseCur = tmp; index ++; } if (pre != null ) { pre.next = reversPre; } else { head = reversPre; } cur.next = reverseCur; return head; } } class Solution { public ListNode reverseBetween (ListNode head, int m, int n) { if (m == 1 ) { return reverseN(head, n); } else { ListNode res = reverseBetween(head.next, m - 1 , n - 1 ); head.next = res; return head; } } ListNode post = null ; ListNode reverseN (ListNode head, int n) { if (n == 1 ) { post = head.next; return head; } ListNode res = reverseN(head.next, n - 1 ); head.next.next = head; head.next = post; return res; } }
扁平化多级双向链表 多级双向链表中,除了指向下一个节点和前一个节点指针之外,它还有一个子链表指针,可能指向单独的双向链表。这些子列表也可能会有一个或多个自己的子项,依此类推,生成多级数据结构,如下面的示例所示。
给你位于列表第一级的头节点,请你扁平化列表,使所有结点出现在单级双链表中。
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 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 class Solution { public Node flatten (Node head) { if (head == null ) return null ; Node nextNode = flatten(head.next); Node childNode = flatten(head.child); if (childNode == null ) { head.next = nextNode; if (nextNode != null ) { nextNode.prev = head; } } else { head.next = childNode; childNode.prev = head; while (childNode.next != null ) { childNode = childNode.next; } childNode.next = nextNode; if (nextNode != null ) { nextNode.prev = childNode; } head.child = null ; } return head; } } class Solution { public Node flatten (Node head) { if (head == null ) return null ; Node pre = null , cur = head; Stack<Node> stack = new Stack<>(); stack.push(head); while (!stack.isEmpty()) { cur = stack.pop(); if (pre != null ) { pre.next = cur; } cur.prev = pre; if (cur.next != null ) { stack.push(cur.next); } if (cur.child != null ) { stack.push(cur.child); cur.child = null ; } pre = cur; } return head; } }
删除排序链表中的重复节点II 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 51 52 53 54 55 56 57 58 59 class Solution { public ListNode deleteDuplicates (ListNode head) { if (head == null ) return head; ListNode cur = head, pre = null ; while (cur != null ) { ListNode ptr = cur; int count = 0 ; while (ptr != null && ptr.val == cur.val) { count ++; ptr = ptr.next; } if (count > 1 ) { if (pre == null ) { head = ptr; } else { pre.next = ptr; } } else { pre = cur; } cur = ptr; } return head; } } class Solution { public ListNode deleteDuplicates (ListNode head) { if (head == null || head.next == null ) return head; if (head.val != head.next.val) { head.next = deleteDuplicates(head.next); } else { ListNode nextNode = head; while (nextNode != null && nextNode.val == head.val) { nextNode = nextNode.next; } head = deleteDuplicates(nextNode); } return head; } }
链表相加 给定两个用链表表示的整数,每个节点包含一个数位。
这些数位是反向存放的,也就是个位排在链表首部。
编写函数对这两个整数求和,并用链表形式返回结果
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 class Solution { public ListNode addTwoNumbers (ListNode l1, ListNode l2) { ListNode dummy = new ListNode(0 ); ListNode ptr = dummy; int plus = 0 ; while (l1 != null || l2 != null || plus != 0 ) { int sum = 0 ; sum += l1 == null ? 0 : l1.val; sum += l2 == null ? 0 : l2.val; l1 = l1 == null ? null :l1.next; l2 = l2 == null ? null : l2.next; int cur = (sum + plus) % 10 ; plus = (sum + plus) / 10 ; ptr.next = new ListNode(cur); ptr = ptr.next; } return dummy.next; } }
删除链表中连续和为0的节点 给你一个链表的头节点 head,请你编写代码,反复删去链表中由 总和 值为 0 的连续节点组成的序列,直到不存在这样的序列为止。
删除完毕后,请你返回最终结果链表的头节点。
你可以返回任何满足题目要求的答案。
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 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 class Solution { public ListNode removeZeroSumSublists (ListNode head) { if (head == null ) return null ; ListNode next = removeZeroSumSublists(head.next); ListNode cur = next; int sum = head.val; while (cur != null && sum != 0 ) { sum += cur.val; cur = cur.next; } if (sum == 0 ) { head = cur; } else { head.next = next; } return head; } } class Solution { public ListNode removeZeroSumSublists (ListNode head) { ListNode dummy = new ListNode(0 ); dummy.next = head; Map<Integer, ListNode> map = new HashMap<>(); int sum = 0 ; ListNode ptr1 = dummy; while (ptr1 != null ) { sum += ptr1.val; map.put(sum, ptr1); ptr1 = ptr1.next; } sum = 0 ; ListNode ptr2 = dummy; while (ptr2 != null ) { sum += ptr2.val; ptr2.next = map.get(sum).next; ptr2 = ptr2.next; } return dummy.next; } }
二叉树中的链表 给你一棵以 root 为根的二叉树和一个 head 为第一个节点的链表。
如果在二叉树中,存在一条一直向下的路径,且每个点的数值恰好一一对应以 head 为首的链表中每个节点的值,那么请你返回 True ,否则返回 False 。
一直向下的路径的意思是:从树中某个节点开始,一直连续向下的路径。
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 class Solution { public boolean isSubPath (ListNode head, TreeNode root) { if (head == null ) return true ; if (root == null ) return false ; return isPath(head, root) || (isSubPath(head, root.left) || isSubPath(head, root.right)); } public boolean isPath (ListNode head, TreeNode root) { if (head == null ) return true ; if (root == null ) return false ; return head.val == root.val && (isPath(head.next, root.left) || isPath(head.next, root.right)); } }
删除链表倒数第N个节点 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 class Solution { public ListNode removeNthFromEnd (ListNode head, int n) { if (head == null ) return head; ListNode fast = head, slow = head, pre = null ; for (int i = 0 ; i < n; i++) { fast = fast.next; } while (fast != null ) { pre = slow; fast = fast.next; slow = slow.next; } if (pre == null ) { head = head.next; } else { pre.next = slow.next; } return head; } }
旋转链表 给定一个链表,旋转链表,将链表每个节点向右移动 k 个位置,其中 k 是非负数。
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 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 class Solution { public ListNode rotateRight (ListNode head, int k) { if (head == null || k == 0 ) return head; int length = 0 ; ListNode ptr = head; while (ptr != null ) { length ++; ptr = ptr.next; } int remain = k % length; if (remain == 0 ) return head; ListNode fast = head, slow = head, pre = null ; for (int i = 0 ; i < remain; i++) { fast = fast.next; } while (fast != null ) { pre = slow; fast = fast.next; slow = slow.next; } pre.next = null ; ListNode newHead = slow; while (slow != null ) { pre = slow; slow = slow.next; } pre.next = head; return newHead; } } class Solution { public ListNode rotateRight (ListNode head, int k) { if (head == null || k == 0 ) return head; ListNode tail = head; int length = 1 ; while (tail.next != null ) { tail = tail.next; length ++; } tail.next = head; int step = length - (k % length) - 1 ; for (int i = 0 ; i < step; i++) { head = head.next; } ListNode res = head.next; head.next = null ; return res; } }
K个一组翻转链表 要求空间复杂度为O(1)
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 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 class Solution { public ListNode reverseKGroup (ListNode head, int k) { if (head == null || k <= 1 ) return head; ListNode tail = head; int length = 1 ; while (tail != null && length < k) { tail = tail.next; length ++; } if (tail == null ) return head; ListNode nextHead = reverseKGroup(tail.next, k); ListNode pre = null , cur = head, tmp = null ; while (pre != tail) { tmp = cur.next; cur.next = pre; pre = cur; cur = tmp; } head.next = nextHead; return tail; } } class Solution { public ListNode reverseKGroup (ListNode head, int k) { if (head == null || k <= 1 ) return head; int length = 0 ; ListNode ptr = head; while (ptr != null ) { length ++; ptr = ptr.next; } int numOfParts = length / k; ListNode dummy = new ListNode(0 ); dummy.next = head; ListNode pre = dummy, kPre = dummy, cur = head, tmp = null ; for (int i = 0 ; i < numOfParts; i++) { ListNode futureTail = cur; for (int j = 0 ; j < k; j++) { tmp = cur.next; cur.next = pre; pre = cur; cur = tmp; } kPre.next = pre; kPre = futureTail; } if (kPre != null ) kPre.next = cur; return dummy.next; } }
合并K个排序链表 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 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 class Solution { public ListNode mergeKLists (ListNode[] lists) { List<ListNode> list = new ArrayList<>(); for (ListNode head : lists) { list.add(head); } return recursiveMergeKLists(list); } public ListNode recursiveMergeKLists (List<ListNode> lists) { if (lists.size() == 0 ) return null ; ListNode currentHead = lists.get(0 ); lists.remove(0 ); ListNode sortedHead = recursiveMergeKLists(lists); ListNode dummy = new ListNode(0 ); ListNode cur = dummy; while (currentHead != null && sortedHead != null ) { if (currentHead.val <= sortedHead.val) { cur.next = currentHead; currentHead = currentHead.next; } else { cur.next = sortedHead; sortedHead = sortedHead.next; } cur = cur.next; } cur.next = currentHead != null ? currentHead : sortedHead; return dummy.next; } } class Solution { public ListNode mergeKLists (ListNode[] lists) { return recursiveMergeKLists(lists, 0 , lists.length - 1 ); } public ListNode recursiveMergeKLists (ListNode[] lists, int l , int r) { if (l == r) return lists[l]; if (l > r) return null ; int mid = (l + r) / 2 ; ListNode leftHead = recursiveMergeKLists(lists, l , mid); ListNode rightHead = recursiveMergeKLists(lists, mid + 1 , r); ListNode dummy = new ListNode(0 ); ListNode cur = dummy; while (leftHead != null && rightHead != null ) { if (leftHead.val <= rightHead.val) { cur.next = leftHead; leftHead = leftHead.next; } else { cur.next = rightHead; rightHead = rightHead.next; } cur = cur.next; } cur.next = leftHead != null ? leftHead : rightHead; return dummy.next; } } class Solution { public ListNode mergeKLists (ListNode[] lists) { if (lists.length == 0 ) return null ; PriorityQueue<ListNode> queue = new PriorityQueue<>(lists.length, (ListNode o1, ListNode o2) -> (o1.val - o2.val)); for (ListNode head : lists) { if (head == null ) continue ; queue.add(head); } ListNode dummy = new ListNode(0 ); ListNode cur = dummy; while (!queue.isEmpty()) { cur.next = queue.poll(); cur = cur.next; if (cur.next != null ) queue.add(cur.next); } return dummy.next; } }
单调栈 柱状图中的最大矩形 给定 n 个非负整数,用来表示柱状图中各个柱子的高度。每个柱子彼此相邻,且宽度为 1 。
求在该柱状图中,能够勾勒出来的矩形的最大面积。
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 class Solution { public int largestRectangleArea (int [] heights) { int area = 0 ; for (int i = 0 ; i < heights.length; i++) { int height = heights[i]; int left = i, right = i; while (left >= 0 && heights[left] >= height) { left --; } while (right <= heights.length - 1 && heights[right] >= height) { right ++; } area = Math.max(area, height * (right - left - 1 )); } return area; } } class Solution { public int largestRectangleArea (int [] heights) { int area = 0 ; int [] copyHeights = new int [heights.length + 2 ]; System.arraycopy(heights, 0 , copyHeights, 1 , heights.length); Stack<Integer> stack = new Stack<>(); for (int i = 0 ; i < copyHeights.length; i++) { while (!stack.isEmpty() && copyHeights[stack.peek()] > copyHeights[i]) { int height = copyHeights[stack.pop()]; int width = i - stack.peek() - 1 ; area = Math.max(area, height * width); } stack.push(i); } return area; } }
接雨水 给定一个直方图(也称柱状图),假设有人从上面源源不断地倒水,最后直方图能存多少水量?直方图的宽度为 1。
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 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 class Solution { public int trap (int [] height) { int volumn = 0 ; for (int i = 0 ; i < height.length; i++) { int leftMax = height[i], rightMax = height[i]; for (int j = i; j >= 0 ; j--) { leftMax = Math.max(leftMax, height[j]); } for (int j = i; j < height.length; j++) { rightMax = Math.max(rightMax, height[j]); } int curHeight = rightMax > leftMax ? (leftMax - height[i]) : (rightMax - height[i]); volumn += curHeight; } return volumn; } } class Solution { public int trap (int [] height) { int volumn = 0 ; Stack<Integer> stack = new Stack<>(); for (int i = 0 ; i < height.length; i++) { while (!stack.isEmpty() && height[i] > height[stack.peek()]) { int curHeight = height[stack.pop()]; if (stack.isEmpty()) break ; int width = i - stack.peek() - 1 ; int boundHeight = Math.min(height[i], height[stack.peek()]); volumn += width * (boundHeight - curHeight); } stack.push(i); } return volumn; } } class Solution { public int trap (int [] height) { int left = 0 ; int right = height.length - 1 ; int rightMax = 0 , leftMax = 0 ; int volumn = 0 ; while (left <= right) { if (leftMax < rightMax) { if (height[left] >= leftMax) { leftMax = height[left]; } else { volumn += (leftMax - height[left]); } left ++; } else { if (height[right] >= rightMax) { rightMax = height[right]; } else { volumn += (rightMax - height[right]); } right --; } } return volumn; } }
Author:
Fortune
Permalink:
http://njussj.github.io/2020/06/29/LeetCode/
License:
Copyright (c) 2019 CC-BY-NC-4.0 LICENSE
Slogan:
Do you believe in DESTINY ?