203移除链表元素
删除链表中所有值为val的节点
我的题解:
class Solution {
public ListNode removeElements(ListNode head, int val) {
ListNode left = head;
while (left!=null&&left.val==val){
left = left.next;
}
ListNode newhead = left;
if (newhead==null){
return newhead;
}
ListNode right = left.next;
while (right!=null){
if (right.val==val) {
left.next = right.next;
}else {
left = left.next;
}
right = right.next;
}
return newhead;
}
}
查找值非val的第一个结点设为头结点,使用前后结点指针,用于删除值为val的结点。
看了其他题解
新创建一个无值意义的头结点,用于标记头结点,这样就无需查找值非val的第一个结点了。
class Solution {
public ListNode removeElements(ListNode head, int val) {
if(head == null){
return head;
}
ListNode virtualNode = new ListNode(-1, head);
ListNode pre = virtualNode;
ListNode cur = head;
while(cur != null){
if(cur.val == val){
pre.next = cur.next;
} else {
pre = cur;
}
cur = cur.next;
}
return virtualNode.next;
}
}
707设计链表
设计链表 实现 按下标查找 从头尾插入元素 按下标插入元素 删除元素 等功能
我的题解:
class MyLinkedList {
int val;
MyLinkedList next;
public MyLinkedList() {
}
public MyLinkedList(int val, MyLinkedList next) { this.val = val; this.next = next; }
public int get(int index) {
MyLinkedList node = this.next;
int num = 0;
while (node!=null){
if (num == index){
return node.val;
}
num++;
node = node.next;
}
return -1;
}
public void addAtHead(int val) {
MyLinkedList headnode = new MyLinkedList(val, this.next);
this.next = headnode;
}
public void addAtTail(int val) {
MyLinkedList node = this;
while (node.next!=null){
node = node.next;
}
MyLinkedList tailnode = new MyLinkedList(val, node.next);
node.next = tailnode;
}
public void addAtIndex(int index, int val) {
MyLinkedList node = this;
int num = -1;
while (node!=null){
if (num == index-1){
MyLinkedList indexnode = new MyLinkedList(val, node.next);
node.next = indexnode;
break;
}
num++;
node = node.next;
}
}
public void deleteAtIndex(int index) {
MyLinkedList prenode = this;
MyLinkedList node = this.next;
int num = 0;
while (node!=null){
if (num == index){
prenode.next = node.next;
break;
}
num++;
prenode = prenode.next;
node = node.next;
}
}
}
/**
* Your MyLinkedList object will be instantiated and called as such:
* MyLinkedList obj = new MyLinkedList();
* int param_1 = obj.get(index);
* obj.addAtHead(val);
* obj.addAtTail(val);
* obj.addAtIndex(index,val);
* obj.deleteAtIndex(index);
*/
用单链表直接就是从头往后找。。。暴力破解了属于
看了其他题解,
使用了另一个Node类作为结点具体内容的存储,List类只保存Node头结点的List容量大小,这样就可以直接判断下标是否合理,也可以直接按照尾部索引插入了
class LinkedNode {
int val;
LinkedNode next;
LinkedNode(){}
LinkedNode(int val) {
this.val = val;
this.next = null;
}
}
class MyLinkedList {
LinkedNode head;
int size;
public MyLinkedList() {
head = new LinkedNode(0);
size = 0;
}
public int get(int index) {
if (index < 0 || index >= size){
return -1;
}
LinkedNode cur = head;
for (int i = 0; i <= index; i++) {
cur = cur.next;
}
return cur.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 || index < 0) {
return;
}
LinkedNode cur = head;
for (int i = 0; i < index; i++) {
cur = cur.next;
}
LinkedNode toAdd = new LinkedNode(val);
toAdd.next = cur.next;
cur.next = toAdd;
size++;
}
public void deleteAtIndex(int index) {
if (index >= size || index < 0) {
return;
}
size--;
LinkedNode cur = head;
for (int i = 0; i < index; i++) {
cur = cur.next;
}
cur.next = cur.next.next;
}
}
双链表再和size结合,就可以看索引是离头结点近,还是尾结点近。
注意双链表,要创建头和尾两个哨兵结点。
class MyLinkedList {
int size;
ListNode head;
ListNode tail;
class ListNode{
int val;
ListNode prev;
ListNode next;
public ListNode(int val) {
this.val = val;
}
}
public MyLinkedList() {
size = 0;
head = new ListNode(0);
tail = new ListNode(0);
head.next = tail;
tail.prev = head;
}
public int get(int index) {
if(index<0||index>=size){
return -1;
}
ListNode cur;
//比较从head还是tail哪个更快找到目标
if(index+1<size-index){//head更快
cur=head;
for(int i=-1;i<index;i++){
cur=cur.next;
}
}else{//tail更快
cur=tail;
for(int i=size;i>index;i--){
cur=cur.prev;
}
}
return cur.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);
ListNode pred, succ;
if(index<size-index){
pred=head;
for(int i=-1;i<index-1;i++){
pred=pred.next;
}
succ=pred.next;
}else{
succ=tail;
for(int i=size;i>index;i--){
succ=succ.prev;
}
pred=succ.prev;
}
size++;
ListNode add=new ListNode(val);
add.prev=pred;
add.next=succ;
pred.next=add;
succ.prev=add;
}
public void deleteAtIndex(int index) {
if (index < 0 || index >= size) {
return;
}
ListNode pred, succ;
if (index < size - index) {
pred = head;
for (int i = 0; i < index; i++) {
pred = pred.next;
}
succ = pred.next.next;
} else {
succ = tail;
for (int i = size; i > index + 1; i--) {
succ = succ.prev;
}
pred = succ.prev.prev;
}
size--;
pred.next = succ;
succ.prev = pred;
}
}
206反转链表
返回反转后的链表
用循环解决:用3个指针解决,分别标志pre node next,然后node->pre pre变成node node变成next,直到尾
注意最后要把head的next置空
class Solution {
public ListNode reverseList(ListNode head) {
if (head==null){
return head;
}
ListNode prenode = head;
ListNode node = head.next;
while (node!=null){
ListNode nextnode = node.next;
node.next = prenode;
prenode = node;
node = nextnode;
}
head.next = null;
return prenode;
}
}
用递归解决
需要第二个函数用于递归,递归出口是到达尾结点,每个递归都返回next结点
在递归里,需要把返回的next结点的next改为此结点
注意最后要把head的next置空
class Solution {
public ListNode reverseList(ListNode head) {
if (head==null||head.next==null){
return head;
}
ListNode prenode = head;
while (prenode.next!=null){
prenode = prenode.next;
}
ListNode node = head;
reverse(node);
head.next = null;
return prenode;
}
public ListNode reverse(ListNode head) {
if (head.next==null){
return head;
}
ListNode node = reverse(head.next);
node.next = head;
return head;
}
}
收获
可以通过创建哨兵结点从而便于头结点处理
链表集合的概念,可以使用list类来存储头结点和大小