链表的基础知识
单链表的写法:
public class ListNode{
public ListNode next;
int val;
public ListNode(){}
public ListNode(int val){this.val=val;}
public ListNode(int val,ListNode next)
{
this.val=val;
this.next=next;
}
- 如果要移除的元素位于头节点,那么需要将头结点位置往后移动一位
由上图可知当头节点为需要删除的元素时,先处理成头节点不是待删除元素的情形。使用while循环进行处理
while(head.val==val){
head=head.next;
}
完整的代码如下:
static ListNode removeElement(ListNode head,int val){
while(head!=null&&head.val==val){
head=head.next;
}
if(head==null)return head;
ListNode pre=head;
ListNode p=head.next;
while(p!=null){
if(p.val==val){
pre.next=p.next;
p=p.next;
}else{
p=p.next;
pre=pre.next;
}
}
return head;
}
- 上述方式在处理上需要单独将头节点符合情况的情形剔除,使用不便,可以使用虚拟节点
ListNode removeElements(ListNode head,int val){
//设置dummy节点
ListNode dummy=new ListNode(-1);
dummy.next=head;
ListNode pre=dummy;
ListNode p=head;
while(p!=null){
if(p.val==val){
pre.next=p.next;
p=p.next;
}else{
pre=pre.next;
p=p.next;
}
}
return dummy.next;
}
707设计链表
首先直接考虑的是不使用虚拟节点,直接使用单链表进行处理
class MyLinkedList {
ListNode listNode;
int length;
public MyLinkedList() {
this.length=0;
}
public int get(int index) {
if(listNode==null)return -1;
if(index>=0&&index<length) {
ListNode p = listNode;
for (int i = 0; i < index; i++) {
p = p.next;
}
return p.val;
}
return -1;
}
public void addAtHead(int val) {
if(listNode==null){
listNode=new ListNode(val);
length++;
}else{
ListNode list=new ListNode(val);
list.next=listNode;
listNode=list;
length++;
}
}
public void addAtTail(int val) {
if(listNode==null){
listNode=new ListNode(val);
length++;
}else{
ListNode p1=new ListNode(val);
ListNode p=listNode;
while(p.next!=null){
p=p.next;
}
p.next=p1;
length++;
}
}
public void addAtIndex(int index, int val) {
if(index<=0){
addAtHead(val);
}else if(index==length){
addAtTail(val);
}else if(index>length){
return;
}
else{
ListNode p1=new ListNode(val);
ListNode p=listNode;
int count=index;
for(int i=0;i<count-1;i++){
p=p.next;
}
ListNode temp=p.next;
p.next=p1;
p1.next=temp;
length++;
}
}
public void deleteAtIndex(int index) {
if(length<=0)return;
if(index>length-1||index<0){
return;
}else if(index==0){
listNode=listNode.next;
length--;
}else{
ListNode p=listNode;
for(int i=0;i<index-1;i++){
p=p.next;
}
p.next=p.next.next;
length--;
}
}
}
接下来考虑使用虚拟头节点
class MyLinkedList1{
ListNode head;//设置一个虚拟头节点
int length;//length长度仅仅与链表的实际长度有关
public MyLinkedList1() {
this.length=0;
head=new ListNode(0);
}
public int get(int index) {
if(index<0||index>length-1){//最长的index到length-1
return -1;
}
else{
ListNode p=head;
for(int i=0;i<index+1;i++){
p=p.next;
}
return p.val;
}
}
public void addAtHead(int val) {
ListNode temp=head.next;
head.next=new ListNode(val);
head.next.next=temp;
length++;
}
public void addAtTail(int val) {
ListNode p=head;
for(int i=0;i<length;i++){
p=p.next;
}
p.next=new ListNode(val);
length++;
}
public void addAtIndex(int index, int val) {
if(index>length){
return ;
}else if(index==length){
addAtTail(val);
}
else if(index<=0){
addAtHead(val);
}else{
ListNode p1=new ListNode(val);
ListNode p=head;
for(int i=0;i<index;i++){
p=p.next;
}
ListNode temp=p.next;
p.next=p1;
p1.next=temp;
length++;
}
}
public void deleteAtIndex(int index) {
if(length<=0)return;
if(index>length-1||index<0){
return;
}else if(index==0){
head.next=head.next.next;
length--;
}else{
ListNode p=head;
for(int i=0;i<index;i++){
p=p.next;
}
p.next=p.next.next;
length--;
}
}
}
双链表的写法:
class DoubleListNode{
int val;
DoubleListNode pre;
DoubleListNode next;
public DoubleListNode(){}
public DoubleListNode(int val){
this.val=val;
}
}
- 翻转链表有几种解题思路,一种是双指针法
思路为:每两个节点都交换一次方向位置,必须保存相邻两个位置的节点,方便节点next的交换
public ListNode reverseList(ListNode head) {
ListNode pre=null;
ListNode cur=head;
while(cur!=null){
ListNode temp=cur.next;
cur.next=pre;
pre=cur;
cur=temp;
}
return pre;
}
- 一种为递归法,从底向上递归
public ListNode reverseList(ListNode head) {
if(head==null)return head;
if(head.next==null) return head;
ListNode list= reverseList(head.next);
head.next.next=head;
head.next=null;
return list;
}