文章目录
- 一、链表基础
- 二、链表题(LeetCode)
-
- 1.找出两个链表的交点
- 2.合并两个有序链表
- 3.反转一个单链表(Easy,题号:206)
- 4.反转链表 II(Medium,题号:92)
- 5.删除排序链表中的重复元素(Easy,题号:83)
- 6.删除链表的倒数第N个节点(题号:19)
- 7.两两交换链表中的节点(题号:24)
- 8.两数(链表)相加 II(题号:445)
- 9. 回文链表(题号:234,Easy)
- 10.分隔链表(Medium,题号:86)
- 11.奇偶链表(Medium,题号:328)
- 12.移除链表元素(Easy,题号:3203)
- 13.两数相加(Medium,题号:2)
- 14.删除链表中的节点(Easy,题号:237)
- 15.旋转链表(Medium,题号:61)
一、链表基础
1.链表基础知识
参考网址:https://leetcode-cn.com/explore/learn/card/linked-list/
2.设计链表
函数实现的功能:
get(index):获取链表中第 index 个节点的值。如果索引无效,则返回-1。
addAtHead(val):在链表的第一个元素之前添加一个值为 val 的节点。插入后,新节点将成为链表的第一个节点。
addAtTail(val):将值为 val 的节点追加到链表的最后一个元素。
addAtIndex(index,val):在链表中的第 index 个节点之前添加值为 val 的节点。如果 index 等于链表的长度,则该节点将附加到链表的末尾。如果 index 大于链表长度,则不会插入节点。
deleteAtIndex(index):如果索引 index 有效,则删除链表中的第 index 个节点。
示例:
MyLinkedList linkedList = new MyLinkedList();
linkedList.addAtHead(1);
linkedList.addAtTail(3);
linkedList.addAtIndex(1,2); //链表变为1-> 2-> 3
linkedList.get(1); //返回2
linkedList.deleteAtIndex(1); //现在链表是1-> 3
linkedList.get(1); //返回3
具体设计代码如下:
class MyLinkedList {
ListNode head = null;
/** Initialize your data structure here. */
public MyLinkedList() {
}
/** Get the value of the index-th node in the linked list. If the index is invalid, return -1. */
public int get(int index) {
//获取index索引的节点值
int i=0;
while(head != null){
if(index == i){
return head.val;
}
else {
head = head.next;
i++;
}
}
return -1;
}
/** Add a node of value val before the first element of the linked list. After the insertion, the new node will be the first node of the linked list. */
public void addAtHead(int val) {
//添加头节点
if(head == null){
head = new ListNode(val);
}
else {
head.next = new ListNode(val);
}
}
/** Append a node of value val to the last element of the linked list. */
public void addAtTail(int val) {
//添加尾结点
ListNode cur = head;
while(cur.next != null){
cur = cur.next;
}
cur.next = new ListNode(val);
}
/** Add a node of value val before the index-th node in the linked list. If index equals to the length of linked list, the node will be appended to the end of linked list. If index is greater than the length, the node will not be inserted. */
public void addAtIndex(int index, int val) {
//在指定索引处添加节点
int i=0;
ListNode cur = head;
ListNode p = null;
while(cur != null){
if((index - 1) == -1){
addAtHead(val);
}
else if((index - 1) == i){
p = cur.next;
cur.next = new ListNode(val);
cur.next.next = p;
}
else if((index - 2) == i){
addAtTail(val);
}
i++;
cur = cur.next;
}
}
/** Delete the index-th node in the linked list, if the index is valid. */
public void deleteAtIndex(int index) {
//删除指定索引的节点
int i=0;
ListNode cur = head;
ListNode pre = null;
while(cur != null){
if(i == (index - 1)){
pre = cur;
cur = cur.next;
pre.next = cur.next;
}
i++;
cur = cur.next;
}
}
}
二、链表题(LeetCode)
1.找出两个链表的交点
1) 题目描述:
2) 解题思路:由于创建链表也是创建对象,所以存放在堆内存中,而"=="比较的是对象的内存地址,所以对于某两个节点的值相同并且下一个节点相同,但不一定是交点,因为它们的内存地址不同,不算是同一个节点。
3)代码:
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) {
* val = x;
* next = null;
* }
* }
*/
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
if(headA == null || headB == null)
return null;
ListNode pA = headA, pB = headB;
while(pA != pB) {
pA = pA == null ? headB : pA.next;
pB = pB == null ? headA : pB.next;
}
return pA;
}
leetcode版本:链表交点
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) {
* val = x;
* next = null;
* }
* }
*/
public class Solution {
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
ListNode p1 = headA;
ListNode p2 = headB;
int flag = 0;
while(p1 != null && p2 != null && flag <= 2){
if(p1 == p2)
return p1;
p1 = p1.next;
p2 = p2.next;
if(p1 == null){
p1 = headB;
flag++;
}
if(p2 == null){
p2 = headA;
flag++;
}
}
return null;
}
}
2.合并两个有序链表
题目链接:合并两个有序链表
1)题目描述:
将两个有序链表合并为一个新的有序链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。
2) 解题思路:
首先,创建的链表节点对象在堆内存中,并且节点之间不一定是占据连续内存,而是节点之间存在单向引用的关系。另外,只有代码new ListNode();是在堆内存中开辟空间从而创建节点,而ListNode p 则定义的是一个应用。这里使用头插法,首先创建一个头节点(这里为节点-1),然后创建相应类型的引用result指向头节点,再让引用p指向头节点,(这里的p和result都可以使用头节点的内容,比如使用p.val,p.next = l1等,可以直接修改,如例1),此时在l1和l2都不为空的情况下,比较l1与l2的值,若l1.val < l2.val,则让p的下一个节点,同时也是result引用指向的节点(即头节点)的下一个节点为l1,然后p指向p.next,此时p指向头节点的下一个节点;若l1.val > l2.val,原理相同。最后l1和l2其中有一个变为null了,此时未变为null的一串节点需要直接加到链表末端,所以让p.next = 剩下的非空链表,最后去掉头节点,返回result得到合并后的链表。
例1:
3)代码:
class Solution {
public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
ListNode result = new ListNode(-1); //设置一个头节点(在后面将会去掉)
ListNode p = result;
while(l1 != null && l2 != null){
if(l1.val < l2.val){
p.next = l1;
p = p.next;
l1 = l1.next;
}
else {
p.next = l2;
p = p.next;
l2 = l2.next;
}
}
if(l1 == null){
p.next = l2;
}
else if(l2 == null){
p.next = l1;
}
result = result.next; //去掉头节点
return result;
}
}
3.反转一个单链表(Easy,题号:206)
第2次
题目链接:反转一个单链表
题目描述:
反转一个单链表。
解题思路: