LeetCode算法刷题|第三天| 链表理论基础、 707.设计链表 、 206.反转链表

链表理论基础

1.分类:链表有单链表、双链表、循环链表
2.存储方式:相对于数组在内存中的连续存储,链表不是连续存储。
链表通过节点中的指针域,将内存中的各个节点连接起来,所以链表中的节点是散乱分布在内存中,分配机制取决于操作系统的内存管理。
如下图所示
在这里插入图片描述
3.链表操作
删除节点:将节点c的next指针指向e节点就行了。(如下图所示)
在这里插入图片描述
增加节点:将c节点的next指针指向新的节点就可。(如下图所示)
在这里插入图片描述
4、链表的定义

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

203.移除链表元素

题目链接/文章讲解/视频讲解:点击跳转

方法:1、使用原来的链表;2、使用虚拟头结点。

整体流程如下所示

1、删除开头所有等于 val 的节点:
	head -> [val] -> [val] -> [1] -> [2] -> [val] -> [3]
	 ↓变为
	head -> [1] -> [2] -> [val] -> [3]
2、遍历链表并删除中间等于 val 的节点:(使用 curr 作为遍历指针 curr == head)
	curr -> [1] -> [2] -> [val] -> [3]
	 ↓变为
	curr -> [1] -> [2] -> [3]

代码实现

//方法1:使用原链表操作1
public ListNode removeElements(ListNode head, int val) {
	//移除头结点为空或者头结点值与目标值相等的情况
	while (head != null && head.val == val) {
	    head = head.next;
	}
	
	ListNode curr = head;
	while (curr != null && curr.next != null) {
	    if (curr.next.val == val) {
	        curr.next = curr.next.next;
	    } else {
	        curr = curr.next;
	    }
	}
	
	return head;
	}
}
curr.next = curr.next.next;   这行代码有点绕,可以换一种方式实现。
//方法1:使用原链表操作2
 public ListNode removeElements(ListNode head, int val) {
	//移除头结点为空或者头结点值与目标值相等的情况 head != null && head.val == val
	 while (head != null && head.val == val) {
	     head = head.next;
	 }
	 //头结点为空,直接退出操作 head == null
	 if (head == null) {
	     return null;
	 }
	 //head != null && head.val != val
	 ListNode pre = head; //头节点
	 ListNode curr = head.next; //需要判断的节点
	 while (curr != null) {
	     if (curr.val == val) {
	         pre.next = curr.next; //移除链表中的数据
	     } else {
	         pre = curr; //头节点后移一位
	     }
	     curr = curr.next; // 遍历的节点位置后移一位
	 }
	 return head;
	}
//方法二: 使用虚拟有节点的方法,不用再考虑头节点的值与目标值相等的情况
public ListNode removeElements(ListNode head, int val) {
    ListNode dummy = new ListNode();
    dummy.next = head;

    ListNode curr = dummy;

    while (curr.next != null) {
        if (curr.next.val == val) {
            curr.next = curr.next.next;
        } else {
            curr = curr.next;
        }
    }
    return dummy.next;

707.设计链表

题目链接/文章讲解/视频讲解:点击此处跳转

思路:画一个链表图,模拟一下操作的过程。

class MyLinkedList {

      int size; //size存储链表元素的个数
      ListNode head; //虚拟头结点

      //初始化链表
      public MyLinkedList() {
          size = 0;
          head = new ListNode(0);
      }

      //获取第index个节点的数值,注意index是从0开始的,第0个节点就是头结点
      public int get(int index) {

          //特殊情况判断
          if (index < 0 || index >= size) {
              return -1;
          }

          ListNode currentNode = head;
          for (int i = 0; i <= index; i++) {
              currentNode = currentNode.next;
          }
          return currentNode.val;
      }

      public void addAtHead(int val) {
          ListNode newNode = new ListNode(val);
          newNode.next = head.next;
          head.next = newNode;
          size++;
          // 在链表最前面插入一个节点,等价于在第0个元素前添加
          // addAtIndex(0, val);
      }

      public void addAtTail(int val) {
          ListNode newNode = new ListNode(val);
          ListNode cur = head;
          while (cur.next != null) {
              cur = cur.next;
          }

          cur.next = newNode;
          size++;

          // 在链表的最后插入一个节点,等价于在(末尾+1)个元素前添加
          // addAtIndex(size, val);
      }

      public void addAtIndex(int index, int val) {
          //插入位置大于链表长度,该数据不会插入
          if (index > size) {
              return;
          }
          //插入位置小于链表的长度, 插入的位置为0
          if (index < 0) {
              index = 0;
          }
          size++;
          //找到要插入位置的前一个节点
          ListNode pre = head;
          for (int i = 0; i < index; i++) {
              pre = pre.next;
          }
          //插入节点
          ListNode addNode = new ListNode(val);
          addNode.next = pre.next;
          pre.next = addNode;
      }

      public void deleteAtIndex(int index) {
          //下标无效的情况
          if (index < 0 || index >= size) {
              return;
          }
          //下标有效,删除改下标的元素
          //因为有虚拟头节点,所以不用对Index=0的情况进行特殊处理
          ListNode pre = head;
          size--;
          for (int i = 0; i < index; i++) {
              pre = pre.next;
          }
          pre.next = pre.next.next;
      }
  }

206.反转链表

题目链接/文章讲解/视频讲解:点击此处跳转

思路:使用双指针,只需要改变链表的next指针的指向,直接将链表反转 ,而不用重新定义一个新的链表。

代码如下

public ListNode reverseList(ListNode head) {
		
		ListNode cur = head;
		ListNode pre = null;
		ListNode temp = null;

		while(cur != null){
			temp = cur.next; //保存节点
			cur.next = pre; //反转指针
			pre =cur; //pre指针向后移
			cur = temp; //cur指针向后移动
		}
		return pre;
    }
  • 7
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值