面试手撕代码总结(二)-链表篇
1.合并两个有序链表
public ListNode Merge(ListNode list1,ListNode list2) {
if(list1==null){
return list2;
}
if(list2==null){
return list1;
}
ListNode newhead =null;
if(list1.val<=list2.val){
newhead = list1;
newhead.next=Merge(list1.next,list2);
}else{
newhead = list2;
newhead.next=Merge(list1,list2.next);
}
return newhead;
}
2.删除链表中重复的节点
public ListNode deleteDuplication(ListNode pHead) {
if (pHead == null) {
return null;
}
ListNode head = new ListNode(0);
ListNode pre = head;
ListNode now = pHead;
head.next = pHead;
while (now != null && now.next != null) {
if (now.val == now.next.val) {
int val = now.val;
while (now != null && now.val == val) {
now = now.next;
}
pre.next = now;
} else {
pre.next = now;
pre = now;
now = now.next;
}
}
return head.next;
}
3.打印两个链表的第一个公共节点
public class Solution {
public ListNode FindFirstCommonNode(ListNode pHead1, ListNode pHead2) {
if (pHead1 == null||pHead2 == null) {
return null;
}
int count1 = 0;
ListNode p1 = pHead1;
while (p1!=null){
p1 = p1.next;
count1++;
}
int count2 = 0;
ListNode p2 = pHead2;
while (p2!=null){
p2 = p2.next;
count2++;
}
int flag = count1 - count2;
if (flag > 0){
while (flag>0){
pHead1 = pHead1.next;
flag --;
}
while (pHead1!=pHead2){
pHead1 = pHead1.next;
pHead2 = pHead2.next;
}
return pHead1;
}
if (flag <= 0){
while (flag<0){
pHead2 = pHead2.next;
flag ++;
}
while (pHead1 != pHead2){
pHead2 = pHead2.next;
pHead1 = pHead1.next;
}
return pHead1;
}
return null;
}
}
4.链表奇数偶数节点
public ListNode oddEvenList(ListNode head) {
if (head == null) return null;
ListNode odd = head, even = head.next, evenHead = even;
while (even != null && even.next != null) {
odd.next = even.next;
odd = odd.next;
even.next = odd.next;
even = even.next;
}
odd.next = evenHead;
return head;
}
5.链表的回文结构
class Solution {
public boolean isPalindrome(ListNode head) {
// 要实现 O(n) 的时间复杂度和 O(1) 的空间复杂度,需要翻转后半部分
if (head == null || head.next == null) {
return true;
}
ListNode fast = head;
ListNode slow = head;
// 根据快慢指针,找到链表的中点
while(fast.next != null && fast.next.next != null) {
fast = fast.next.next;
slow = slow.next;
}
slow = reverse(slow.next);
while(slow != null) {
if (head.val != slow.val) {
return false;
}
head = head.next;
slow = slow.next;
}
return true;
}
private ListNode reverse(ListNode head){
// 递归到最后一个节点,返回新的新的头结点
if (head.next == null) {
return head;
}
ListNode newHead = reverse(head.next);
head.next.next = head;
head.next = null;
return newHead;
}
}
6.复杂链表的复制
/*
public class RandomListNode {
int label;
RandomListNode next = null;
RandomListNode random = null;
RandomListNode(int label) {
this.label = label;
}
}
*/
public class Solution {
public RandomListNode Clone(RandomListNode pHead)
{
if(pHead==null){
return null;
}
RandomListNode head=new RandomListNode(pHead.label);
RandomListNode temp=head;
while(pHead.next!=null){
temp.next=new RandomListNode(pHead.next.label);
if(pHead.random!=null){
temp.random=new RandomListNode(pHead.random.label);
}
pHead=pHead.next;
temp=temp.next;
}
return head;
}
}
7.检测链表是否有环
//(1)链表是否有环
public boolean hasCycle(ListNode head) {
ListNode fast=head;
ListNode slow=head;
if(fast==null) return false;
while(fast!=null&&fast.next!=null){
fast=fast.next.next;
slow=slow.next;
if(slow==fast){
return true;
}
}
return !(fast==null||fast.next==null);
}
//(2)链表中环的入口节点
public ListNode EntryNodeOfLoop(ListNode pHead){
if(pHead==null||pHead.next==null)return null;
ListNode p1=pHead;
ListNode p2=pHead;
while(p2!=null&&p2.next!=null){
p1=p1.next;
p2=p2.next.next;
if(p1==p2){
p1=pHead;
while(p1!=p2){
p1=p1.next;
p2=p2.next;
}
if(p1==p2)return p1;
}
}
return null;
}
8.判断两个链表是否相交
public boolean isIntersect(Node h1,Node h2){
if(h1==null||h2=null){
return false;
}
Node tail1=h1;
while(tail1.next!=null){
tail1=tail1.next;
}
Node tail2=h2;
while(tail2.next!=null){
tail2=tail2.next;
}
return tail1==tail2;
}
9.两数相加链表
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
ListNode dummyHead = new ListNode(0);
ListNode p = l1, q = l2, curr = dummyHead;
int carry = 0;
while (p != null || q != null) {
int x = (p != null) ? p.val : 0;
int y = (q != null) ? q.val : 0;
int sum = carry + x + y;
carry = sum / 10;//去掉最后一位,进位
curr.next = new ListNode(sum % 10);
curr = curr.next;
if (p != null) p = p.next;
if (q != null) q = q.next;
}
if (carry > 0) {
curr.next = new ListNode(carry);
}
return dummyHead.next;
}
10.翻转链表
public ListNode ReverseList(ListNode head) {
if(head ==null){
return null;
}
ListNode temp = null;
while(head!=null){
ListNode p = head.next;
head.next = temp;
temp=head;
head=p;
}
return temp;
}