赞
踩
什么是链表
public class ListNode {
// 值
int val;
// 指针
ListNode next;
public ListNode() {
}
public ListNode(int val) {
this.val = val;
}
public ListNode(int val, ListNode next) {
this.val = val;
this.next = next;
}
}
删除节点
添加节点
性能分析
插入 /删除(时间复杂度) | 查询(时间复杂度) | 适用场景 | |
---|---|---|---|
数组 | O(n) | O(1) | 数据量固定,频繁查询,较少增删 |
链表 | O(1) | O(n) | 数据量不固定,频繁增删,较少查询 |
给你一个链表的头节点 head
和一个整数 val
,请你删除链表中所有满足 Node.val == val
的节点,并返回 新的头节点 。
/**
* head为链表的第一个结点
*/
class Solution {
public ListNode removeElements(ListNode head, int val) {
//1.生成待检测结点的前一个结点h,构造while结构
ListNode h=new ListNode(-1);
h.next=head;
//2.用待检测节点的前一个节点去遍历
ListNode buf=h;
while(buf.next!=null){
if(buf.next.val==val){
buf.next=buf.next.next;
}else{
buf=buf.next;
}
}
return h.next;
}
}
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
设计链表的实现。您可以选择使用单链表或双链表。单链表中的节点应该具有两个属性:val 和 next。val 是当前节点的值,next 是指向下一个节点的指针/引用。如果要使用双向链表,则还需要一个属性 prev 以指示链表中的上一个节点。假设链表中的所有节点都是 0-index 的。实现这些功能:
/**
* head:为空结点,next指向链表的第一个结点
*/
class MyLinkedList {
int size;
Node head;
public MyLinkedList() {
size=0;
head=new Node(0);
}
public int get(int index) {
if(index>=size || index<0 || size<=0) return -1;
Node node=head;
for(int i=0;i<=index;i++){
node=node.next;
}
return node.val;
}
public void addAtHead(int val) {
addAtIndex(0,val);
}
public void addAtTail(int val) {
addAtIndex(size,val);
}
public void addAtIndex(int index, int val) {
if(index>size) return;
index=Math.max(0,index);
size++; //注意:记得要size++
Node pres=head;
for(int i=0;i<index;i++){
pres=pres.next;
}
Node newNode=new Node(val);
newNode.next=pres.next;
pres.next=newNode;
}
public void deleteAtIndex(int index) {
if(index>=size || index<0 || size<=0) return;
size--;
Node pres=head;
for(int i=0;i<index;i++){
pres=pres.next;
}
Node node=pres.next;
pres.next=node.next;
node.next=null;
}
}
class Node{
int val;
Node next;
Node(int value){
this.val=value;
}
}
给你单链表的头节点 head
,请你反转链表,并返回反转后的链表。
/**
* 方式一:遍历:当反转结点为null时返回前驱节点
* head:链表的第一个结点
*/
class Solution {
public ListNode reverseList(ListNode head) {
//1.待反转结点的前结点
ListNode pre=null;
//2.待反转结点
ListNode node=head;
//3.待反转结点的后结点
ListNode next=null;
while(node!=null){
next=node.next;
//反转结点
node.next=pre;
pre=node;
node=next;
if(next!=null) next=next.next;
}
return pre;
}
}
/**
* 方式二:递归:当反转结点为null时返回前驱节点。
*/
class Solution {
public ListNode reverseList(ListNode head) {
return recursive(null,head);
}
public ListNode recursive(ListNode before,ListNode head){
if(head==null) return before;
ListNode after=head.next;
head.next=before;
return recursive(head,after);
}
}
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换)。
class Solution {
/**
* 版本一:虚拟头结点
* 结论:拿到待操作结点的前驱结点:即拿到所有所需结点
*/
public ListNode swapPairs(ListNode head) {
//1.前驱结点
ListNode front=new ListNode();
front.next=head;
//2.结果结点(虚拟结点):如果有交换便让front进行操作
ListNode result=front;
while(front.next!=null && front.next.next!=null){
ListNode after=head.next.next;
front.next=head.next;
head.next.next=head;
head.next=after;
front=head;
head=head.next;
}
return result.next;
}
/**
* 版本二:递归
* 结论:前两个结点指向递归结果
*/
public ListNode swapPairs(ListNode head) {
if(head==null || head.next==null) return head;
//保存后结点
ListNode after=head.next.next;
//保存右结点
ListNode right=head.next;
head.next.next=head;
head.next=swapPairs(after);
return right;
}
}
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
给你一个链表,删除链表的倒数第 n
个结点,并且返回链表的头结点。
/**
* 思路:双指针-在确认链表长度的同时确定待删除结点的前驱结点
*/
class Solution {
public ListNode removeNthFromEnd(ListNode head, int n) {
//1.待删除结点的前驱结点
ListNode front=new ListNode();
front.next=head;
//2.尾结点
ListNode tail=front;
//3.计算结点个数,前驱结点根据该数值移动
int count=0;
//4.结果结点
ListNode result=front;
while(tail.next!=null){
count++;
tail=tail.next;
if(count>n) front=front.next;
}
front.next=front.next.next;
return result.next;
}
}
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
给你两个单链表的头节点 headA
和 headB
,请你找出并返回两个单链表相交的起始节点。如果两个链表没有交点,返回 null
。
/**
* 思路:如果相交,即两链表尾部重合。所以应当从尾部长度相等开始判断是否相同。
*/
public class Solution {
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
ListNode node=null;
//计算链表A、链表B的长度
int lenA=0,lenB=0;
node=headA;
while(node!=null){
lenA++;
node=node.next;
}
node=headB;
while(node!=null){
lenB++;
node=node.next;
}
if(lenA==0 || lenB==0) return null;
//保证A链表为长链表
if(lenA<lenB){
node=headA;
headA=headB;
headB=node;
int buf=lenA;
lenA=lenB;
lenB=buf;
}
for(int i=0;i<lenA-lenB;i++){
headA=headA.next;
}
while(headA!=null){
if(headA==headB) return headA;
headA=headA.next;
headB=headB.next;
}
return null;
}
}
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) {
* val = x;
* next = null;
* }
* }
*/
给定一个链表的头节点 head
,返回链表开始入环的第一个节点。 如果链表无环,则返回 null
。不允许修改 链表
/**
解题思路:
1.假设慢指针走过的步数为 x+y ,快指针走过的步数则为 x+y+n(z+y)
2.当快、慢指针相遇时存在:2(x+y)=x+y+n(z+y)
3.到入口结点的步数:x+y=n(z+y) --> x=(z+y)(n-1)+z
所以,当n>=1时:从快、慢指针相遇结点和头结点head开始,每次走一步,两结点相遇的结点即为环形入口结点
*/
public class Solution {
public ListNode detectCycle(ListNode head) {
//1.慢指针
ListNode slow=head;
//2.快指针
ListNode fast=head;
//3.相遇结点
ListNode meet=null;
//4.入口结点
ListNode entrance=head;
while(head !=null && fast.next!=null && fast.next.next!=null){
slow=slow.next;
fast=fast.next.next;
if(slow==fast){
meet=fast;
break;
}
}
if(meet==null) return null;
while(meet!=head){
meet=meet.next;
head=head.next;
}
return head;
//存储走过的结点,判断当前结点是否走过
// Set<ListNode> set=new HashSet();
// while(head!=null){
// if(!set.contains(head)){
// set.add(head);
// head=head.next;
// }
// else return head;
// }
// return null;
}
}
/**
* Definition for singly-linked list.
* class ListNode {
* int val;
* ListNode next;
* ListNode(int x) {
* val = x;
* next = null;
* }
* }
*/
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。