diff --git a/src/main/java/cn/whaifree/leetCode/easy/LeetCode203.java b/src/main/java/cn/whaifree/leetCode/easy/LeetCode203.java new file mode 100644 index 0000000..a434b79 --- /dev/null +++ b/src/main/java/cn/whaifree/leetCode/easy/LeetCode203.java @@ -0,0 +1,186 @@ +package cn.whaifree.leetCode.easy; + + +import cn.whaifree.leetCode.model.ListNode; +import org.junit.Test; + +/** + * 链表 + * + * 203. 移除链表元素 + * 示例 1: + + * 输入:head = [1,2,6,3,4,5,6], val = 6 + * 输出:[1,2,3,4,5] + * 示例 2: + * + * 输入:head = [], val = 1 + * 输出:[] + * 示例 3: + * + * 输入:head = [7,7,7,7], val = 7 + * 输出:[] + * + */ +public class LeetCode203 { + + +// /** +// * [6] 6 +// * [] 6 +// * [2] 6 +// * +// * +// * @param head +// * @param val +// * @return +// */ +// public ListNode removeElements(ListNode head, int val) { +// +// // 如果链表只有一个节点或者没有要删除的元素,则直接返回原链表 +// if (head == null) { +// return head; +// } +// if (head.next == null && head.val == val) { +// head = null; +// return head; +// } else if (head.next == null) { +// return head; +// } +// +// // 定义一个指针pre指向head节点 +// // 定义一个指针index指向head.next节点 +// ListNode pre = head; +// ListNode index = head.next; +// +// // 遍历链表,直到index.next为null +// while (index.next != null) { +// +// // 如果index节点的值等于要删除的元素val +// if (index.val == val) { +// +// // 删除该节点 +// pre.next = index.next; +// +// // 将指针index移动到下一个节点 +// index = pre.next; +// +// // 将指针pre移动到下一个节点 +// pre = pre.next; +// +// // 继续遍历链表 +// continue; +// } +// +// // 如果index节点的值不等于要删除的元素val +// index = index.next; +// pre = pre.next; +// } +// // 尾巴节点为val,那就删除尾巴节点 +// if (index.val == val) { +// pre.next = null; +// } +// // 如果头节点的值等于要删除的元素val +// if (head.val == val) { +// head = head.next; +// } +// +// +// // 返回删除元素后的链表 +// return head; +// } + + + public ListNode removeElements1(ListNode head, int val) { + // 找到第一个head不删除的点 删除头结点时另做考虑 + while (head != null && head.val == val) { + head = head.next; + } + // 保证删完后不为空 + if(head==null) + return head; + // + ListNode index = head; + + while (index.next != null) { + if (index.next.val == val) { + index.next = index.next.next; + } else { + index = index.next; + } + } + return head; + } + +// /** +// * 递归 +// * @param head +// * @param val +// * @return +// */ +// public ListNode removeElements(ListNode head, int val) { +// if (head == null) { +// return null; +// } +// head.next = removeElements(head.next, val); +// if (head.next.val == val) { +// return head.next.next; +// } else { +// return head.next; +// } +// } + + + /** + * 递归 + * 1. 停止条件 + * 2. 循环返回值 + * @param head + * @param val + * @return + */ + public ListNode removeElements(ListNode head, int val) { + if (head == null) { + return null; + } + // h + // 6 6 + // 让head 之后的元素交给下个递归 + head.next = removeElements(head.next, val); + if (head.val == val) { + return head.next; + } else { + return head; + } + + // 递归的返回值为head.next,即传入的下一结点; + // 如果匹配就返回当前结点;不匹配,返回的head就是前一结点了。 + // 压栈时的head.next为后一个结点;弹栈时的head.next就位后前一个结点 + } + + public ListNode removeElements3(ListNode head, int val) { + if (head == null) { + return head; + } + + // 1. 获取当前节点 + // 2. 递归next 6 6 + head.next = removeElements3(head.next, val); + if (head.val == val) { + return head.next; + } else { + return head; + } + } + + + + + @Test + public void Test() { + ListNode listNode = ListNode.listNodeFromArray(new int[]{6,6,6,6}); +// ListNode.printList(listNode); + ListNode listNode1 = removeElements(listNode, 6); + ListNode.printList(listNode1); + } +} diff --git a/src/main/java/cn/whaifree/leetCode/middle/LeetCode54.java b/src/main/java/cn/whaifree/leetCode/middle/LeetCode54.java index ed7209f..671b1f1 100644 --- a/src/main/java/cn/whaifree/leetCode/middle/LeetCode54.java +++ b/src/main/java/cn/whaifree/leetCode/middle/LeetCode54.java @@ -74,13 +74,81 @@ public class LeetCode54 { } + + /** + * 时间复杂度:O(mn)O(mn)O(mn),其中 mmm 和 nnn 分别是输入矩阵的行数和列数。矩阵中的每个元素都要被访问一次。 + * + * 空间复杂度:O(1)O(1)O(1)。除了输出数组以外,空间复杂度是常数。 + * + * @param matrix + * @return + */ + + public List spiralOrder1(int[][] matrix) { + int width = matrix[0].length; + int height = matrix.length; + List s = new ArrayList<>(width * height); + + if (height == 1) { + int[] line = matrix[0]; + for (int i : line) { + s.add(i); + } + return s; + } else if (width == 1) { + for (int[] ints : matrix) { + s.add(ints[0]); + } + return s; + } + + int loop = Math.min(width, height) / 2; + int start = 0; + int i = 0, j = 0; + while (start < loop) { + + for (i = start; i < width - start - 1; i++) { + s.add(matrix[start][i]); + } + + for (j = start; j < height - start - 1; j++) { + s.add(matrix[j][i]); + } + + for (; i >= start + 1; i--) { + s.add(matrix[j][i]); + } + + for (; j >= start + 1; j--) { + s.add(matrix[j][i]); + } + start++; + } + + if (width > height) { + if (height % 2 == 1) { + // 横向填充 + for (; i < width - start-1; i++) { + s.add(matrix[start][i + 1]); + } + } + } else { + if (width % 2 == 1) { + for (; j < height - start - 1; j++) { + s.add(matrix[j+1][i + 1]); + } + } + } + + return s; + + } @Test public void test() { - spiralOrder(new int[][]{ - {1,2,4}, - {5,6,8}, - {9,10,12} - + spiralOrder1(new int[][]{ + {1,2}, + {1,3}, + {1,3} }).forEach(System.out::println); } } diff --git a/src/main/java/cn/whaifree/leetCode/middle/LeetCode707.java b/src/main/java/cn/whaifree/leetCode/middle/LeetCode707.java new file mode 100644 index 0000000..51f1fe5 --- /dev/null +++ b/src/main/java/cn/whaifree/leetCode/middle/LeetCode707.java @@ -0,0 +1,267 @@ +package cn.whaifree.leetCode.middle; + +import org.junit.Test; + +/** + * 707. 设计链表 + * 中等 + * 相关标签 + * 相关企业 + * 你可以选择使用单链表或者双链表,设计并实现自己的链表。 + * + * 单链表中的节点应该具备两个属性:val 和 next 。val 是当前节点的值,next 是指向下一个节点的指针/引用。 + * + * 如果是双向链表,则还需要属性 prev 以指示链表中的上一个节点。假设链表中的所有节点下标从 0 开始。 + * + * 实现 MyLinkedList 类: + * + * MyLinkedList() 初始化 MyLinkedList 对象。 + * int get(int index) 获取链表中下标为 index 的节点的值。如果下标无效,则返回 -1 。 + * void addAtHead(int val) 将一个值为 val 的节点插入到链表中第一个元素之前。在插入完成后,新节点会成为链表的第一个节点。 + * void addAtTail(int val) 将一个值为 val 的节点追加到链表中作为链表的最后一个元素。 + * void addAtIndex(int index, int val) 将一个值为 val 的节点插入到链表中下标为 index 的节点之前。如果 index 等于链表的长度,那么该节点会被追加到链表的末尾。如果 index 比长度更大,该节点将 不会插入 到链表中。 + * void deleteAtIndex(int index) 如果下标有效,则删除链表中下标为 index 的节点。 + * + * + * 示例: + * + * 输入 + * ["MyLinkedList", "addAtHead", "addAtTail", "addAtIndex", "get", "deleteAtIndex", "get"] + * [[], [1], [3], [1, 2], [1], [1], [1]] + * 输出 + * [null, null, null, null, 2, null, 3] + * + * 解释 + * MyLinkedList myLinkedList = new MyLinkedList(); + * myLinkedList.addAtHead(1); + * myLinkedList.addAtTail(3); + * myLinkedList.addAtIndex(1, 2); // 链表变为 1->2->3 + * myLinkedList.get(1); // 返回 2 + * myLinkedList.deleteAtIndex(1); // 现在,链表变为 1->3 + * myLinkedList.get(1); // 返回 3 + */ +public class LeetCode707 { + + @Test + public void test() { + MyLinkedList myLinkedList = new MyLinkedList(); + myLinkedList.addAtHead(4); + myLinkedList.get(1); + myLinkedList.addAtHead(1); + myLinkedList.addAtHead(5); + myLinkedList.deleteAtIndex(3); + myLinkedList.addAtHead(7); + myLinkedList.get(3); + myLinkedList.get(3); + myLinkedList.get(3); + + myLinkedList.addAtHead(1); + myLinkedList.deleteAtIndex(4); + } + +} + +class ListNode1{ + int val; + ListNode1 next; + + public ListNode1() { + } + + public ListNode1(int val, ListNode1 next) { + this.val = val; + this.next = next; + } +} + +/** + * 过了 但效果不好 + * + * 执行用时分布11ms + * 击败12.61%使用 Java 的用户 + * + * 消耗内存分布44.49MB + * 击败5.02%使用 Java 的用户 + */ +class MyLinkedList1 { + + ListNode1 head; + public MyLinkedList1() { + head = null; + } + + // 0 + public int get(int index) { + if (index < 0) { + return -1; + } + ListNode1 node = head; + int i = 0; + while (node != null) { + if (i++ == index) { + return node.val; + } + node = node.next; + } + return -1; + } + + public void addAtHead(int val) { + head = new ListNode1(val, head); + } + + public void addAtTail(int val) { + if (head == null) { + head = new ListNode1(val, null); + return; + } + ListNode1 node = head; + while (node.next != null) { + node = node.next; + } + node.next = new ListNode1(val, null); + } + + public void addAtIndex(int index, int val) { + if (index == 0) { + addAtHead(val); + return; + } + ListNode1 node = head; + int i = 0; + while (node != null) { + if (i++ == index - 1) { + node.next = new ListNode1(val, node.next); + return; + } + node = node.next; + } + } + + public void deleteAtIndex(int index) { + if (index == 0) { + // 头删 + head = head.next; + return; + } + ListNode1 node = head; + int i = 0; + while (node != null) { + if (i++ == index - 1 && node.next != null) { + node.next = node.next.next; + } + node = node.next; + } + } +} + +class ListNode{ + int val; + ListNode next; + + public ListNode() { + } + + public ListNode(int val, ListNode next) { + this.val = val; + this.next = next; + } +} + +/** + * 执行用时分布9ms + * 击败88.60%使用 Java 的用户 + * + * 消耗内存分布44.44MB + * 击败5.02%使用 Java 的用户 + */ +class MyLinkedList { + + int size; + ListNode head; + + public MyLinkedList() { + head = null; + size = 0; + } + + public int get(int index) { + if (index < 0 || index > size - 1) { + return -1; + } + ListNode node = head; + for (int i = 0; i < index; i++) { + node = node.next; + } + return node.val; + } + + public void addAtHead(int val) { + head = new ListNode(val, head); + size++; + } + + public void addAtTail(int val) { + addAtIndex(size, val); + } + + public void addAtIndex(int index, int val) { + if (index == 0) { + // 头插 + head = new ListNode(val, head); + size++; + return; + } + if (index < 0 || index > size) { + return; + } + + ListNode node = head; + int i = 0; + while (i++ < index - 1) { + node = node.next; + } + node.next = new ListNode(val, node.next); + size++; + } + + public void deleteAtIndex(int index) { + if (index < 0 || index > size - 1) { + return; + } + if (index == 0) { + // 头删 + head = head.next; + size--; + return; + } + + ListNode node = head; + int i = 0; + while (i++ < index - 1) { + node = node.next; + } + node.next = node.next.next; + size--; + } +} + +/** + * Your MyLinkedList object will be instantiated and called as such: + * MyLinkedList obj = new MyLinkedList(); + * int param_1 = obj.get(index); + * obj.addAtHead(val); + * obj.addAtTail(val); + * obj.addAtIndex(index,val); + * obj.deleteAtIndex(index); + */ + +/** + * Your MyLinkedList object will be instantiated and called as such: + * MyLinkedList obj = new MyLinkedList(); + * int param_1 = obj.get(index); + * obj.addAtHead(val); + * obj.addAtTail(val); + * obj.addAtIndex(index,val); + * obj.deleteAtIndex(index); + */ diff --git a/src/main/java/cn/whaifree/leetCode/model/ListNode.java b/src/main/java/cn/whaifree/leetCode/model/ListNode.java new file mode 100644 index 0000000..581da65 --- /dev/null +++ b/src/main/java/cn/whaifree/leetCode/model/ListNode.java @@ -0,0 +1,49 @@ +package cn.whaifree.leetCode.model; + +public class ListNode { + + public int val; + public ListNode next; + + public ListNode() {} + public ListNode(int val) { + this.val = val; + } + public ListNode(int val, ListNode next) { + this.val = val; this.next = next; + } + + /** + * 将给定的整数数组转换为链表,并返回链表的头节点。 + */ + public static ListNode listNodeFromArray(int[] nums) { + if (nums == null || nums.length == 0) { + return null; + } + + ListNode dummy = new ListNode(0); + ListNode head = dummy; + ListNode prev = dummy; + + for (int num : nums) { + ListNode node = new ListNode(num); + prev.next = node; + prev = node; + } + + return dummy.next; + } + + /** + * 输出链表的函数 + * @param head 链表的头节点 + */ + public static void printList(ListNode head) { + ListNode curr = head; + while (curr != null) { + System.out.print(curr.val + " "); + curr = curr.next; + } + + } +}