LeetCode-探索链表-综合问题
合并两个有序链表
将两个有序链表合并为一个新的有序链表并返回。
新链表是通过拼接给定的两个链表的所有节点组成的。
public class Solution { public ListNode MergeTwoLists(ListNode l1, ListNode l2) { if(l1==null)return l2; if(l2==null)return l1; ListNode newList=null; //递归调用自身,递归到两链表中最后剩的最大的链表,赋值为前一个小值的next if(l1.val<=l2.val){ newList=l1; newList.next=MergeTwoLists(l1.next,l2); }else{ newList=l2; newList.next=MergeTwoLists(l1,l2.next); } return newList; } }
两数相加
给出两个 非空 的链表用来表示两个非负的整数。
其中,它们各自的位数是按照 逆序 的方式存储的,并且它们的每个节点只能存储 一位 数字。
如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的和。
您可以假设除了数字 0 之外,这两个数都不会以 0 开头。
public class Solution { public ListNode AddTwoNumbers(ListNode l1, ListNode l2) { ListNode p1=l1,p2=l2,head=null,curr=null; int carry=0; //两链表都为空,并且进位值为0才结束循环 while(p1!=null||p2!=null||carry!=0){ int num1=0,num2=0; if(p1!=null){ num1=p1.val; p1=p1.next; } if(p2!=null){ num2=p2.val; p2=p2.next; } int sum=num1+num2+carry;//两节点值相加,加上进位值 carry=(sum/10==0)?0:1;//下次相加的进位值 ListNode s=new ListNode(sum%10);//将和的值存入新节点 if(head==null)head=s;//第一个节点为head else curr.next=s;//将新节点加入链表 curr=s;//记录链表的尾部即本循环的新节点 } return head; } }
扁平化多级双向链表
您将获得一个双向链表,除了下一个和前一个指针之外,它还有一个子指针,可能指向单独的双向链表。
这些子列表可能有一个或多个自己的子项,依此类推,生成多级数据结构,如下面的示例所示。
扁平化列表,使所有结点出现在单级双链表中。您将获得列表第一级的头部。
/* // Definition for a Node. public class Node { public int val; public Node prev; public Node next; public Node child; public Node(){} public Node(int _val,Node _prev,Node _next,Node _child) { val = _val; prev = _prev; next = _next; child = _child; } */ public class Solution { public Node Flatten(Node head) { FindChild(head); return head; } public Node FindChild(Node head){ Node go=head,gopre=null; while(go!=null){ //若存在子节点 if(go.child!=null){ Node childTail=FindChild(go.child);//得到返回的子节点链表的尾部 if(go.next!=null){//若go是链表最后一个节点 childTail.next=go.next;//在go和其后继结点之间插入子节点链表 go.next.prev=childTail; } go.child.prev=go; go.next=go.child; go.child=null;//将go的子节点设为空 go=childTail;//将go指针指向插入的链表尾部 } gopre=go;//记录go的前驱节点gopre go=go.next;//go指向其后继结点 } return gopre;//将链表尾部返回 } }
复制带随机指针的链表
给定一个链表,每个节点包含一个额外增加的随机指针,该指针可以指向链表中的任何节点或空节点。
要求返回这个链表的深度拷贝。
/** * Definition for singly-linked list with a random pointer. * public class RandomListNode { * public int label; * public RandomListNode next, random; * public RandomListNode(int x) { this.label = x; } * }; */ public class Solution { Dictionary<RandomListNode,RandomListNode> dict=new Dictionary<RandomListNode,RandomListNode>(); public RandomListNode CopyRandomList(RandomListNode head) { if(head==null)return null; //判断键值对中是否有该节点副本,若有直接返回 if(!dict.ContainsKey(head)){ //没有就新建一个节点,并递归拷贝节点的字段 dict[head]=new RandomListNode(head.label); dict[head].next=CopyRandomList(head.next); dict[head].random=CopyRandomList(head.random); } return dict[head]; } }
旋转链表
给定一个链表,旋转链表,将链表每个节点向右移动 k 个位置,其中 k 是非负数
public class Solution { public ListNode RotateRight(ListNode head, int k) { if(head==null||head.next==null||k==0)return head; int len=0; ListNode curr=head,pre=head,p=head; //获取链表长度len while(curr!=null){ pre=curr; curr=curr.next; len++; } int step=k%len;//计算断开位置 if(step==0)return head; curr=head; //获取断开位置前后节点 for(int i=0;i<len-step;i++){ p=head; head=head.next; } //旋转链表 p.next=null; pre.next=curr; return head; } }