链表面试编程题
1. 删除链表中等于给定值 val 的所有节点。 203. 移除链表元素 - 力扣(LeetCode)
2. 反转一个单链表。206. 反转链表 - 力扣(LeetCode)
3. 给定一个带有头结点 head 的非空单链表,返回链表的中间结点。如果有两个中间结点,则返回
第二个中间结 点。876. 链表的中间结点 - 力扣(LeetCode)
4. 输入一个链表,输出该链表中倒数第k个结点。面试题 02.02. 返回倒数第 k 个节点 - 力扣(LeetCode)
5. 将两个有序链表合并为一个新的有序链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。21. 合并两个有序链表 - 力扣(LeetCode)
6. 编写代码,以给定值x为基准将链表分割成两部分,所有小于x的结点排在大于或等于x的结点之前 。链表分割_牛客题霸_牛客网 (nowcoder.com)
7. 链表的回文结构。链表的回文结构_牛客题霸_牛客网 (nowcoder.com)
8. 输入两个链表,找出它们的第一个公共结点160. 相交链表 - 力扣(LeetCode)
10.给定一个链表,返回链表开始入环的第一个节点。 如果链表无环,则返回 NULL
142. 环形链表 II - 力扣(LeetCode)
1. 删除链表中等于给定值 val 的所有节点。 203. 移除链表元素 - 力扣(LeetCode)
class Solution {
public ListNode removeElements(ListNode head, int val) {
if(head==null){
return head;
}
ListNode prev=head;
ListNode cur=head.next;
while(cur!=null){
if(cur.val==val){
prev.next=cur.next;
cur=cur.next;
}else{
prev=cur;
cur=cur.next;
}
}
if(head.val==val){
head=head.next;
}
return head;
}
}
2. 反转一个单链表。206. 反转链表 - 力扣(LeetCode)
方法一:头插法
class Solution {//方法一:头插法
public ListNode reverseList(ListNode head) {
if(head==null){
return head;
}
ListNode cur=head.next;
head.next=null;
while(cur!=null){
ListNode curN=cur.next;
cur.next=head;
head=cur;
cur=curN;
}
return head;
}
}
方法二:改变指向法
/**
* 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 reverseList(ListNode head) {
if(head==null){
return head;
}
ListNode save;
ListNode cur=head.next;
head.next=null;
while(cur!=null){
save=cur.next;
cur.next=head;
head=cur;
cur=save;
}
return head;
}
}
3. 给定一个带有头结点 head 的非空单链表,返回链表的中间结点。如果有两个中间结点,则返回第二个中间结 点。876. 链表的中间结点 - 力扣(LeetCode)
方法一:快慢指针法
class Solution {
public ListNode middleNode(ListNode head) {
ListNode fast=head;
ListNode slow=head;
while(fast!=null&&fast.next!=null){
slow=slow.next;
fast=fast.next.next;
}
return slow;
}
}
4. 输入一个链表,输出该链表中倒数第k个结点。面试题 02.02. 返回倒数第 k 个节点 - 力扣(LeetCode)
方法:依旧是快慢指针法,快指针先走k-1步,紧接着一起走,快指针走到null时,slow指针的值就是倒数第k个节点,需要注意的是,确保k符合条件
class Solution {
public int kthToLast(ListNode head, int k) {
ListNode slow=head;
ListNode fast=head;
while(k-1>0){
fast=fast.next;
k--;
}
while(fast.next!=null){
fast=fast.next;
slow=slow.next;
}
return slow.val;
}
}
5. 将两个有序链表合并为一个新的有序链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。21. 合并两个有序链表 - 力扣(LeetCode)
方法:创建傀儡节点/虚拟节点,小的进行尾插
class Solution {
public ListNode mergeTwoLists(ListNode list1, ListNode list2) {
ListNode head=new ListNode(0);
ListNode cur=head;
while(list1!=null&&list2!=null){
if(list1.val>list2.val){
cur.next=list2;
list2=list2.next;
cur=cur.next;
}else{
cur.next=list1;
list1=list1.next;
cur=cur.next;
}
}
if(list1!=null){
cur.next=list1;
}
if(list2!=null){
cur.next=list2;
}
return head.next;
}
}
6. 编写代码,以给定值x为基准将链表分割成两部分,所有小于x的结点排在大于或等于x的结点之前 。链表分割_牛客题霸_牛客网 (nowcoder.com)
方法:依旧使用两个虚拟节点/傀儡节点,小于x的放在一个虚拟节点内,大于等于x的放在另一个虚拟节点内,最后进行拼接
public class Partition {
public ListNode partition(ListNode pHead, int x) {
ListNode nx=new ListNode(0);
ListNode xn=new ListNode(0);
ListNode cur=pHead;
ListNode as=nx;
ListNode bs=xn;
while(cur!=null){
if(cur.val<x){
nx.next=cur;
cur=cur.next;
nx=nx.next;
}else{
xn.next=cur;
cur=cur.next;
xn=xn.next;
}
}
nx.next=bs.next;
xn.next=null;
return as.next;
}
}
7. 链表的回文结构。链表的回文结构_牛客题霸_牛客网 (nowcoder.com)
先寻找中间节点
再从中间节点往后翻转
从后往前循环判断,判断过程中分奇偶判断,内补实现偶数判断返回true,循环结束为奇数判断结束,返回true
public boolean chkPalindrome(ListNode A) {
if(A==null){
return true;
}
// write code here
ListNode slow=A;
ListNode fast=A;
while(fast!=null&&fast.next!=null){
fast=fast.next.next;
slow=slow.next;
}
ListNode cur=slow.next;
while(cur!=null){
ListNode curN=cur.next;
cur.next=slow;
slow=cur;
cur=curN;
}//从中间节点开始,翻转另一边链表
while(A!=slow){
if(A.val!=slow.val){
return false;
}
if(A.next==slow){//偶数特例
return true;
}
A=A.next;
slow=slow.next;
}
return true;//奇数例子
}
也可以不用判断奇数偶数,及时给找到中间节点后的slow的next置空就好啦
8. 输入两个链表,找出它们的第一个公共结点160. 相交链表 - 力扣(LeetCode)
ublic ListNode getIntersectionNode(ListNode headA, ListNode headB) {
ListNode pl=headA;
ListNode ps=headB;
int countA=0;
int countB=0;
while(pl!=null){
countA++;
pl=pl.next;
}
while(ps!=null){
countB++;
ps=ps.next;
}
int len=countA-countB;
pl=headA;
ps=headB;
if(len<0){
len=countB-countA;
pl=headB;
ps=headA;
}
while(len>0){
pl=pl.next;
len--;
}
while(pl!=ps){
pl=pl.next;
ps=ps.next;
}
if(pl==null){
return null;
}
return pl;
}
9. 给定一个链表,判断链表中是否有环。141. 环形链表 - 力扣(LeetCode)
public boolean hasCycle(ListNode head) {
if(head==null){
return false;
}
ListNode fast=head;
ListNode slow=head;
while(fast!=null&&fast.next!=null){
slow=slow.next;
fast=fast.next.next;
if(fast==slow){
return true;
}
}
return false;
}
10.给定一个链表,返回链表开始入环的第一个节点。 如果链表无环,则返回 NULL
142. 环形链表 II - 力扣(LeetCode)
public ListNode detectCycle(ListNode head) {
if(head==null){
return null;
}
ListNode Head=head;
ListNode fast=head;
ListNode slow=head;
while(fast!=null&&fast.next!=null){
slow=slow.next;
fast=fast.next.next;
if(fast==slow){
while(Head!=slow){
Head=Head.next;
slow=slow.next;
}
if(slow==Head){
return Head;
}
}
}
return null;
}