Java链表刷题总结

1、输入一个链表的头节点,从尾到头反过来返回每个节点的值(用数组返回)。

 //方法一
    public static int[] reversePrint(ListNode head) {
        int k=0;
        int nodeCount=0;
        ListNode temp=head;
        if(temp==null){
            return new int[0];
        }
        //1、计算链表长度用于定义数组
        while(temp!=null){
            nodeCount++;
            temp=temp.next;
        }
        int[] array=new int[nodeCount];
        temp=head;
        //2、将链表元素全部放入数组
        while(temp!=null){
            array[k]=temp.val;
            temp=temp.next;
            k=k+1;
        }
        int cur=0;
        //3、反转数组
        for(int i=0;i<=nodeCount/2-1;i++){
            cur=array[i];
            array[i]=array[nodeCount-1-i];
            array[nodeCount-1-i]=cur;
        }
        return array;
    }

    //2、递归加回溯(关键代码)
    ArrayList<Integer> tmp = new ArrayList<Integer>();
   public  void recur(ListNode head) {//调用后tmp存储链表的倒叙
        if(head == null) return;//为递归终止条件
        recur(head.next);//递归
        tmp.add(head.val);//层层回溯时,将当前节点值加入列表
    }

2、给定单向链表的头指针和一个要删除的节点的值,定义一个函数删除该节点。

//双指针解决
1、特例处理: 当应删除头节点 head 时,直接返回 head.next 即可。
2、初始化: pre = head , cur = head.next 。
3、定位节点: 当 cur 为空 或 cur 节点值等于 val 时跳出。
保存当前节点索引,即 pre = cur 。
遍历下一节点,即 cur = cur.next 。
4、删除节点: 若 cur 指向某节点即不为空,则执行 pre.next = cur.next 。
若 cur 指向 null,代表链表中不包含值为 val 的节点。
5、返回值: 返回链表头部节点 head 即可。

 public static ListNode deleteNode(ListNode head, int val) {
        if(head.val == val) return head.next;
        ListNode pre = head, cur = head.next;
        while(cur != null && cur.val != val) {
            pre = cur;
            cur = cur.next;
        }
        if(cur != null) pre.next = cur.next;
        return head;
    }

3、删除链表的倒数第k个节点

第一时间想到的解法:
1、先遍历统计链表长度,记为 n ;
2、 设置一个指针走 (n-k) 步,即可找到链表倒数第k个节点。/
//双指针
/

1、初始化: 前指针 former 、后指针 latter ,双指针都指向头节点 head​ 。
2、构建双指针距离: 前指针 former 先向前走 k步(结束后,双指针 former 和 latter 间相距 k步)。
3、双指针共同移动: 循环中,双指针 former 和 latter 每轮都向前走一步,直至 former 走过链表 尾节点 时跳出
(跳出后, latter 与尾节点距离为 k-1,即 latter 指向倒数第 k个节点)。
4、返回值: 返回 latter 即可。

public static ListNode getKthFromEnd(ListNode head, int k){
        ListNode former=head,latter=head;
        for(int i=0;i<k;i++){
            former=former.next;
        }
        while (former!=null){
            former=former.next;
            latter=latter.next;
        }
        return latter;
    }

4、输入一个链表的头节点,反转该链表并输出反转后链表的头节点。

快慢指针解法
1、申请节点,pre和 cur,pre指向null,cur指向head
2、定义辅助节点temp,用于记录cur的下一个节点
3、只要cur不为空

1、记录当前节点的下一个节点 
2、然后将当前节点指向pre 
3、pre和cur节点都前进一位

4、返回pre

public ListNode reverseList(ListNode head) {
        ListNode cur=head;
        ListNode pre=null;
        ListNode temp=null;
        while(cur!=null){
            temp=cur.next;
            cur.next=pre;
            pre=cur;
            cur=temp;
        }
        return pre;
    }

5、合并两个有序的链表

1、定义一个新节点newNode
2、初始化一个伪头节点l3,节点l3指向newNode。
3、只要l1没到头并且l2也没到头
if(temp1.val<=temp2.val)
newNode.next=temp1;
temp1=temp1.next;
else:
newNode.next=temp2;
temp2=temp2.next;
4、if(temp2!=null)
newNode.next=temp2;
5、if(temp1!=null)
newNode.next=temp1;
6、return l3.next;

public static ListNode mergeTwoLists(ListNode l1, ListNode l2) {
        ListNode temp1=l1;
        ListNode temp2=l2;
        ListNode newNode = new ListNode(0);
        ListNode l3=newNode;
        while(temp1!=null&&temp2!=null){
            if(temp1.val<=temp2.val){
                newNode.next=temp1;
                temp1=temp1.next;
            }else{
                newNode.next=temp2;
                temp2=temp2.next;
            }
            newNode=newNode.next;
        }
        if(temp2!=null){
            newNode.next=temp2;
        }
        if(temp1!=null){
            newNode.next=temp1;
        }
        return l3.next;
    }

6、输入两个链表,找出它们的第一个公共节点。

双链指针同时移动,确保同时到链表尾
1、获取两个链表长度lengthA,lengthB;
2、定义两个辅助指针tempA和tempB分别指向headA和headB
3、首先让长的链表先走|lengthA-lengthB|步
4、然后二者同时走判断tempA.val==tempB.val,成立就返回

public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        int lengthA = getlength(headA), lengthB = getlength(headB);
        ListNode tempA = headA;
        ListNode tempB = headB;
        if (lengthA > lengthB) {
            for (int i = 0; i < lengthA - lengthB; i++) {
                tempA = tempA.next;
            }
        } else {
            for (int i = 0; i < lengthB - lengthA; i++) {
                tempA = tempA.next;
            }
        }
        while (tempA.val == tempB.val) {
            tempA = tempA.next;
            tempB = tempB.next;
        }
        return tempA;
    }
    private int getlength(ListNode head) {
        int count = 0;
        ListNode temp = head;
        while (head != null) {
            count++;
            temp = temp.next;
        }
        return count;
    }

7、实现一种算法,删除单向链表中间的某个节点(即不是第一个或最后一个节点),假定你只能访问该节点。
思路:
1、将下一个结点的值赋给当前节点,
2、当前节点的下一个结点为下下一个结点。

public void deleteNode(ListNode node) {
        node.val=node.next.val;
        node.next=node.next.next;
    }

8、编写一个函数,检查输入的链表是否是回文的。
将链表值放入双端队列,比较双端队列是否回文很简单

public static boolean isPalindrome(ListNode head) {
        if(head==null||head.next==null){
            return true;
        }
        LinkedList<Integer> list=new LinkedList<>();
        ListNode temp=head;
        while(temp!=null){//1、遍历链表,将其放入双端队列
            list.add(temp.val);
            temp=temp.next;
        }
        int left=0;
        int right=list.size()-1;
        while(left<right){//2、左右指针判断队列是否回文
            int a=list.get(left);
            int b=list.get(right);
            if(a!=b){
                return false;
            }
            left++;
            right--;
        }
        return true;
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值