移除链表元素 LeetCode 203
题目链接:LeetCode 203 - 简单
思路
看到移除链表中的元素,就直接考虑使用虚拟头指针。
O(n)时间复杂度:
java
/**
* 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 removeElements(ListNode head, int val) {
ListNode headNode = new ListNode(0,head);
ListNode pre = headNode;
ListNode next = head;
while(next != null){
if(next.val == val){
pre.next = next.next;
next = pre.next;
continue;
}
pre = next;
next = pre.next;
}
return headNode.next;
}
}
总结
有不使用虚拟头结点的方法,即用while判断头结点的值是否为val
设计链表 LeetCode 707
题目链接:LeetCode 707 - 中等
思路
看到链表设计的题目时,只想到addAtHead和addAtTail可以使用addAtIndex。
单链表:
java
class ListNode{
int val;
ListNode next;
ListNode(){}
ListNode(int val){
this.val = val;
}
}
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 currNode=head;
for(int i=0;i<=index;i++){
currNode = currNode.next;
}
return currNode.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;
}
size++;
if(index<0){
index=0;
}
ListNode currNode = head;
for(int i=0;i<index;i++){
currNode = currNode.next;
}
ListNode temp = new ListNode(val);
temp.next = currNode.next;
currNode.next = temp;
}
public void deleteAtIndex(int index) {
if(index<0 || index>=size){
return;
}
size--;
ListNode currNode = head;
for(int i=0;i<index;i++){
currNode = currNode.next;
}
currNode.next = currNode.next.next;
}
}
总结
- 分为单链表和双链表两种解题方式。
- 写代码时没有考虑要定义一个ListNode类,这是其一。其二对于index何时等于,何时不取到思维混乱。其三,没有充分考虑到size的增加减少,这是很重要的考虑问题。
反转链表 LeetCode 206
题目链接:LeetCode 206 - 简单
思路
刚看到反转链表的时候打算使用双指针和虚拟头节点,但是这样子有些繁琐,并且不太便于书写代码。如果选择一个temp节点来存储cur.next的话,在代码书写上会更加简洁。这道题属于高频题。
该题有两种解题思路,递归和遍历。
该题使用遍历的方式会比使用递归的方式更加好写一些。 主要就是: 在遍历链表时 ①存储当前节点的后一个节点(next=cur.next) ②将当前节点的next指针指向前一个节点(cur.next=pre) ③将当前的节点存储为pre ④将next节点存储到cur中
最后返回新的头结点
遍历:
class Solution {
public ListNode reverseList(ListNode head) {
ListNode pre = null;
ListNode cur = head;
while(cur!=null){
ListNode next = cur.next;
cur.next = pre;
pre = cur;
cur = next;
}
return pre;
}
}
该反转链表使用递归的话:
1.确定递归终止条件:if(head==null||head.next==null){ return head;}
2.确定递归调用:反转链表
3.最后返回新的头结点
class Solution {
public ListNode reverseList(ListNode head) {
if(head==null||head.next==null){
return head;
}
ListNode newHead = reverseList(head.next);
head.next.next = head;
head.next = null;
return newHead;
}
}