剑指刷题记录1:list

题1:从尾到头打印数据

思路一:利用list中的add(index,value)

import java.util.ArrayList;
public class Solution {
    public ArrayList<Integer> printListFromTailToHead(ListNode listNode) {
        ArrayList<Integer> list = new ArrayList<>();
        ListNode tmp = listNode;
        while (tmp!=null)
        {
            list.add(0,tmp.val);
            tmp = tmp.next;
        }
        return list;
    }
}

思路二:利用递归

public class Solution {
    ArrayList list = new ArrayList();
    public ArrayList printListFromTailToHead(ListNode listNode) {
        if(listNode!=null){
            printListFromTailToHead(listNode.next);
            list.add(listNode.val);
        }
        return list;
    }
}

思路三:栈

import java.util.Stack;
public class Solution{
    public ArrayList<Integer> printListFromTailToHead(ListNode listNode) {
       Stack<Integer> sc = new Stack<>(); //栈是先进后出
       while(listNode != null){ //若当前ListNode类对象不为空
           sc.push(listNode.val);//则将当前对象的头节点存入栈中
           listNode = listNode.next; //将当前对象的下一个节点对象赋给listNode对象,对象传对象
       }
        ArrayList<Integer> list = new ArrayList<>();
        while(!sc.isEmpty()){  //若当前的栈内存不为空
            list.add(sc.pop());//出栈,先进后出,即先输出后进来的
        }
        return list;
    }
}

题2:输入链表中倒数第k个数字

思路一:快慢指针

class Solution:
    def FindKthToTail(self, head, k):
        # write code here
        if head==None or k<=0:
            return None
        #设置两个指针,p2指针先走(k-1)步,然后再一起走,当p2为最后一个时,p1就为倒数第k个 数
        p2=head
        p1=head
        #p2先走,走k-1步,如果k大于链表长度则返回 空,否则的话继续走
        while k>1:
            if p2.next!=None:
                p2=p2.next
                k-=1
            else:
                return None
#两个指针一起 走,一直到p2为最后一个,p1即为所求
        while p2.next!=None:
            p1=p1.next
            p2=p2.next
        return p1

思路二:栈 pop第n个

import java.util.Stack;
public class Solution {
    public ListNode FindKthToTail(ListNode head,int k) {
       if(head == null || k ==0 ){
            return null;
            }
        //可以先把链表反转,然后找出第k个
        Stack<ListNode> stack = new Stack<ListNode>();
        int count = 0;
        while(head != null){
            stack.push(head);
            head = head.next;
            count++;
        }
        if(count < k){
            return null;
        }
        ListNode knode = null;
        for(int i = 0; i < k; i++){
            knode = stack.pop();
        }
        return knode;
    }
    }

题3:反转链表

思路一:两个指针循环在链表滑动

(注意考虑链表只要一个值或者空的特殊情况)
在这里插入图片描述

public class Solution {
    public ListNode ReverseList(ListNode head) {
        ListNode newHead = null;
        ListNode currentHead = head;
        if(head == null || head.next == null){
            return head;
        }
 
        while(currentHead != null){
            ListNode next = currentHead.next;
            currentHead.next = newHead;
            newHead = currentHead;
            currentHead = next;
        }

题4:合并两个有序链表并排序

思路1:如图

在这里插入图片描述

public class Solution {
    public ListNode Merge(ListNode list1,ListNode list2) {
        if (list1 == null){
            return list2;
        }
        if (list2 == null){
            return list1;
        }
        ListNode res = null;
        if(list1.val < list2.val){
            res = list1;
            res.next = Merge(list1.next, list2);
        }
        else{
            res = list2;
            res.next = Merge(list2.next, list1);
        }
        return res;
    }
}

题5 复杂链表的复制

思路一:复制 分割

在这里插入图片描述

public class Solution {
    public RandomListNode Clone(RandomListNode pHead)
    {
        if (pHead == null){
            return null;
        } 
        //复制节点
        RandomListNode currentnode = pHead;
        while(currentnode!= null){
            RandomListNode clonenode = new RandomListNode(currentnode.label);
            clonenode.next = currentnode.next;
            currentnode.next = clonenode;
            currentnode = clonenode.next;
        }
        //复制random指针
        currentnode = pHead;
        while(currentnode != null){
            if(currentnode.random!=null){
                currentnode.next.random = currentnode.random.next;
            }
            currentnode = currentnode.next.next;
        }
        //分割
        RandomListNode head =pHead.next;
        RandomListNode tmp = head;
        currentnode = pHead;
        while(currentnode.next!=null){
            tmp = currentnode.next;
            currentnode.next = tmp.next;
            currentnode = tmp;
        }
        return head;
    }
}

思路二:hashmap

remain

题6 删除链表重复的节点

remain

题7 求两个链表第一个公共节点

在这里插入图片描述

public class Solution {
    public ListNode FindFirstCommonNode(ListNode pHead1, ListNode pHead2) {
        if (pHead1 == null || pHead2 == null){return null;}
        ListNode p1 = pHead1;
        ListNode p2 = pHead2;
        while(p1 != p2){
            p1 = p1.next;
            p2 = p2.next;
            if(p1 != p2){
                if(p1 == null) p1=pHead2;
                if(p2 == null) p2=pHead1;
            }
        }
        return p1;
}
}

题8 链表中环的入口节点

思路:1.判断链表中有环 -> 2.得到环中节点的数目 -> 3.找到环中的入口节点

/*
 public class ListNode {
    int val;
    ListNode next = null;

    ListNode(int val) {
        this.val = val;
    }
}
*/
public class Solution {
    public ListNode EntryNodeOfLoop(ListNode pHead)
    {
        if(pHead == null){return null;}
        ListNode l = pHead;
        ListNode r = pHead;
        boolean flag = false;
        //判断是否有环;
        while(r!=null && r.next!=null){
            l=l.next;
            r=r.next.next;
            if(l == r){
                flag = true;
                break;
            }
        }
            if(!flag){
                return null;
            }
            //环的节点数
            else{
                int n=1;
                r=r.next;
                while(l!=r){
                    r=r.next;
                    n++;
                }
                ListNode l1=pHead;
                ListNode r1=pHead;
                for(int i=0; i<n; i++){
                    r1=r1.next;
                }
                while(l1 != r1){
                    l1 = l1.next;
                    r1 = r1.next;
                }
                return l1;
            }
        }
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值