LeetCode203 707链表
- 双向链表的使用 - 增加虚拟头节点方便操作
This commit is contained in:
parent
c707fd4ca2
commit
9385b628ad
186
src/main/java/cn/whaifree/leetCode/easy/LeetCode203.java
Normal file
186
src/main/java/cn/whaifree/leetCode/easy/LeetCode203.java
Normal file
@ -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);
|
||||
}
|
||||
}
|
@ -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<Integer> spiralOrder1(int[][] matrix) {
|
||||
int width = matrix[0].length;
|
||||
int height = matrix.length;
|
||||
List<Integer> 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);
|
||||
}
|
||||
}
|
||||
|
267
src/main/java/cn/whaifree/leetCode/middle/LeetCode707.java
Normal file
267
src/main/java/cn/whaifree/leetCode/middle/LeetCode707.java
Normal file
@ -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);
|
||||
*/
|
49
src/main/java/cn/whaifree/leetCode/model/ListNode.java
Normal file
49
src/main/java/cn/whaifree/leetCode/model/ListNode.java
Normal file
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user