1._203移除链表元素
标签:链表
思路:1.当作构建一个新的链表,设置一个newHead指向新链表的头,cur指向新链表的尾节点。
2.遍历整个链表,遇到与要删除的值相同的节点,跳过,不相同的加入到新链表中。
3.最后cur.next应该指向空
注意点:虚拟头节点的使用
代码:
public ListNode removeElements(ListNode head, int val) {
if(head == null) return null;
ListNode newHead = new ListNode(0);
ListNode cur = newHead;
while(head != null){
if(head.val != val){
cur.next = head;
cur = head;
}
head = head.next;
}
cur.next = null;
return newHead.next;
}
2.2_两数相加
标签:链表
思路:1.设置一个新的链表来表示它们的和,利用虚拟头节点,设置newHead指向新链表头部, newTail指向尾部。
2.依次遍历两个链表,将遍历的节点的值和category进位相加,new一个新的节点来存储和 的个位数(i %10),设置category为进位标志。若(i/10)>1 ,则进位。
3.结束条件:两个链表都为空。最后要判断一下进位标志。
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
if(l1 == null) return l2;
if(l2 == null) return l1;
int category = 0;//进位标志
ListNode newHead = new ListNode(0);
ListNode newTail = newHead;
while(l1 != null || l2 != null){ //如果l1或l2为空,该怎么处理?
int v1 = 0;
if(l1 != null){
v1 = l1.val;
l1 = l1.next;
}
int v2 = 0;
if(l2 != null){
v2 = l2.val;
l2= l2.next;
}
int result = v1 + v2 + category ;
newTail = newTail.next = new ListNode(result % 10);
category = result / 10;
}
if(category == 1){
newTail.next = new ListNode(1);
}
return newHead.next;
}
3._160相交链表
标签:链表 双指针
思路:1.将两个链表相加,使得两个链表的长度一致。
2.从头至尾遍历两个链表,比较两个链表的元素是否相等。
代码:
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
if(headA == null || headB == null) return null;
ListNode curA = headA;
ListNode curB = headB;
while(curA != curB ){
curA = (curA == null) ? headB : curA.next;
curB = (curB == null) ? headA : curB.next;
}
return curA;
}
4._86分隔链表
标签:链表
思路:1.可以想象成将链表分割成两个链表,比特定值小的在左链表,比特定值大的在右链表,最 后将两个链表连接在一起。
2.设置两个虚拟头节点,一个指向左链表,一个指向右链表,然后对左右链表进行添加。
注意点:右链表的尾节点要清空,这一句非常重要 //因为可能出现这样的情况:原链表倒数第N个节点A的值是>=x的,A后面所有节点的值都是<x的 //然后rTail.next最终其实就是A.next
代码:
public ListNode partition(ListNode head, int x) {
ListNode lHead = new ListNode(0);
ListNode lTail = lHead;
ListNode rHead = new ListNode(0);
ListNode rTail = rHead;
while(head != null){
if(head.val < x){//左链表
lTail.next = head;
lTail = head;
}else{
rTail.next = head;
rTail = head;
}
head = head.next;
}
rTail.next = null;
lTail.next = rHead.next;
return lHead.next;
}
5._234回文链表
标签:链表、双指针、反转链表、找链表中间元素
思路:找到中间节点,然后对中间结点右侧的节点进行翻转。最后遍历比较左右链表元素是否相 同。
代码:
public boolean isPalindrome(ListNode head) {
if(head == null || head.next == null) return true;
if(head.next.next == null) return head.val == head.next.val;
ListNode middleNode = FindMiddleNode(head);//找到中间结点
ListNode rHead = reverseList(middleNode.next);//翻转右边链表
while(rHead != null){
if(rHead.val != head.val) return false;
rHead = rHead.next;
head = head.next;
}
return true;
}
private ListNode FindMiddleNode(ListNode head){
ListNode fast = head;
ListNode slow = head;
while(fast.next != null && fast.next.next != null){
fast = fast.next.next;
slow = slow.next;
}
return slow;
}
private ListNode reverseList(ListNode head){
ListNode newHead = null;
while(head != null){
ListNode tmp = head.next;
head.next = newHead;
newHead = head;
head = tmp;
}
return newHead;
}
6._24反转链表
非递归方法:头插法,每次往头部插入一个节点
思路:设置一个newHead先指向空,然后将head.next指向newHead,newHead指向head.head需要继续往下遍历。但是head.next已经指向newHead了,找不到原来链表head.next指向的内容。所以从一开始就要新建一个指针tmp指向head.next.这样head = tmp,tmp = head.next,便可将整个链表遍历完成。
代码:
public ListNode reverseList(ListNode head) {
ListNode newHead = null;
while(head != null){
ListNode tmp = head.next;
head.next = newHead;
newHead = head;
head = tmp;
}
return newHead;
}