LeetCode203 707链表

- 双向链表的使用
- 增加虚拟头节点方便操作
This commit is contained in:
whai 2023-12-27 11:06:00 +08:00
parent c707fd4ca2
commit 9385b628ad
4 changed files with 575 additions and 5 deletions

View 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);
}
}

View File

@ -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);
}
}

View 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);
*/

View 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;
}
}
}