链表
002两数相加
代码(对应结点相加)
/**
* 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 addTwoNumbers(ListNode l1,ListNode l2) {
/*
题目信息:
两个非空的链表
逆序存储
除了数字0不会以0开头
*/
/*
* 依次相加
* 注意考虑进位
*/
// 创建头结点
ListNode head=new ListNode();
// 指向head
ListNode node=head;
// 依次将每个结点相加,记得考虑进位
// 初始化进位为0
int so=0;
// 遍历两个链表叠加
// 直到两个链表均遍历完
ListNode p=l1;
ListNode q=l2;
while(p!=null||q!=null) {
// 初始化进位、两个对应结点的和为进位大小
int sum=so;
if(p!=null) {
sum+=p.val;
}
if(q!=null) {
sum+=q.val;
}
// 创建node的下一个结点,大小为sum%10;
node.next=new ListNode(sum%10);
// 更新进位
so=sum/10;
/*
* 记得要考虑p、q结点是否为null
*/
if(p!=null) {
p=p.next;
}
if(q!=null) {
q=q.next;
}
node=node.next;
}
// 叠加之后要考虑是否仍存在进位,是否需要创建新结点
if(so==1) {
node.next=new ListNode(so);
}
return head.next;
}
}
019删除链表的倒数第N个结点
代码一(倒数转正数)
/**
* 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 removeNthFromEnd(ListNode head, int n) {
// 倒数转换为整数
// 先计算链表长度
ListNode p=head,q=head;
// 记录链表长度
int size=0;
// 求链表长度
while(p!=null){
size++;
p=p.next;
}
// 除去第一个结点的时候
/*
易错点:
下面的
int t=size-n
t代表的是要删除的结点前面有几个结点,
而该链表head没有头结点
故前面有0个结点
要单独拿出来讨论
*/
if(size==n){
return head.next;
}
// 记录删除结点的前一个结点的正数位置
int t=size-n;
int i=1;
// 找要删除的结点的前一个结点
while(i!=t){
q=q.next;
i++;
}
// 删除结点
q.next=q.next.next;
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 removeNthFromEnd(ListNode head, int n) {
// 创建头结点
// 删除结点时要知道其前一个结点
ListNode node=new ListNode();
node.next=head;
ListNode node1=node,node2=node;
// 第一个先遍历n+1个结点
int i=0;
while(i<=n){
i++;
node1=node1.next;
}
// node1与node2一直相差n+1,当node1遍历完,node2即为要删除的结点的前一个结点
// 故node1先遍历了n+1个结点而非n个结点
while(node1!=null){
node1=node1.next;
node2=node2.next;
}
node2.next=node2.next.next;
return node.next;
}
}
代码三(利用数组)
/**
* 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 removeNthFromEnd(ListNode head, int n) {
List<ListNode>list=new ArrayList<>();
ListNode node=head;
// 记录链表长度
int size=0;
// 求链表长度,并将结点存入数组
while(node!=null){
size++;
list.add(node);
node=node.next;
}
// 删除第一个结点
if(n==size){
return head.next;
}
// 删除其他结点
else{
ListNode re=list.get(size-n-1);
re.next=re.next.next;
return head;
}
}
}
021合并两个有序链表
代码一(遍历链表)
/**
* 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 mergeTwoLists(ListNode list1, ListNode list2) {
// 链表list1为空
if(list1==null&&list2!=null){
return list2;
}
// 链表list2为空
else if(list1!=null&&list2==null){
return list1;
}
// 两个链表都为空
else if(list1==null&&list2==null){
return null;
}
// 两个链表都不为空
else{
// 创建头结点
ListNode head=new ListNode();
ListNode node=head;
// 遍历链表list1,list2
while(list1!=null&&list2!=null){
// 当前遍历list1的结点的val较小或者两者相等
if(list1.val<=list2.val){
node.next=list1;
list1=list1.next;
node=node.next;
}
else{
node.next=list2;
list2=list2.next;
node=node.next;
}
}
// 当list1未遍历完
if(list1!=null){
node.next=list1;
}
// 当list2未遍历完
else if(list2!=null){
node.next=list2;
}
return head.next;
}
}
}
代码二(学习递归,暂时不会)
023合并K个升序链表
代码一(利用数组)
/**
* 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 mergeKLists(ListNode[] lists) {
// 将结点的val值存入数组中
List<Integer> list=new ArrayList<>();
for(ListNode node:lists){
while(node!=null){
list.add(node.val);
node=node.next;
}
}
//数组排序
Collections.sort(list);
// 创建链表
ListNode list1=new ListNode();
ListNode node=list1;
for(int val:list){
node.next=new ListNode(val);
node=node.next;
}
return list1.next;
}
}
代码二(学习优先队列,暂时不会)
代码三(学习分治算法,暂时不会)
024两两交换链表中的节点
代码一
/**
* 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 swapPairs(ListNode head) {
// 判断是否为空
if(head==null){
return null;
}
// 用于记录当前遍历的结点的位次,结点总数
int size=0;
ListNode p=head;
// 记录相邻结点翻转后的链表
ListNode list=new ListNode();
ListNode node=list;
while(p!=null){
// 结点的个数++
size++;
// 目的:记录第偶数个结点
ListNode q=p;
p=p.next;
// 表明是第偶数个
if(size%2==0){
node.next=q;
node=node.next;
node.next=head;
/*
head.next=null不可漏掉,不然会陷入循环
比如1 2 3 4
list为头结点->2->1->4->3此时按道理说遍历完结束了
但实际为
list为头结点->2->1->4->3->4->3->4->3。。。。4,3一直循环,这是 因为原链表3指向4,但是我们没有改变
*/
head.next=null;
node=node.next;
head=p;
}
}
// 判断是否结点数是否为奇数,若为奇数,则有一个不用翻转,未添加
if(size%2!=0){
node.next=head;
head.next=null;
}
return list.next;
}
}
代码二(学习递归,暂时不会)
代码三(学习迭代,暂时不会)
025K个一组链表翻转
代码一
/**
* 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 reverseKGroup(ListNode head, int k) {
ListNode head1=head;
// 记录结点个数
int size=0;
// 求结点个数
while(head1!=null){
size++;
head1=head1.next;
}
// 将结点val值存入数组
int[] arr=new int [size];
int i=0;
while(head!=null){
arr[i++]=head.val;
head=head.next;
}
// 记录循环的周期数
int circles=size/k;
// 记录翻转的链表
ListNode newHead=new ListNode();
ListNode node=newHead;
int p=1;
int q=k;
int size1=0;
while(p<=circles){
while(q>(p-1)*k){
node.next=new ListNode(arr[q-1]);
size1++;
node=node.next;
q--;
}
p++;
q=p*k;
}
// 检查是否有周期以外未遍历的结点
while(size1<arr.length){
node.next=new ListNode(arr[size1]);
node=node.next;
size1++;
}
return newHead.next;
}
}