LeetCode链表
1.1 题目描述
1.2 迭代(虚拟头解决)
class Solution {
public ListNode removeElements(ListNode head, int val) {
ListNode dummyNode=new ListNode(0,head);
ListNode l=dummyNode;
if(dummyNode.next==null){
return null;
}
while(dummyNode.next!=null){
if(dummyNode.next.val==val){
dummyNode.next=dummyNode.next.next;
}else{
dummyNode=dummyNode.next;
}
}
return l.next;
}
}
1.3 迭代(不使用虚拟头)
class Solution {
public ListNode removeElements(ListNode head, int val) {
if(head==null){
return null;
}
ListNode l=head;
while(l.next!=null){
if(head.val==val){
head=head.next;
l=l.next;
}else if(l.next.val==val){
l.next=l.next.next;
}else{
l=l.next;
}
}
if(l.val==val){
return null;
}else{
return head;
}
}
}
1.4 思考
? 以后只要有链表中头结点被删除的可能,那么直接使用虚拟头的方式,非常好用!
2.1 题目描述
2.2 头插法
? 这种解法需要多余的空间,如果题目的空间复杂度为O(1),那就不能使用这个解法。
class Solution {
public ListNode reverseList(ListNode head) {
ListNode node=null;
while(head!=null){
if(node==null){
node=new ListNode(head.val);
}else{
ListNode newNode=new ListNode(head.val,node);
node=newNode;
}
head=head.next;
}
return node;
}
}
2.3 原地移动法
? 这种方法不需要开辟新的内存空间,适用于要求空间复杂度为O(1)的题目。
class Solution {
public ListNode reverseList(ListNode head) {
if(head==null || head.next==null){
return head;
}
ListNode l=head.next;
head.next=null;
while(l!=null && l.next!=null){
ListNode newNode=l.next;
l.next=head;
head=l;
l=newNode;
}
l.next=head;
return l;
}
}
3.1 题目描述
3.2 快慢指针
? 设置一个快指针和慢指针,快指针一次走两步,慢指针一次走一步。
? 若链表元素为偶数个,当快指针为null时,慢指针所指向的就是最中间元素
? 若链表元素为奇数个,当快指针的next为null时,慢指针所指向的就是最中间元素(中间第二个元素)
class Solution {
public ListNode middleNode(ListNode head) {
ListNode low=head;
ListNode fast=head;
while(fast!=null && fast.next!=null){
fast=fast.next.next;
low=low.next;
}
return low;
}
}
4.1 题目描述
4.2 快慢指针
? 返回倒数第K个结点,那么就可以先让fast先走K步,然后让low和fast一块走,fast为null的时候就是要返回的那个结点值。
class Solution {
public int kthToLast(ListNode head, int k) {
ListNode low=head;
ListNode fast=head;
for(int i=0;i<k;i++){
fast=fast.next;
}
while(fast!=null){
fast=fast.next;
low=low.next;
}
return low.val;
}
}
5.环形链表Ⅱ
5.1 题目描述
5.2 解题思路
5.3 代码
5.3.1 快慢指针方法
public ListNode detectCycle(ListNode head) {
ListNode slow=head;
ListNode fast=head;
while(true){
if(fast==null || fast.next==null){
return null;
}
slow=slow.next;
fast=fast.next.next;
if(slow==fast){
break;
}
}
slow=head;
while(slow!=fast){
fast=fast.next;
slow=slow.next;
}
return fast;
}
5.3.2 方法二
public ListNode detectCycle(ListNode head) {
List<ListNode> list=new ArrayList<>();
ListNode pos=head;
while(true){
if(pos==null || pos.next==null){
return null;
}
if(list.contains(pos)){
return pos;
}else{
list.add(pos);
}
pos=pos.next;
}
}
6.1 题目描述
6.2 解题思路
? 和第5题一模一样,甚至比第五题还要少一个步骤,只需要判断链表是否有环即可
6.3 代码
6.3.1 快慢指针方法
public boolean hasCycle(ListNode head) {
ListNode slow=head;
ListNode fast=head;
while(true){
if(fast==null || fast.next==null){
return false;
}
slow=slow.next;
fast=fast.next.next;
if(slow==fast){
return true;
}
}
}
6.3.2 方法二
public boolean hasCycle(ListNode head) {
List<ListNode> list=new ArrayList<>();
ListNode pos=head;
while(true){
if(pos==null || pos.next==null){
return false;
}
if(list.contains(pos)){
return true;
}else{
list.add(pos);
}
pos=pos.next;
}
}
7.1 题目描述
7.2 解题思路
? 要比较两个链表是否有相交部分时,那肯定是在两个链表长度相同条件下进行比较的,所以
7.3 代码
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
if(headA==null || headB==null){
return null;
}
ListNode posA=headA;
ListNode posB=headB;
while(posA!=posB){
posA=(posA==null?headB:posA.next);
posB=(posB==null?headA:posB.next);
}
return posA;
}
8.1 题目描述
8.2 解题思路
- 使用快慢指针找到链表的中间元素,要注意偶数个和奇数
- 将起始元素到中间元素的所有元素存放在栈中,用于与后面的元素进行比对
- 根据链表的个数进行比对
8.3 代码
public boolean isPalindrome(ListNode head) {
if(head==null || head.next==null){
return true;
}
if(head.next.next==null){
if(head.val==head.next.val){
return true;
}else{
return false;
}
}
ListNode slow=head;
ListNode fast=head;
int num=0;
Stack stack=new Stack();
while(true){
stack.push(slow.val);
if(fast.next==null){
num=1;
break;
}
if(fast.next.next==null){
num=0;
break;
}
slow=slow.next;
fast=fast.next.next;
}
if(num==1){
stack.pop();
slow=slow.next;
while(slow!=null){
if((int)stack.pop()!=slow.val){
return false;
}
slow=slow.next;
}
return true;
}else{
slow=slow.next;
while(slow!=null){
if((int)stack.pop()!=slow.val){
return false;
}
slow=slow.next;
}
return true;
}
}
9.1 题目描述
9.2 解题思路
? 这道题的描述和示例结果不清楚,实际就是将大于等于x的结点全部放在小于结点的后面,结果不唯一
9.3 代码
public ListNode partition(ListNode head, int x) {
if(head==null){
return null;
}
ListNode dummyNode1=new ListNode(0);
dummyNode1.next=head;
ListNode pos1=dummyNode1.next;
ListNode dummyNode2=new ListNode();
dummyNode2.next=null;
ListNode pos2=dummyNode2;
while(pos1!=null){
if(pos1.val<x){
pos2.next=new ListNode(pos1.val);
pos2=pos2.next;
pos2.next=null;
}
pos1=pos1.next;
}
pos1=dummyNode1.next;
while(pos1!=null){
if(pos1.val>=x){
pos2.next=new ListNode(pos1.val);
pos2=pos2.next;
pos2.next=null;
}
pos1=pos1.next;
}
return dummyNode2.next;
}
10.1 题目描述
10.2 解题思路
- 先创建一个链表pos
- 判断两个链表中最小的结点,连接到pos上,然后将最小的结点所在list=list.next
- 到最后,肯定有一个list会先为null,那么直接让pos.next=另外一个list
10.3 代码
public ListNode mergeTwoLists(ListNode list1, ListNode list2) {
ListNode dummyNode=new ListNode();
dummyNode.next=null;
ListNode pos=dummyNode;
ListNode pos1=list1;
ListNode pos2=list2;
while(true){
if(pos1==null){
pos.next=pos2;
break;
}
else if(pos2==null){
pos.next=pos1;
break;
}
if(pos1.val<=pos2.val){
pos.next=new ListNode(pos1.val,null);
pos=pos.next;
pos1=pos1.next;
}else{
pos.next=new ListNode(pos2.val,null);
pos=pos.next;
pos2=pos2.next;
}
}
return dummyNode.next;
}
|