2021-6-13-剑指笔记01
Posted 轻舟一曲
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2021-6-13-剑指笔记01相关的知识,希望对你有一定的参考价值。
笔记01
_11_返回倒数第k个节点
package LeetCode._面试经典.笔记01;
public class _11_返回倒数第k个节点
public class ListNode
int val;
ListNode next;
ListNode(int x) val = x;
/*
1.递归:代码简洁但是需要占用O(N)的空间
2.迭代:代码稍微复杂一点但是效率快
* */
public int K=0;
public int value=0;
public int kthToLast(ListNode head, int k)
K=k;
nthToLast(head);
return value;
//递归每次返回该节点的下标(tip:最后1个为倒数第1个)
public int nthToLast(ListNode node)
if (node==null) return 0;
int l=nthToLast(node.next)+1;
if (l==K) value=node.val;
return l;
//快慢指针
public int kthToLast02(ListNode head, int k)
if (head==null) return 0;
ListNode slow=head;
ListNode fast=head;
while (k>0&&fast!=null)//最后fast肯定到null所以需要多走1步
fast=fast.next;
k--;
if (k!=0) return 0;//不合法的k
while (fast!=null)
slow=slow.next;
fast=fast.next;
return slow.val;
_12_删除链表中间节点
package LeetCode._面试经典.笔记01;
import org.junit.Test;
import java.util.Random;
public class _12_删除链表中间节点
public class ListNode
int val;
ListNode next;
ListNode(int x) val = x;
/*
中间节点:除去首尾节点外都叫中间节点,只能访问删除的的节点
tips:若待删除的是尾结点,该题无解,面试的时候应该给面试官指出
将其为null ? 很明显这就是对指针的不理解了,你置null只是将node置null,却并未将前驱节点的next置null,其还是只想该块内存额
* */
public void deleteNode(ListNode node)
if (node==null) return;
if (node.next==null)
System.out.println("尾结点:"+node.val);
node.val=-1;
return;
node.val=node.next.val;
node.next=node.next.next;
@Test
public void test()
//[a,b] random(b-a)+a
ListNode head=new ListNode(1);
ListNode n2=new ListNode(2);
ListNode n3=new ListNode(3);
ListNode n4=new ListNode(4);
head.next=n2;
n2.next=n3;
n3.next=n4;
deleteNode(n4);
print(head);
public void print(ListNode node)
ListNode p=node;
while (p!=null)
System.out.println(p.val);
p=p.next;
_13_分割链表
package LeetCode._面试经典.笔记01;
import org.junit.Test;
public class _13_分割链表
public class ListNode
int val;
ListNode next;
ListNode(int x) val = x;
/*
询问如果不考虑"稳定性":原来的顺序不变-->1个链表:头插+尾插
考虑:2个链表
* */
public ListNode partition01(ListNode head, int x)
if (head==null) return null;
ListNode lowS=new ListNode(-1);
ListNode lowL=lowS;
ListNode highS=new ListNode(-1);
ListNode highL=highS;
ListNode p=head;
while (p!=null)//保证losS或highS最后1个不为null
if (p.val<x)
lowL.next=p;
lowL=lowL.next;
else
highL.next=p;
highL=highL.next;
p=p.next;
//避免出现环
lowL.next=null;
highL.next=null;
lowL.next=highS.next;
return lowS.next;
//不考虑稳定性,利用现有节点进行头插尾插法,更简洁代码
//左边部分<x 右边部分>=x
public ListNode partition(ListNode head, int x)
if (head==null) return null;
ListNode S=head;
ListNode L=head;
ListNode P=head.next;
while (P!=null)
ListNode next=P.next;
if (P.val<x)
P.next=S;//p.next断开,下面就用不到了
S=P;
else
L.next=P;
L=P;
P=next;
L.next=null;
return S;
@Test
public void test()
ListNode n1=new ListNode(1);
ListNode n2=new ListNode(4);
ListNode n3=new ListNode(3);
ListNode n4=new ListNode(2);
ListNode n5=new ListNode(5);
ListNode n6=new ListNode(2);
n1.next=n2;
n2.next=n3;
n3.next=n4;
n4.next=n5;
n5.next=n6;
ListNode res=partition(n1,3);
_14_链表求和
package LeetCode._面试经典.笔记01;
public class _14_链表求和
public class ListNode
int val;
ListNode next;
ListNode(int x) val = x;
/*
首先回顾一下加法:
6 1 7
+ 2 5 9
可用递归实现,注意短链表的空指针
* */
public ListNode addTwoNumbers01(ListNode l1, ListNode l2)
return nextList(l1,l2,0);
public ListNode nextList(ListNode l1,ListNode l2,int carry)
if (l1==null&&l2==null&&carry==0) return null;
int sum=carry;
if (l1!=null) sum+=l1.val;
if (l2!=null) sum+=l2.val;
ListNode res=new ListNode(sum%10);//先序遍历
res.next=nextList(l1==null?null:l1.next,l2==null?null:l2.next,sum/10);
return res;
/*
进阶:整数正向存储
因为需要配对,所以需要先补0
* */
public class PartialSum//封装类
public ListNode sum=null;
public int carry=0;
//两个节点相加得到一个封装加数节点PartialSum,再往前传递即可
PartialSum addHelper(ListNode l1,ListNode l2)
if (l1==null&&l2==null)
return new PartialSum();
PartialSum sumHelper=addHelper(l1.next,l2.next);
//得到l1.next,l2.next的加数类,直接拿加数类的节点即可
//构造当前加数类的节点
int val=sumHelper.carry+l1.val+l2.val;
ListNode node=new ListNode(val%10);//当前加数节点
if (sumHelper.sum!=null)
node.next=sumHelper.sum;
sumHelper.carry=val/10;
return sumHelper;//最后返回的是一个加数节点和进位
public ListNode addTwoNumbers(ListNode l1, ListNode l2)
if (l1==null||l2==null) return l1==null?l2:l1;
int count1=0;
ListNode p1=l1;
while (p1!=null)
count1++;
p1= p1.next;
int count2=0;
ListNode p2=l1;
while (p2!=null)
count2++;
p2= p2.next;
if (count1<count2) return addTwoNumbers(l2,l2);
//保证l1最长
int diff=count1-count2;
ListNode head2=new ListNode(0);
ListNode p=head2;
for (int i=1;i<=diff;i++)
ListNode node=new ListNode(0);
p.next=node;
p=node;
if (diff!=0)
p.next=l2;
l2=head2;
PartialSum res=addHelper(l1,l2);
if (res.carry==0)
return res.sum;
else
ListNode node=new ListNode(res.carry);//当前加数节点
if (res.sum!=null)
node.next=res.sum;
return node;
_15_回文链表
编写一个函数,检查输入的链表是否是回文的。
示例 1:
输入: 1->2
输出: false
示例 2:
输入: 1->2->2->1
输出: true
进阶:
你能否用 O(n) 时间复杂度和 O(1) 空间复杂度解决此题?
package LeetCode._面试经典.笔记01;
import org.junit.Test;
import java.util.ArrayDeque;
public class _15_回文链表
public class ListNode
int val;
ListNode next;
ListNode(int x) val = x;
//方法1:先将链表反转(头插),然后比较前半部分 O(N) O(N)
public boolean isPalindrome01(ListNode head)
if (head==null) return true;
ListNode node=getReverse(head);
return isReverse(head,node);
public ListNode getReverse(ListNode head)
ListNode p=head;
ListNode r=null;
while (p!=null)
ListNode node=new ListNode(p.val);
node.next=r;
r=node;
p=p.next;
//最后一个节点为头节点
return r;
public boolean isReverse(ListNode l1,ListNode l2)
ListNode p1=l1;
ListNode p2=l2;
while (p1!=null&&p2!=null)
if (p1.val!=p2.val) return false;
p1=p1.next;
p2=p2.next;
return true;
//---------------------------------------------------------------
//方法2:迭代法,利用栈+快慢指针 O(N) O(N)
public boolean isPalindrome02(ListNode head)
if (head==null) return true;
ListNode slow=head;
ListNode fast=head;
ArrayDeque<Integer> deque = new ArrayDeque<>();
while (fast!=null&&fast.next!=null)
deque.addFirst(slow.val);
slow=slow.next;
fast=fast.next.next;
//因为有奇数个节点,所以跳过中间节点
if (fast!=null) slow=slow.next;
while (slow!=null)
if (deque.removeFirst()!=slow.val) return false;
slow=slow.next;
return true;
//---------------------------------------------------------------
//方法3:递归,使用一个封装类
class Result
ListNode node;
boolean result;
public Result(ListNode node, boolean result)
this.node = node;
this.result = result;
public boolean isPalindrome(ListNode head)
int len=0;
ListNode p=head;
while (p!=null)
len++;
p=p.next;
Result reverse = isReverse(head, len);
return reverse.result;
//封装类的意思是返回 内序列的比对结果以及下次比较的内序列的最后1个节点
Result isReverse(ListNode head,int len)
if (head==null||len<=0)//偶数个节点
return new Result(head,true);
else if (len==1)//奇数个节点
return new Result(head.next,true);
Result res=isReverse(head.next,len-2);
if (!res.result||res.node==null) return res;//向上传递失败信息
res.result=(head.val==res以上是关于2021-6-13-剑指笔记01的主要内容,如果未能解决你的问题,请参考以下文章
[Unity学习笔记:FPS游戏制作]角色的移动,旋转与推进上升————(2021.6.13学习笔记)