算法基础之数据结构——链表

数据结构之链表


【写在前面】所有LeetCode题的题目都去原网站看

  • 单链表
  • 双链表

一、单链表

1、添加操作

  • ① 使用给定值初始化新节点cur

在这里插入图片描述

  • ② 将cur节点的next链接到prev的下一个节点later

在这里插入图片描述

  • ③ 将prev节点的next链接到cur节点

在这里插入图片描述

2、开头添加节点

  • ① 初始化一个新的节点cur

在这里插入图片描述

  • ② 将cur的next链接到head

在这里插入图片描述

  • ③ 将cur更改为head

在这里插入图片描述

3、删除节点操作

  • ① 找到cur节点的上一个节点prev及其下一个节点later

  • ② 将prev的next节点链接到later

在这里插入图片描述

4、删除开头节点

  • 简单的,直接将第二个节点指定为head

在这里插入图片描述

5、设计单链表(LeetCode 707

// 链表类,定义构造方法
public class ListNode{
   
	int val;
	ListNode next;
	ListNode(int x){
   
		val = x;
	}
}

// 设计单链表类
Class MyLinkedList{
   
	int size;
	ListNode head;
	public MyLinkedList(){
   
		size = 0;
		head = new ListNode(0);
	}

	// 获得索引指定值
	public int get(int index){
   
		if(index < 0 || index >= size) return -1;
		ListNode cur = head;
		for(int i = 0; i < index; ++i) cur = cur.next;
		return cur.val;
	}
	
	// 添加头节点(索引为0)
	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 < 0) index = 0;
		if(index > size) return;
		
		++size;
		// 创建前节点
		ListNode pred = head;
		// 将前节点移动到索引指定节点
		for(int i = 0; i < index; ++i) pred = pred.next;
		// 根据值,创建要添加的节点
		ListNode toAdd = new ListNode(val);
		// 首先,将toAdd节点链接到pred节点的下一个节点
		toAdd.next = pred.next;
		// 最后,将pred节点链接到toAdd节点
		pred.next = toAdd;
	}
	
	// 根据索引,删除节点
	public void deleteAtIndex(int index){
   
		if(index < 0 || index >= size) return;
		size--;
		ListNode pred = head;
		for(int i = 0; i < index; ++i) pred = pred.next;
		// 直接将当前节点链接到下个节点的下个节点
		pred.next = pred.next.next;
	}
}

二、链表双指针

1、环形链表

方法1——哈希表

public boolean hasCycle(ListNode head){
   
	// 创建链表节点集合
	Set<ListNode> seen = new HashSet<ListNode>();
	while(head != null){
   
		if(!seen.add(head)){
   
			return true;
		}
		head = head.next;
	}
	return false;
}

方法2——快慢指针(改进)

public boolean hasCycle(ListNode head){
   
	if(head == null || head.next == null){
   
		return false;
	}
	ListNode slow = head;
	ListNode fast = head.next;
	while(slow != fast){
   
		if(fast == null || fast.next == null){
   
			return false;
		}
		slow = slow.next;
		fast = fast.next.next;
	}
	return true;
}

2、相交链表(LeetCode 160

方法1——暴力法

  • 对链表A中的每一个节点ai,遍历链表B并检查是否有bj = ai
  • 时间复杂度:O(m*n)
  • 空间复杂度:O(1)

方法2——哈希表法

  • 将链表A每个节点存入哈希表,再检查链表B
  • 时间复杂度:O(m+n)
  • 空间复杂度:O(n)或O(n)

方案3——双指针法

  • 将链表A与链表B互相接到后面,形成A-B链表、形成B-A链表,利用双指针遍历
    在这里插入图片描述
  • 时间复杂度:O(m+n)
  • 空间复杂度:O(1)
public ListNode getIntersectionNode(ListNode headA, ListNode headB){
   
	if(headA == null || headB == null) return null;
	// 创建链表A、B的'指针'节点
	ListNode pA = headA, pB = headB
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值