链表题

学了链表,我把链表的相关题做了一下,并总结如下:

package InterviewImportant.DS;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

class ListNode{
    public int val;
    public ListNode next;

    public ListNode(int val) {
        this.val = val;
    }


}

public class MyList {


    //建表
    public static ListNode build1(){

        ListNode A = new ListNode(1);
        ListNode B = new ListNode(2);
        ListNode C = new ListNode(3);
        ListNode D = new ListNode(4);
        ListNode E = new ListNode(5);

        A.next = B;
        B.next = C;
        C.next = D;
        D.next = E;
        return A;
    }

    
    public static ListNode build(){

        ListNode A = new ListNode(3);
        ListNode B = new ListNode(6);
        ListNode C = new ListNode(8);
        ListNode D = new ListNode(9);
        ListNode E = new ListNode(12);

        A.next = B;
        B.next = C;
        C.next = D;
        D.next = B;
       // D.next = E;
        return A;
    }

    //打印链表
    public static void display(ListNode head){
        ListNode node = head;
        while (node != null) {
            System.out.print(node.val+" ");
            node = node.next;
        }
    }


    
    public static void main(String[] args) {
      //  display(build());
       // System.out.println();
     //   display(build1());
        //System.out.println();
        //display(deleteVal(build(),9));
        //display(reverse(build()));
        //display(midNode(build()));
        //display(kNode(build(),4));

       // display(mergeNode(build1(),build()));

        //System.out.println(isPalindromeList(build()));

        //display(separateList(build(),4));
        //display(deleteSameNode(build()));

        //display(shareNode(build1(),build()));
       // System.out.println(isHasCycle(build()));
        //display(detectCycle(build()));
       // display(firstCysleNode(build()));

        List list = generate(5);
        for (Object x:list){
            System.out.println(x);
        }

    }


    
    //删除给定值为data的所有节点
    public static ListNode deleteVal(ListNode head,int data){

        if (head == null) {
            return null;
        }


        ListNode prev = head;
        ListNode cur = head.next;


        while (cur != null) {
            if (cur.val == data) {
                prev.next = cur.next;
                cur = prev.next;

            }else {
                cur = cur.next;
                prev = prev.next;
            }

        }

        if (head.val == data) {
            head = head.next;
        }
        return head;
    }


    //反转单链表
    public static ListNode reverse(ListNode head){

        //如果链表为空或者只有一个节点,就返回它本身
        if (head == null||head.next==null) {
            return head;
        }

        ListNode Next =null;
        ListNode pre = null;


        while (head != null) {
            Next = head.next;
            head.next = pre;
            pre = head;
            head = Next;

        }

        return pre;
    }

    //返回链表的中间节点
    public static ListNode midNode(ListNode head){
        if (head == null) {
            return null;
        }
        //定义快慢节点,慢指针走一步,快指针走两步
        ListNode fast = head;
        ListNode slow = head;

        //当fast指向空时,slow指向的节点就是中间节点
        while (fast != null && fast.next != null) {
            fast = fast.next.next;
            slow = slow.next;
        }

        return slow;

    }

    //输入一个链表,输出该链表中倒数第k个结点。
    public static ListNode kNode(ListNode head,int k){
        if (k < 0) {
            return null;
        }

        ListNode slow = head;
        ListNode fast = head;

        while (k>0) {
            fast = fast.next;
            k--;
        }

        while (fast != null) {
            fast = fast.next;
            slow = slow.next;
        }

        return slow;
    }



   // 将两个有序链表合并为一个新的有序链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。
    public static ListNode mergeNode(ListNode l1,ListNode l2){
        ListNode newHead = new ListNode(-1);

        ListNode cur = newHead;

        if (l1 == null&&l2==null) {
            return null;
        }

        while (l1 != null && l2 != null) {
            if (l1.val <= l2.val) {
                cur.next = l1;
                l1 = l1.next;
                cur = cur.next;

            }else {
                cur.next = l2;
                l2 = l2.next;
                cur = cur.next;
            }
        }

        if (l1 != null) {
            cur.next = l1;
        }

        if (l2 != null) {
            cur.next = l2;
        }

        return newHead.next;
    }



    //链表的回文结构
    public static boolean isPalindromeList(ListNode head){

        ListNode slow = head;
        ListNode fast = head;
        //找到中点
        while (fast != null && fast.next != null) {
            fast = fast.next.next;
            slow = slow.next;
        }

        ListNode pre = null;
        ListNode Next = null;

        //将后半部分反转
        while (slow != null) {
            Next = slow.next;
            slow.next = pre;
            pre = slow;
            slow = Next;
        }

        //与前半部分进行比较
        while (pre != null) {
            if (pre.val == head.val) {
                pre= pre.next;
                head = head.next;
            }else {
                return false;
            }
        }
        return true;
    }


    //以给定值x为基准将链表分割成两部分,所有小于x的结点排在大于或等于x的结点之前
    public static ListNode separateList(ListNode head,int x){
       ListNode as = null;
       ListNode ae = null;
       ListNode bs = null;
       ListNode be = null;

       ListNode cur = head;
        while (cur != null) {
            if (cur.val < x) {
                if (as == null) {
                    as = cur;
                    ae = as;

                }else {
                    ae.next = cur;
                    ae = ae.next;

                }
            }
            if (cur.val >= x) {
                if (bs == null) {
                    bs = cur;
                    be = bs;

                }else {
                    be.next = cur;
                    be = be.next;
                }
            }
            cur = cur.next;
        }

        if (as!=null&&bs != null) {
            ae.next = bs;
            be.next = null;
        }

        if (as != null) {
            return as;
        }

        if (bs != null) {
            return bs;
        }
        return as;
    }


    // 在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针
    public static ListNode deleteSameNode(ListNode head){
        ListNode cur = head;
        if (cur == null || cur.next == null) {
            return cur;
        }

        while (cur != null&&cur.next!=null) {
            if (cur.val != cur.next.val) {
                cur = cur.next;
            }else {

                cur.next = cur.next.next;
            }
        }

        return head;
    }


    // 输入两个链表,找出它们的第一个公共结点
    public static ListNode shareNode(ListNode l1,ListNode l2){
        if (l1==null|| l2 == null) {
            return null;
        }

        ListNode cur1 = l1;
        ListNode cur2 = l2;

        ListNode cur = new ListNode(-1);
        ListNode newCur = cur;
        while (cur1 != null && cur2 != null) {
            if (cur1.val<cur2.val) {
                cur1 = cur1.next;

            } else if (cur1.val > cur2.val) {
                cur2 = cur2.next;
            }else {
                return cur1;
            }

        }
        return null;
    }



    //给定一个链表,判断链表中是否有环。
    //方法1:
    public static boolean isHasCycle(ListNode head){

        ListNode slow = head;
        ListNode fast = head;

        while (fast != null&&fast.next!=null) {
            fast = fast.next.next;
            slow = slow.next;
            if (fast == slow) {
                return true;
            }
        }

        return false;
    }


    /**
     *方法2:使用hashSet,遍历链表把链表的值添加进去,如果有相同的node说明有环
     *
     */
    public static boolean isHasCycle2(ListNode head){
        Set<ListNode> set = new HashSet<>();

        ListNode cur = head;
        while (cur != null) {
            if (!set.contains(cur)){
                set.add(cur);

            }else {
                return true;
            }

            cur = cur.next;
        }

        return false;

    }



    //给定一个链表,返回链表开始入环的第一个节点。
    public static ListNode firstCysleNode(ListNode head){

        ListNode fast = head;
        ListNode slow = head;

        while (fast != null&&fast.next!=null) {
            fast = fast.next.next;
            slow = slow.next;
            if (fast == slow) {
                break;
            }
        }
        if (fast == null || fast.next == null) {
            return null;
        }

        ListNode newhead = head;
        while (newhead != slow) {
            newhead = newhead.next;
            slow = slow.next;
        }

        return slow;
    }


    //杨辉三角的打印
    public static List<List<Integer>> generate(int numRows) {
        int[][] arr = new int[numRows][numRows];
        List<List<Integer>> list = new ArrayList<>();
        for (int i=0;i<numRows;i++){

            List<Integer> subList = new ArrayList<>();
            for (int j=0;j<=i;j++){
                if (j == 0 || i == j) {
                    arr[i][j] = 1;
                }else {
                    arr[i][j] = arr[i-1][j-1]+arr[i-1][j];

                }
                subList.add(arr[i][j]);

            }
            list.add(subList);

        }

        return list;


    }



    // 实现每次反转k个链表直到结尾
    public static ListNode reverseK(ListNode head,int k){
        ListNode newHead = new ListNode(-1);
        newHead.next = head;
        ListNode start = head;
        ListNode  end = newHead;
        ListNode l = newHead;
        ListNode n = start;

        while (end != null) {
            int count =0;
            //找到第k个节点
            while (end.next != null && count < k) {
                end = end.next;
                count++;
            }

            //如果后续节点不足k个,则不需要反转
            if (count != k) {
                break;
            }

            l.next = end;

            //尾插法实现反转
            for (int i=0;i<k-1;i++){
                ListNode temp = start.next;
                start.next = end.next;
                end.next = start;
                start = temp;

            }

            l = n;
            end = n;
            n = n.next;
            start = n;

        }
        return newHead.next;

    }



}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值